diff --git a/src/core/gpu/mod.rs b/src/core/gpu/mod.rs index e4e5647..97c8f3d 100644 --- a/src/core/gpu/mod.rs +++ b/src/core/gpu/mod.rs @@ -8,6 +8,7 @@ use crate::num::FromPrimitive; mod mosaic; mod obj; +use obj::ObjInfo; mod sfx; pub mod regs; @@ -82,31 +83,6 @@ impl Default for GpuState { } use GpuState::*; -pub struct FrameBuffer([u32; DISPLAY_WIDTH * DISPLAY_HEIGHT]); - -impl fmt::Debug for FrameBuffer { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "FrameBuffer: ")?; - for i in 0..6 { - write!(f, "#{:06x}, ", self[i])?; - } - write!(f, "...") - } -} - -impl std::ops::Index for FrameBuffer { - type Output = u32; - fn index(&self, index: usize) -> &Self::Output { - &self.0[index] - } -} - -impl std::ops::IndexMut for FrameBuffer { - fn index_mut(&mut self, index: usize) -> &mut Self::Output { - &mut self.0[index] - } -} - #[derive(Copy, Clone)] pub struct Scanline([T; DISPLAY_WIDTH]); @@ -200,7 +176,7 @@ pub struct BgAffine { pub y: i32, } -#[derive(Debug)] +#[derive(DebugStub)] pub struct Gpu { pub state: GpuState, cycles: usize, @@ -223,9 +199,11 @@ pub struct Gpu { pub bldalpha: BlendAlpha, pub bldy: u16, - pub obj_line: Scanline, - pub obj_line_priorities: Scanline, - pub frame_buffer: FrameBuffer, + #[debug_stub = "Sprite Buffer"] + pub obj_buffer: [ObjInfo; DISPLAY_WIDTH], + + #[debug_stub = "Frame Buffer"] + pub frame_buffer: [u32; DISPLAY_WIDTH * DISPLAY_HEIGHT], } impl Gpu { @@ -247,9 +225,8 @@ impl Gpu { state: HDraw, vcount: 0, cycles: 0, - obj_line: Scanline::default(), - obj_line_priorities: Scanline([3; DISPLAY_WIDTH]), - frame_buffer: FrameBuffer([0; DISPLAY_WIDTH * DISPLAY_HEIGHT]), + obj_buffer: [Default::default(); DISPLAY_WIDTH], + frame_buffer: [0; DISPLAY_WIDTH * DISPLAY_HEIGHT], } } @@ -293,7 +270,7 @@ impl Gpu { } fn render_pixel(&mut self, x: i32, y: i32, p: Rgb15) { - self.frame_buffer.0[index2d!(usize, x, y, DISPLAY_WIDTH)] = p.to_rgb24(); + self.frame_buffer[index2d!(usize, x, y, DISPLAY_WIDTH)] = p.to_rgb24(); } fn scanline_reg_bg(&mut self, bg: usize, sb: &mut SysBus) { @@ -446,13 +423,12 @@ impl Gpu { self.mosaic_sfx(); let post_sfx_line = self.composite_sfx(sb); for x in 0..DISPLAY_WIDTH { - self.frame_buffer.0[x + self.vcount * DISPLAY_WIDTH] = - post_sfx_line[x].to_rgb24(); + self.frame_buffer[x + self.vcount * DISPLAY_WIDTH] = post_sfx_line[x].to_rgb24(); } } pub fn get_framebuffer(&self) -> &[u32] { - &self.frame_buffer.0 + &self.frame_buffer } fn update_vcount(&mut self, value: usize, irqs: &mut IrqBitmask) { diff --git a/src/core/gpu/obj.rs b/src/core/gpu/obj.rs index 88502db..e051a6b 100644 --- a/src/core/gpu/obj.rs +++ b/src/core/gpu/obj.rs @@ -145,7 +145,7 @@ impl Gpu { if screen_x >= screen_width { break; } - if self.obj_line_priorities[screen_x as usize] <= obj.2.priority() { + if self.obj_buffer[screen_x as usize].priority <= obj.2.priority() { continue; } @@ -169,8 +169,9 @@ impl Gpu { let pixel_color = self.get_palette_color(sb, pixel_index as u32, palette_bank, PALRAM_OFS_FG); if pixel_color != Rgb15::TRANSPARENT { - self.obj_line[screen_x as usize] = pixel_color; - self.obj_line_priorities[screen_x as usize] = obj.2.priority(); + let mut current_obj = &mut self.obj_buffer[screen_x as usize]; + current_obj.color = pixel_color; + current_obj.priority = obj.2.priority(); } } } @@ -216,7 +217,7 @@ impl Gpu { if screen_x >= screen_width { break; } - if self.obj_line_priorities[screen_x as usize] <= obj.2.priority() { + if self.obj_buffer[screen_x as usize].priority <= obj.2.priority() { continue; } let mut sprite_y = screen_y - ref_y; @@ -240,16 +241,16 @@ impl Gpu { let pixel_color = self.get_palette_color(sb, pixel_index as u32, palette_bank, PALRAM_OFS_FG); if pixel_color != Rgb15::TRANSPARENT { - self.obj_line[screen_x as usize] = pixel_color; - self.obj_line_priorities[screen_x as usize] = obj.2.priority(); + let mut current_obj = &mut self.obj_buffer[screen_x as usize]; + current_obj.color = pixel_color; + current_obj.priority = obj.2.priority(); } } } pub fn render_objs(&mut self, sb: &SysBus) { // reset the scanline - self.obj_line = Scanline::default(); - self.obj_line_priorities = Scanline([3; DISPLAY_WIDTH]); + self.obj_buffer = [Default::default(); DISPLAY_WIDTH]; for obj_num in 0..128 { let obj = read_obj_attrs(sb, obj_num); match obj.0.objtype() { @@ -263,8 +264,25 @@ impl Gpu { } } +#[derive(Debug, Copy, Clone)] +pub struct ObjInfo { + pub(super) color: Rgb15, + pub(super) priority: u16, + pub(super) mode: ObjMode, +} + +impl Default for ObjInfo { + fn default() -> ObjInfo { + ObjInfo { + mode: ObjMode::Normal, + color: Rgb15::TRANSPARENT, + priority: 3, + } + } +} + #[derive(Debug, Primitive, Copy, Clone, PartialEq)] -enum ObjMode { +pub enum ObjMode { Normal = 0b00, Sfx = 0b01, Window = 0b10, diff --git a/src/core/gpu/sfx.rs b/src/core/gpu/sfx.rs index c194a9d..6bca754 100644 --- a/src/core/gpu/sfx.rs +++ b/src/core/gpu/sfx.rs @@ -51,11 +51,11 @@ impl Gpu { 'outer: for priority in 0..4 { if bflags.contains(BlendFlags::OBJ) && wflags.contains(WindowFlags::OBJ) - && !self.obj_line[screen_x].is_transparent() - && self.obj_line_priorities[screen_x] == priority + && !self.obj_buffer[screen_x].color.is_transparent() + && self.obj_buffer[screen_x].priority == priority { return Some(Layer { - color: self.obj_line[screen_x], + color: self.obj_buffer[screen_x].color, blend_flag: BlendFlags::OBJ, }); } @@ -75,9 +75,10 @@ impl Gpu { } } } + let backdrop = sb.palette_ram.read_16(0); if bflags.contains(BlendFlags::BACKDROP) { return Some(Layer { - color: Rgb15(sb.palette_ram.read_16(0)), + color: Rgb15(backdrop), blend_flag: BlendFlags::BACKDROP, }); }