From 01dcbbcd5368ea8de7845e041953a564d4567326 Mon Sep 17 00:00:00 2001 From: Alex Janka Date: Tue, 25 Apr 2023 10:08:22 +1000 Subject: [PATCH] tile window shows gbc sprites --- gb-emu/src/window.rs | 26 +++--- lib/src/connect/mod.rs | 4 + lib/src/processor/memory/mmio/gpu.rs | 11 +-- .../processor/memory/mmio/gpu/tile_window.rs | 80 +++++++++++++++++-- 4 files changed, 101 insertions(+), 20 deletions(-) diff --git a/gb-emu/src/window.rs b/gb-emu/src/window.rs index 01297f3..cbda981 100644 --- a/gb-emu/src/window.rs +++ b/gb-emu/src/window.rs @@ -17,6 +17,7 @@ pub struct WindowRenderer { gamepad_handler: Option, joypad_state: JoypadState, current_rumble: bool, + position: Option<(isize, isize)>, } impl WindowRenderer { @@ -30,6 +31,7 @@ impl WindowRenderer { gamepad_handler, joypad_state: JoypadState::default(), current_rumble: false, + position: None, } } } @@ -38,20 +40,26 @@ impl Renderer for WindowRenderer { fn prepare(&mut self, width: usize, height: usize) { self.width = width; self.height = height; - self.window = Some( - Window::new( - "Gameboy", - width * self.factor, - height * self.factor, - WindowOptions::default(), - ) - .unwrap(), - ); + + let mut w = Window::new( + "Gameboy", + width * self.factor, + height * self.factor, + WindowOptions::default(), + ) + .unwrap(); + + if let Some((x, y)) = self.position { + w.set_position(x, y); + } + + self.window = Some(w); } fn display(&mut self, buffer: &[u32]) { if let Some(ref mut window) = self.window { self.scaled_buf = scale_buffer(buffer, self.width, self.height, self.factor); + self.position = Some(window.get_position()); window .update_with_buffer( &self.scaled_buf, diff --git a/lib/src/connect/mod.rs b/lib/src/connect/mod.rs index e76b7fc..1128992 100644 --- a/lib/src/connect/mod.rs +++ b/lib/src/connect/mod.rs @@ -26,6 +26,10 @@ pub enum RomFile { pub trait Renderer> { fn prepare(&mut self, width: usize, height: usize); + fn resize(&mut self, width: usize, height: usize) { + self.prepare(width, height) + } + fn display(&mut self, buffer: &[Format]); fn set_title(&mut self, _title: String) {} diff --git a/lib/src/processor/memory/mmio/gpu.rs b/lib/src/processor/memory/mmio/gpu.rs index f18a948..55d301b 100644 --- a/lib/src/processor/memory/mmio/gpu.rs +++ b/lib/src/processor/memory/mmio/gpu.rs @@ -127,8 +127,7 @@ where { pub fn new(cgb: bool, window: R, tile_window_renderer: Option) -> Self { let tile_window = if let Some(mut tile_window_renderer) = tile_window_renderer { - tile_window_renderer.prepare(TILE_WINDOW_WIDTH, TILE_WINDOW_HEIGHT); - Some(TileWindow::new(tile_window_renderer)) + Some(TileWindow::new(tile_window_renderer, cgb)) } else { None }; @@ -166,9 +165,11 @@ where window: R, tile_window_renderer: Option, ) -> Self { - let tile_window = if let Some(mut tile_window_renderer) = tile_window_renderer { - tile_window_renderer.prepare(TILE_WINDOW_WIDTH, TILE_WINDOW_HEIGHT); - Some(TileWindow::new(tile_window_renderer)) + let tile_window = if let Some(tile_window_renderer) = tile_window_renderer { + Some(TileWindow::new( + tile_window_renderer, + state.cgb_data.is_some(), + )) } else { None }; diff --git a/lib/src/processor/memory/mmio/gpu/tile_window.rs b/lib/src/processor/memory/mmio/gpu/tile_window.rs index d64bb3a..e1cc220 100644 --- a/lib/src/processor/memory/mmio/gpu/tile_window.rs +++ b/lib/src/processor/memory/mmio/gpu/tile_window.rs @@ -5,7 +5,7 @@ use crate::{ }; use super::{ - types::{BgAttributes, ColourInner, Vram}, + types::{BgAttributes, ColourInner, Vram, VramBank}, Colour, }; @@ -16,6 +16,7 @@ where { sprite_buffer: Vec, sprite_renderer: R, + currently_cgb: bool, } impl TileWindow @@ -23,13 +24,20 @@ where ColourFormat: From + Clone, R: Renderer, { - pub(super) fn new(window: R) -> Self { + pub(super) fn new(mut window: R, cgb: bool) -> Self { + let current_width = if cgb { + TILE_WINDOW_WIDTH * 2 + } else { + TILE_WINDOW_WIDTH + }; + window.prepare(current_width, TILE_WINDOW_HEIGHT); Self { sprite_buffer: vec![ ColourInner::Error.rgb_bytes(None, false).into(); - TILE_WINDOW_WIDTH * TILE_WINDOW_HEIGHT + current_width * TILE_WINDOW_HEIGHT ], sprite_renderer: window, + currently_cgb: cgb, } } @@ -39,6 +47,20 @@ where memory: &Vram, is_cgb_mode: bool, ) { + if self.currently_cgb != is_cgb_mode { + self.currently_cgb = is_cgb_mode; + let current_width = if is_cgb_mode { + TILE_WINDOW_WIDTH * 2 + } else { + TILE_WINDOW_WIDTH + }; + self.sprite_renderer + .resize(current_width, TILE_WINDOW_HEIGHT); + self.sprite_buffer = vec![ + ColourInner::Error.rgb_bytes(None, false).into(); + current_width * TILE_WINDOW_HEIGHT + ]; + } for tile_y in 0..16 { self.draw_row( tile_y, @@ -63,7 +85,6 @@ where self.sprite_renderer.display(&self.sprite_buffer); } - #[allow(clippy::too_many_arguments)] fn draw_row( &mut self, tile_y: u8, @@ -72,11 +93,58 @@ where palette: Palette, memory: &Vram, is_cgb_mode: bool, + ) { + let line_width = if is_cgb_mode { + TILE_WINDOW_WIDTH * 2 + } else { + TILE_WINDOW_WIDTH + }; + self.draw_row_from_bank( + tile_y, + display_y, + area, + palette, + memory, + is_cgb_mode, + VramBank::Bank0, + 0, + line_width, + ); + if is_cgb_mode { + self.draw_row_from_bank( + tile_y, + display_y, + area, + palette, + memory, + is_cgb_mode, + VramBank::Bank1, + TILE_WINDOW_WIDTH, + line_width, + ); + } + } + + #[allow(clippy::too_many_arguments)] + fn draw_row_from_bank( + &mut self, + tile_y: u8, + display_y: usize, + area: TiledataArea, + palette: Palette, + memory: &Vram, + is_cgb_mode: bool, + bank: VramBank, + offset: usize, + line_width: usize, ) { for tile_x in 0..16 { let tile_num = (tile_y * 16) + tile_x; let data_begin = area.get_addr(tile_num); - let attributes = BgAttributes::default(); + let attributes = BgAttributes { + tile_bank: bank, + ..Default::default() + }; for px_y in 0..8_u16 { let lsbs = memory @@ -99,7 +167,7 @@ where palette.map_bits(lsb, msb).0 }; - self.sprite_buffer[real_px_x + (real_px_y * TILE_WINDOW_WIDTH)] = + self.sprite_buffer[offset + real_px_x + (real_px_y * line_width)] = colour.rgb_bytes(None, is_cgb_mode).into(); } }