tile window shows gbc sprites

This commit is contained in:
Alex Janka 2023-04-25 10:08:22 +10:00
parent 59d52ee92f
commit 01dcbbcd53
4 changed files with 101 additions and 20 deletions

View file

@ -17,6 +17,7 @@ pub struct WindowRenderer {
gamepad_handler: Option<Gilrs>, gamepad_handler: Option<Gilrs>,
joypad_state: JoypadState, joypad_state: JoypadState,
current_rumble: bool, current_rumble: bool,
position: Option<(isize, isize)>,
} }
impl WindowRenderer { impl WindowRenderer {
@ -30,6 +31,7 @@ impl WindowRenderer {
gamepad_handler, gamepad_handler,
joypad_state: JoypadState::default(), joypad_state: JoypadState::default(),
current_rumble: false, current_rumble: false,
position: None,
} }
} }
} }
@ -38,20 +40,26 @@ impl Renderer<u32> for WindowRenderer {
fn prepare(&mut self, width: usize, height: usize) { fn prepare(&mut self, width: usize, height: usize) {
self.width = width; self.width = width;
self.height = height; self.height = height;
self.window = Some(
Window::new( let mut w = Window::new(
"Gameboy", "Gameboy",
width * self.factor, width * self.factor,
height * self.factor, height * self.factor,
WindowOptions::default(), WindowOptions::default(),
) )
.unwrap(), .unwrap();
);
if let Some((x, y)) = self.position {
w.set_position(x, y);
}
self.window = Some(w);
} }
fn display(&mut self, buffer: &[u32]) { fn display(&mut self, buffer: &[u32]) {
if let Some(ref mut window) = self.window { if let Some(ref mut window) = self.window {
self.scaled_buf = scale_buffer(buffer, self.width, self.height, self.factor); self.scaled_buf = scale_buffer(buffer, self.width, self.height, self.factor);
self.position = Some(window.get_position());
window window
.update_with_buffer( .update_with_buffer(
&self.scaled_buf, &self.scaled_buf,

View file

@ -26,6 +26,10 @@ pub enum RomFile {
pub trait Renderer<Format: From<Colour>> { pub trait Renderer<Format: From<Colour>> {
fn prepare(&mut self, width: usize, height: usize); 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 display(&mut self, buffer: &[Format]);
fn set_title(&mut self, _title: String) {} fn set_title(&mut self, _title: String) {}

View file

@ -127,8 +127,7 @@ where
{ {
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>) -> Self {
let tile_window = if let Some(mut tile_window_renderer) = tile_window_renderer { 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, cgb))
Some(TileWindow::new(tile_window_renderer))
} else { } else {
None None
}; };
@ -166,9 +165,11 @@ where
window: R, window: R,
tile_window_renderer: Option<R>, tile_window_renderer: Option<R>,
) -> Self { ) -> Self {
let tile_window = if let Some(mut tile_window_renderer) = tile_window_renderer { let tile_window = if let Some(tile_window_renderer) = tile_window_renderer {
tile_window_renderer.prepare(TILE_WINDOW_WIDTH, TILE_WINDOW_HEIGHT); Some(TileWindow::new(
Some(TileWindow::new(tile_window_renderer)) tile_window_renderer,
state.cgb_data.is_some(),
))
} else { } else {
None None
}; };

View file

@ -5,7 +5,7 @@ use crate::{
}; };
use super::{ use super::{
types::{BgAttributes, ColourInner, Vram}, types::{BgAttributes, ColourInner, Vram, VramBank},
Colour, Colour,
}; };
@ -16,6 +16,7 @@ where
{ {
sprite_buffer: Vec<ColourFormat>, sprite_buffer: Vec<ColourFormat>,
sprite_renderer: R, sprite_renderer: R,
currently_cgb: bool,
} }
impl<ColourFormat, R> TileWindow<ColourFormat, R> impl<ColourFormat, R> TileWindow<ColourFormat, R>
@ -23,13 +24,20 @@ where
ColourFormat: From<Colour> + Clone, ColourFormat: From<Colour> + Clone,
R: Renderer<ColourFormat>, R: Renderer<ColourFormat>,
{ {
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 { Self {
sprite_buffer: vec![ sprite_buffer: vec![
ColourInner::Error.rgb_bytes(None, false).into(); ColourInner::Error.rgb_bytes(None, false).into();
TILE_WINDOW_WIDTH * TILE_WINDOW_HEIGHT current_width * TILE_WINDOW_HEIGHT
], ],
sprite_renderer: window, sprite_renderer: window,
currently_cgb: cgb,
} }
} }
@ -39,6 +47,20 @@ where
memory: &Vram, memory: &Vram,
is_cgb_mode: bool, 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 { for tile_y in 0..16 {
self.draw_row( self.draw_row(
tile_y, tile_y,
@ -63,7 +85,6 @@ where
self.sprite_renderer.display(&self.sprite_buffer); self.sprite_renderer.display(&self.sprite_buffer);
} }
#[allow(clippy::too_many_arguments)]
fn draw_row( fn draw_row(
&mut self, &mut self,
tile_y: u8, tile_y: u8,
@ -72,11 +93,58 @@ where
palette: Palette, palette: Palette,
memory: &Vram, memory: &Vram,
is_cgb_mode: bool, 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 { for tile_x in 0..16 {
let tile_num = (tile_y * 16) + tile_x; let tile_num = (tile_y * 16) + tile_x;
let data_begin = area.get_addr(tile_num); 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 { for px_y in 0..8_u16 {
let lsbs = memory let lsbs = memory
@ -99,7 +167,7 @@ where
palette.map_bits(lsb, msb).0 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(); colour.rgb_bytes(None, is_cgb_mode).into();
} }
} }