add layer window
This commit is contained in:
parent
2685bc06e6
commit
b0a5373ff6
6 changed files with 82 additions and 25 deletions
|
@ -54,9 +54,13 @@ struct Args {
|
||||||
hex: bool,
|
hex: bool,
|
||||||
|
|
||||||
/// Show tile window
|
/// Show tile window
|
||||||
#[arg(short, long)]
|
#[arg(long)]
|
||||||
tile_window: bool,
|
tile_window: bool,
|
||||||
|
|
||||||
|
/// Show layer window
|
||||||
|
#[arg(long)]
|
||||||
|
layer_window: bool,
|
||||||
|
|
||||||
/// Scale display by...
|
/// Scale display by...
|
||||||
#[arg(short, long)]
|
#[arg(short, long)]
|
||||||
scale_factor: Option<usize>,
|
scale_factor: Option<usize>,
|
||||||
|
@ -122,12 +126,19 @@ impl EmulatorHandler {
|
||||||
let mut window_manager = WindowManager::new(sender);
|
let mut window_manager = WindowManager::new(sender);
|
||||||
|
|
||||||
let window = window_manager.add(factor, Some(Gilrs::new().unwrap()));
|
let window = window_manager.add(factor, Some(Gilrs::new().unwrap()));
|
||||||
|
|
||||||
let tile_window: Option<WindowRenderer> = if args.tile_window {
|
let tile_window: Option<WindowRenderer> = if args.tile_window {
|
||||||
Some(window_manager.add(factor, None))
|
Some(window_manager.add(factor, None))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let layer_window: Option<WindowRenderer> = if args.layer_window {
|
||||||
|
Some(window_manager.add(1, None))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
let options = EmulatorOptions::new(window, rom, output)
|
let options = EmulatorOptions::new(window, rom, output)
|
||||||
.with_save_path(args.save)
|
.with_save_path(args.save)
|
||||||
.with_serial_target(if args.ascii {
|
.with_serial_target(if args.ascii {
|
||||||
|
@ -149,6 +160,7 @@ impl EmulatorHandler {
|
||||||
)
|
)
|
||||||
.with_no_save(args.no_save)
|
.with_no_save(args.no_save)
|
||||||
.with_tile_window(tile_window)
|
.with_tile_window(tile_window)
|
||||||
|
.with_layer_window(layer_window)
|
||||||
.with_cgb_mode(!args.dmg);
|
.with_cgb_mode(!args.dmg);
|
||||||
|
|
||||||
// let core: Box<dyn EmulatorCoreTrait> = if args.camera {
|
// let core: Box<dyn EmulatorCoreTrait> = if args.camera {
|
||||||
|
|
|
@ -116,6 +116,7 @@ impl WindowRenderer {
|
||||||
) -> (Self, WindowInfo) {
|
) -> (Self, WindowInfo) {
|
||||||
let window = WindowBuilder::new()
|
let window = WindowBuilder::new()
|
||||||
.with_title("Gameboy")
|
.with_title("Gameboy")
|
||||||
|
.with_resizable(false)
|
||||||
.build(event_loop)
|
.build(event_loop)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
|
@ -164,6 +164,7 @@ where
|
||||||
{
|
{
|
||||||
pub(crate) window: R,
|
pub(crate) window: R,
|
||||||
pub(crate) tile_window: Option<R>,
|
pub(crate) tile_window: Option<R>,
|
||||||
|
pub(crate) layer_window: Option<R>,
|
||||||
pub(crate) rom: RomFile,
|
pub(crate) rom: RomFile,
|
||||||
pub(crate) output: AudioOutput,
|
pub(crate) output: AudioOutput,
|
||||||
pub(crate) save: Option<SramType>,
|
pub(crate) save: Option<SramType>,
|
||||||
|
@ -185,6 +186,7 @@ where
|
||||||
Self {
|
Self {
|
||||||
window,
|
window,
|
||||||
tile_window: None,
|
tile_window: None,
|
||||||
|
layer_window: None,
|
||||||
rom,
|
rom,
|
||||||
output,
|
output,
|
||||||
save: None,
|
save: None,
|
||||||
|
@ -238,6 +240,11 @@ where
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_layer_window(mut self, window: Option<R>) -> Self {
|
||||||
|
self.layer_window = window;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn with_cgb_mode(mut self, cgb_mode: bool) -> Self {
|
pub fn with_cgb_mode(mut self, cgb_mode: bool) -> Self {
|
||||||
self.cgb_mode = cgb_mode;
|
self.cgb_mode = cgb_mode;
|
||||||
self
|
self
|
||||||
|
|
|
@ -130,6 +130,7 @@ where
|
||||||
options.output,
|
options.output,
|
||||||
options.serial_target,
|
options.serial_target,
|
||||||
options.tile_window,
|
options.tile_window,
|
||||||
|
options.layer_window,
|
||||||
camera,
|
camera,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -119,6 +119,7 @@ where
|
||||||
audio: AudioOutput,
|
audio: AudioOutput,
|
||||||
serial_target: SerialTarget,
|
serial_target: SerialTarget,
|
||||||
tile_window: Option<R>,
|
tile_window: Option<R>,
|
||||||
|
layer_window: Option<R>,
|
||||||
camera: CameraWrapperRef<C>,
|
camera: CameraWrapperRef<C>,
|
||||||
_phantom: PhantomData<ColourFormat>,
|
_phantom: PhantomData<ColourFormat>,
|
||||||
}
|
}
|
||||||
|
@ -134,6 +135,7 @@ where
|
||||||
audio: AudioOutput,
|
audio: AudioOutput,
|
||||||
serial_target: SerialTarget,
|
serial_target: SerialTarget,
|
||||||
tile_window: Option<R>,
|
tile_window: Option<R>,
|
||||||
|
layer_window: Option<R>,
|
||||||
camera: CameraWrapperRef<C>,
|
camera: CameraWrapperRef<C>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -141,6 +143,7 @@ where
|
||||||
audio,
|
audio,
|
||||||
serial_target,
|
serial_target,
|
||||||
tile_window,
|
tile_window,
|
||||||
|
layer_window,
|
||||||
camera,
|
camera,
|
||||||
_phantom: PhantomData,
|
_phantom: PhantomData,
|
||||||
}
|
}
|
||||||
|
@ -170,7 +173,7 @@ where
|
||||||
user_mode: false,
|
user_mode: false,
|
||||||
oam_dma: OamDma::default(),
|
oam_dma: OamDma::default(),
|
||||||
joypad: Joypad::default(),
|
joypad: Joypad::default(),
|
||||||
gpu: Gpu::new(cgb, output.window, output.tile_window),
|
gpu: Gpu::new(cgb, output.window, output.tile_window, output.layer_window),
|
||||||
apu: Apu::new(output.audio),
|
apu: Apu::new(output.audio),
|
||||||
serial: Serial::new(output.serial_target),
|
serial: Serial::new(output.serial_target),
|
||||||
timers: Timer::init(),
|
timers: Timer::init(),
|
||||||
|
|
|
@ -40,6 +40,7 @@ where
|
||||||
scanline: u8,
|
scanline: u8,
|
||||||
lyc: u8,
|
lyc: u8,
|
||||||
tile_window: Option<TileWindow<ColourFormat, R>>,
|
tile_window: Option<TileWindow<ColourFormat, R>>,
|
||||||
|
layer_window: Option<(R, Vec<ColourFormat>)>,
|
||||||
window_lc: u8,
|
window_lc: u8,
|
||||||
has_window_been_enabled: bool,
|
has_window_been_enabled: bool,
|
||||||
bg_palette: Palette,
|
bg_palette: Palette,
|
||||||
|
@ -58,17 +59,30 @@ where
|
||||||
ColourFormat: From<Colour> + Clone,
|
ColourFormat: From<Colour> + Clone,
|
||||||
R: Renderer<ColourFormat>,
|
R: Renderer<ColourFormat>,
|
||||||
{
|
{
|
||||||
pub fn new(cgb: bool, window: R, tile_window_renderer: Option<R>) -> Self {
|
pub fn new(
|
||||||
|
cgb: bool,
|
||||||
|
window: R,
|
||||||
|
tile_window_renderer: Option<R>,
|
||||||
|
layer_window_renderer: Option<R>,
|
||||||
|
) -> Self {
|
||||||
let tile_window = tile_window_renderer
|
let tile_window = tile_window_renderer
|
||||||
.map(|tile_window_renderer| TileWindow::new(tile_window_renderer, cgb));
|
.map(|tile_window_renderer| TileWindow::new(tile_window_renderer, cgb));
|
||||||
let buffer = vec![
|
|
||||||
if cgb {
|
let blank_colour: ColourFormat = if cgb {
|
||||||
rgb_from_bytes(0xFFFF).into()
|
rgb_from_bytes(0xFFFF).into()
|
||||||
} else {
|
} else {
|
||||||
ColourInner::Error.rgb_bytes(None).into()
|
ColourInner::Error.rgb_bytes(None).into()
|
||||||
};
|
};
|
||||||
WIDTH * HEIGHT
|
|
||||||
];
|
let buffer = vec![blank_colour.clone(); WIDTH * HEIGHT];
|
||||||
|
|
||||||
|
let layer_window = layer_window_renderer.map(|mut layer_window_renderer| {
|
||||||
|
layer_window_renderer.prepare(WIDTH, HEIGHT * 3);
|
||||||
|
(
|
||||||
|
layer_window_renderer,
|
||||||
|
vec![blank_colour; WIDTH * HEIGHT * 3],
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
buffer,
|
buffer,
|
||||||
|
@ -83,6 +97,7 @@ where
|
||||||
scanline: 0,
|
scanline: 0,
|
||||||
lyc: 0xFF,
|
lyc: 0xFF,
|
||||||
tile_window,
|
tile_window,
|
||||||
|
layer_window,
|
||||||
window_lc: 0,
|
window_lc: 0,
|
||||||
has_window_been_enabled: false,
|
has_window_been_enabled: false,
|
||||||
bg_palette: Palette::from_byte(0xFC),
|
bg_palette: Palette::from_byte(0xFC),
|
||||||
|
@ -361,12 +376,6 @@ where
|
||||||
}
|
}
|
||||||
let x_coord = x_coord_uncorrected - 8;
|
let x_coord = x_coord_uncorrected - 8;
|
||||||
if x_coord < WIDTH {
|
if x_coord < WIDTH {
|
||||||
let buffer_index = (scanline as usize * WIDTH) + x_coord;
|
|
||||||
if (!object.flags.behind_bg_and_window && !self.is_bg_priority[x_coord])
|
|
||||||
|| self.is_bg_zero[x_coord]
|
|
||||||
|| (self.is_cgb_mode() && !self.lcdc.bg_window_enable)
|
|
||||||
|| obj_priority
|
|
||||||
{
|
|
||||||
let cgb_data = self.cgb_data.as_ref().map(|v| {
|
let cgb_data = self.cgb_data.as_ref().map(|v| {
|
||||||
(
|
(
|
||||||
&v.palettes.obj,
|
&v.palettes.obj,
|
||||||
|
@ -378,8 +387,17 @@ where
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let buffer_index = (scanline as usize * WIDTH) + x_coord;
|
||||||
|
if (!object.flags.behind_bg_and_window && !self.is_bg_priority[x_coord])
|
||||||
|
|| self.is_bg_zero[x_coord]
|
||||||
|
|| (self.is_cgb_mode() && !self.lcdc.bg_window_enable)
|
||||||
|
|| obj_priority
|
||||||
|
{
|
||||||
self.buffer[buffer_index] = colour.rgb_bytes(cgb_data).into();
|
self.buffer[buffer_index] = colour.rgb_bytes(cgb_data).into();
|
||||||
}
|
}
|
||||||
|
if let Some((_, ref mut buffer)) = self.layer_window {
|
||||||
|
buffer[buffer_index + (2 * HEIGHT * WIDTH)] = colour.rgb_bytes(cgb_data).into();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -391,17 +409,17 @@ where
|
||||||
tilemap: TilemapArea,
|
tilemap: TilemapArea,
|
||||||
offset_x: u8,
|
offset_x: u8,
|
||||||
offset_y: u8,
|
offset_y: u8,
|
||||||
wrap: bool,
|
is_bg: bool,
|
||||||
) {
|
) {
|
||||||
let (tile_line_y, did_wrap_y) = draw_from.overflowing_sub(offset_y);
|
let (tile_line_y, did_wrap_y) = draw_from.overflowing_sub(offset_y);
|
||||||
if did_wrap_y && !wrap {
|
if did_wrap_y && !is_bg {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let tilemap_row = tile_line_y / 8;
|
let tilemap_row = tile_line_y / 8;
|
||||||
let row_addr = ((tilemap_row as usize * 32) % 0x400) as u16;
|
let row_addr = ((tilemap_row as usize * 32) % 0x400) as u16;
|
||||||
for x in 0..WIDTH {
|
for x in 0..WIDTH {
|
||||||
let (tile_line_x, did_wrap_x) = (x as u8).overflowing_sub(offset_x);
|
let (tile_line_x, did_wrap_x) = (x as u8).overflowing_sub(offset_x);
|
||||||
if did_wrap_x && !wrap {
|
if did_wrap_x && !is_bg {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -460,10 +478,25 @@ where
|
||||||
.map(|v| (&v.palettes.bg, attributes.palette));
|
.map(|v| (&v.palettes.bg, attributes.palette));
|
||||||
|
|
||||||
self.buffer[(scanline as usize * WIDTH) + x] = colour.rgb_bytes(cgb_data).into();
|
self.buffer[(scanline as usize * WIDTH) + x] = colour.rgb_bytes(cgb_data).into();
|
||||||
|
if let Some((_, ref mut buffer)) = self.layer_window {
|
||||||
|
buffer[(scanline as usize * WIDTH) + x + if is_bg { 0 } else { HEIGHT * WIDTH }] =
|
||||||
|
colour.rgb_bytes(cgb_data).into();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_window(&mut self) {
|
fn render_window(&mut self) {
|
||||||
self.window.display(&self.buffer);
|
self.window.display(&self.buffer);
|
||||||
|
if let Some((ref mut window, ref mut buffer)) = self.layer_window {
|
||||||
|
window.display(buffer);
|
||||||
|
let blank_colour: ColourFormat = if self.cgb_data.is_some() {
|
||||||
|
rgb_from_bytes(0xFFFF).into()
|
||||||
|
} else {
|
||||||
|
ColourInner::Error.rgb_bytes(None).into()
|
||||||
|
};
|
||||||
|
for val in buffer {
|
||||||
|
*val = blank_colour.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue