diff --git a/src/core/graphics/gpu.rs b/src/core/graphics/gpu.rs index cc88040c..55128b9e 100644 --- a/src/core/graphics/gpu.rs +++ b/src/core/graphics/gpu.rs @@ -12,7 +12,6 @@ use crate::core::CpuType::ARM9; use crate::logging::debug_println; use bilge::prelude::*; use std::intrinsics::unlikely; -use std::ptr; use std::ptr::NonNull; use std::sync::atomic::{AtomicU16, Ordering}; use std::sync::Arc; @@ -171,15 +170,15 @@ impl Gpu { gpu.v_count += 1; match gpu.v_count { 192 => { - let pow_cnt1 = PowCnt1::from(gpu.pow_cnt1); - let gpu_3d_regs_ptr = ptr::addr_of_mut!(gpu.gpu_3d_regs); - gpu.get_renderer_mut().on_scanline_finish(get_mem_mut!(emu), pow_cnt1, unsafe { gpu_3d_regs_ptr.as_mut_unchecked() }); - - if gpu.gpu_3d_regs.flushed { - gpu.gpu_3d_regs.swap_buffers(); + let gpu_3d_regs = &mut get_common_mut!(emu).gpu.gpu_3d_regs; + if gpu_3d_regs.flushed { + gpu_3d_regs.swap_buffers(); gpu.get_renderer_mut().renderer_3d.invalidate(); } + let pow_cnt1 = PowCnt1::from(gpu.pow_cnt1); + gpu.get_renderer_mut().on_scanline_finish(get_mem_mut!(emu), pow_cnt1, gpu_3d_regs); + for i in 0..2 { let disp_stat = &mut gpu.disp_stat[i]; disp_stat.set_v_blank_flag(u1::new(1)); diff --git a/src/core/graphics/gpu_mem_buf.rs b/src/core/graphics/gpu_mem_buf.rs index cf6d6550..2b7da646 100644 --- a/src/core/graphics/gpu_mem_buf.rs +++ b/src/core/graphics/gpu_mem_buf.rs @@ -1,9 +1,16 @@ use crate::core::memory::mem::Memory; +use crate::core::memory::vram::VramMaps; use crate::core::memory::{regions, vram}; use crate::utils::HeapMemU8; +use std::ptr::NonNull; +use std::slice; #[derive(Default)] pub struct GpuMemBuf { + vram_maps: VramMaps, + pub palettes_ptr: Option>, + pub oam_ptr: Option>, + pub lcdc: HeapMemU8<{ vram::TOTAL_SIZE }>, pub bg_a: HeapMemU8<{ vram::BG_A_SIZE as usize }>, @@ -26,36 +33,55 @@ pub struct GpuMemBuf { } impl GpuMemBuf { - pub fn read_2d(&mut self, mem: &mut Memory, read_lcdc: bool) { + pub fn set_vram_maps(&mut self, vram_maps: VramMaps) { + self.vram_maps = vram_maps; + } + + pub fn set_palettes_oam(&mut self, mem: &mut Memory) { + if mem.palettes.dirty { + self.palettes_ptr = NonNull::new(mem.palettes.mem.as_mut_ptr()); + mem.palettes.dirty = false; + } else { + self.palettes_ptr = None; + } + if mem.oam.dirty { + self.oam_ptr = NonNull::new(mem.oam.mem.as_mut_ptr()); + mem.oam.dirty = false; + } else { + self.oam_ptr = None; + } + } + + pub fn read_2d(&mut self, read_lcdc: bool) { if read_lcdc { - mem.vram.read_all_lcdc(&mut self.lcdc); + self.vram_maps.read_all_lcdc(&mut self.lcdc); } - mem.vram.read_all_bg_a(&mut self.bg_a); - mem.vram.read_all_obj_a(&mut self.obj_a); - mem.vram.read_all_bg_a_ext_palette(&mut self.bg_a_ext_palette); - mem.vram.read_all_obj_a_ext_palette(&mut self.obj_a_ext_palette); + self.vram_maps.read_all_bg_a(&mut self.bg_a); + self.vram_maps.read_all_obj_a(&mut self.obj_a); + self.vram_maps.read_all_bg_a_ext_palette(&mut self.bg_a_ext_palette); + self.vram_maps.read_all_obj_a_ext_palette(&mut self.obj_a_ext_palette); - mem.vram.read_bg_b(&mut self.bg_b); - mem.vram.read_all_obj_b(&mut self.obj_b); - mem.vram.read_all_bg_b_ext_palette(&mut self.bg_b_ext_palette); - mem.vram.read_all_obj_b_ext_palette(&mut self.obj_b_ext_palette); + self.vram_maps.read_bg_b(&mut self.bg_b); + self.vram_maps.read_all_obj_b(&mut self.obj_b); + self.vram_maps.read_all_bg_b_ext_palette(&mut self.bg_b_ext_palette); + self.vram_maps.read_all_obj_b_ext_palette(&mut self.obj_b_ext_palette); - if mem.palettes.dirty { - mem.palettes.dirty = false; - self.pal_a.copy_from_slice(&mem.palettes.mem[..mem.palettes.mem.len() / 2]); - self.pal_b.copy_from_slice(&mem.palettes.mem[mem.palettes.mem.len() / 2..]); + if let Some(ptr) = self.palettes_ptr { + let slice = unsafe { slice::from_raw_parts(ptr.as_ptr(), regions::STANDARD_PALETTES_SIZE as usize) }; + self.pal_a.copy_from_slice(&slice[..regions::STANDARD_PALETTES_SIZE as usize / 2]); + self.pal_b.copy_from_slice(&slice[regions::STANDARD_PALETTES_SIZE as usize / 2..]); } - if mem.oam.dirty { - mem.oam.dirty = false; - self.oam_a.copy_from_slice(&mem.oam.mem[..mem.oam.mem.len() / 2]); - self.oam_b.copy_from_slice(&mem.oam.mem[mem.oam.mem.len() / 2..]); + if let Some(ptr) = self.oam_ptr { + let slice = unsafe { slice::from_raw_parts(ptr.as_ptr(), regions::OAM_SIZE as usize) }; + self.oam_a.copy_from_slice(&slice[..regions::OAM_SIZE as usize / 2]); + self.oam_b.copy_from_slice(&slice[regions::OAM_SIZE as usize / 2..]); } } - pub fn read_3d(&mut self, mem: &mut Memory) { - mem.vram.read_all_tex_rear_plane_img(&mut self.tex_rear_plane_image); - mem.vram.read_all_tex_palette(&mut self.tex_pal); + pub fn read_3d(&mut self) { + self.vram_maps.read_all_tex_rear_plane_img(&mut self.tex_rear_plane_image); + self.vram_maps.read_all_tex_palette(&mut self.tex_pal); } } diff --git a/src/core/graphics/gpu_renderer.rs b/src/core/graphics/gpu_renderer.rs index 144d665c..a19147db 100644 --- a/src/core/graphics/gpu_renderer.rs +++ b/src/core/graphics/gpu_renderer.rs @@ -74,12 +74,13 @@ impl GpuRenderer { self.common.pow_cnt1 = pow_cnt1; self.renderer_2d.on_scanline_finish(); - self.common.mem_buf.read_2d(mem, self.renderer_2d.has_vram_display[0]); + self.common.mem_buf.set_vram_maps(mem.vram.maps.clone()); + self.common.mem_buf.set_palettes_oam(mem); + mem.vram.maps.undirty(self.renderer_2d.has_vram_display[0]); if self.renderer_3d.dirty { self.renderer_3d.finish_scanline(registers_3d); self.renderer_3d.dirty = false; self.rendering_3d = true; - self.common.mem_buf.read_3d(mem); } *rendering = true; @@ -123,6 +124,9 @@ impl GpuRenderer { ); }; + self.common.mem_buf.read_2d(self.renderer_2d.has_vram_display[0]); + self.common.mem_buf.read_3d(); + if self.rendering_3d { self.rendering_3d = false; self.renderer_3d.render(&self.common); diff --git a/src/core/memory/vram.rs b/src/core/memory/vram.rs index df71f19a..a2de7355 100644 --- a/src/core/memory/vram.rs +++ b/src/core/memory/vram.rs @@ -195,7 +195,6 @@ impl OverlapSection Default for OverlapSection where [(); SIZE / CHUNK_SIZE]:, @@ -266,6 +266,12 @@ where } } + fn undirty(&mut self) { + for s in &mut self.sections { + s.set_dirty(false); + } + } + fn add(&mut self, map: VramMap, offset: usize) { for i in 0..(MAP_SIZE / CHUNK_SIZE) { self.sections[offset + i].add(map.extract_section::(i)) @@ -324,6 +330,17 @@ where } } +impl Default for OverlapMapping +where + [(); SIZE / CHUNK_SIZE]:, +{ + fn default() -> Self { + OverlapMapping { + sections: [OverlapSection::default(); SIZE / CHUNK_SIZE], + } + } +} + #[bitsize(8)] #[derive(FromBits)] struct VramCnt { @@ -397,6 +414,7 @@ pub const OBJ_B_OFFSET: u32 = 0x600000; pub const ARM7_SIZE: u32 = 128 * 1024; +#[derive(Clone, Default)] pub struct VramMaps { lcdc: OverlapMapping, @@ -415,25 +433,6 @@ pub struct VramMaps { } impl VramMaps { - fn new() -> Self { - VramMaps { - lcdc: OverlapMapping::new(), - - bg_a: OverlapMapping::new(), - obj_a: OverlapMapping::new(), - bg_ext_palette_a: [VramMap::default(); 4], - obj_ext_palette_a: VramMap::default(), - - tex_rear_plane_img: [VramMap::default(); 4], - tex_palette: [VramMap::default(); 6], - - bg_b: OverlapMapping::new(), - obj_b: OverlapMapping::new(), - bg_ext_palette_b: [VramMap::default(); 4], - obj_ext_palette_b: VramMap::default(), - } - } - fn reset(&mut self) { self.lcdc.reset(); self.bg_a.reset(); @@ -447,13 +446,133 @@ impl VramMaps { self.bg_ext_palette_b.fill(VramMap::default()); self.obj_ext_palette_b = VramMap::default(); } + + pub fn undirty(&mut self, include_lcdc: bool) { + if include_lcdc { + self.lcdc.undirty(); + } + self.bg_a.undirty(); + self.obj_a.undirty(); + for map in &mut self.bg_ext_palette_a { + map.set_dirty(false); + } + self.obj_ext_palette_a.set_dirty(false); + for map in &mut self.tex_rear_plane_img { + map.set_dirty(false); + } + for map in &mut self.tex_palette { + map.set_dirty(false); + } + self.bg_b.undirty(); + self.obj_b.undirty(); + for map in &mut self.bg_ext_palette_b { + map.set_dirty(false); + } + self.obj_ext_palette_b.set_dirty(false); + } + + pub fn read_all_lcdc(&mut self, buf: &mut [u8; TOTAL_SIZE]) { + self.lcdc.read_all(0, buf) + } + + pub fn read_all_bg_a(&mut self, buf: &mut [u8; BG_A_SIZE as usize]) { + self.bg_a.read_all(0, buf) + } + + pub fn read_all_obj_a(&mut self, buf: &mut [u8; OBJ_A_SIZE as usize]) { + self.obj_a.read_all(0, buf) + } + + pub fn read_all_bg_a_ext_palette(&mut self, buf: &mut [u8; BG_EXT_PAL_SIZE as usize]) { + for i in 0..self.bg_ext_palette_a.len() { + let map = &mut self.bg_ext_palette_a[i]; + if map.is_dirty() { + let buf = &mut buf[i << 13..(i << 13) + 8 * 1024]; + if !map.is_null() { + buf.copy_from_slice(map); + } else { + buf.fill(0); + } + } + } + } + + pub fn read_all_obj_a_ext_palette(&mut self, buf: &mut [u8; OBJ_EXT_PAL_SIZE as usize]) { + if self.obj_ext_palette_a.is_dirty() { + if !self.obj_ext_palette_a.is_null() { + buf.copy_from_slice(&self.obj_ext_palette_a); + } else { + buf.fill(0); + } + } + } + + pub fn read_bg_b(&mut self, buf: &mut [u8; BG_B_SIZE as usize]) { + self.bg_b.read_all(0, buf) + } + + pub fn read_all_obj_b(&mut self, buf: &mut [u8; OBJ_B_SIZE as usize]) { + self.obj_b.read_all(0, buf) + } + + pub fn read_all_bg_b_ext_palette(&mut self, buf: &mut [u8; BG_EXT_PAL_SIZE as usize]) { + for i in 0..self.bg_ext_palette_b.len() { + let map = &mut self.bg_ext_palette_b[i]; + if map.is_dirty() { + let buf = &mut buf[i << 13..(i << 13) + 8 * 1024]; + if !map.is_null() { + buf.copy_from_slice(map); + } else { + buf.fill(0); + } + } + } + } + + pub fn read_all_obj_b_ext_palette(&mut self, buf: &mut [u8; OBJ_EXT_PAL_SIZE as usize]) { + if self.obj_ext_palette_b.is_dirty() { + if !self.obj_ext_palette_b.is_null() { + buf.copy_from_slice(&self.obj_ext_palette_b); + } else { + buf.fill(0); + } + } + } + + pub fn read_all_tex_rear_plane_img(&mut self, buf: &mut [u8; TEX_REAR_PLANE_IMAGE_SIZE as usize]) { + for i in 0..self.tex_rear_plane_img.len() { + let map = &mut self.tex_rear_plane_img[i]; + if map.is_dirty() { + let buf = &mut buf[i << 17..(i << 17) + 128 * 1024]; + if !map.is_null() { + buf.copy_from_slice(map); + } else { + buf.fill(0); + } + } + } + } + + pub fn read_all_tex_palette(&mut self, buf: &mut [u8; TEX_PAL_SIZE as usize]) { + for i in 0..self.tex_palette.len() { + let map = &mut self.tex_palette[i]; + if map.is_dirty() { + let buf = &mut buf[i << 14..(i << 14) + 16 * 1024]; + if !map.is_null() { + buf.copy_from_slice(map); + } else { + buf.fill(0); + } + } + } + } } pub struct Vram { pub stat: u8, pub cnt: [u8; BANK_SIZE], banks: VramBanks, - maps: VramMaps, + pub maps: VramMaps, arm7: OverlapMapping<{ 128 * 2 * 1024 }, { ARM7_SIZE as usize }, 2>, } @@ -465,7 +584,7 @@ impl Vram { stat: 0, cnt: [0u8; BANK_SIZE], banks, - maps: VramMaps::new(), + maps: VramMaps::default(), arm7: OverlapMapping::new(), } } @@ -822,106 +941,4 @@ impl Vram { ARM7 => self.arm7.write_slice(addr_offset, slice), }; } - - pub fn read_all_lcdc(&mut self, buf: &mut [u8; TOTAL_SIZE]) { - self.maps.lcdc.read_all(0, buf) - } - - pub fn read_all_bg_a(&mut self, buf: &mut [u8; BG_A_SIZE as usize]) { - self.maps.bg_a.read_all(0, buf) - } - - pub fn read_all_obj_a(&mut self, buf: &mut [u8; OBJ_A_SIZE as usize]) { - self.maps.obj_a.read_all(0, buf) - } - - pub fn read_all_bg_a_ext_palette(&mut self, buf: &mut [u8; BG_EXT_PAL_SIZE as usize]) { - for i in 0..self.maps.bg_ext_palette_a.len() { - let map = &mut self.maps.bg_ext_palette_a[i]; - if map.is_dirty() { - let buf = &mut buf[i << 13..(i << 13) + 8 * 1024]; - if !map.is_null() { - buf.copy_from_slice(map); - } else { - buf.fill(0); - } - map.set_dirty(false); - } - } - } - - pub fn read_all_obj_a_ext_palette(&mut self, buf: &mut [u8; OBJ_EXT_PAL_SIZE as usize]) { - if self.maps.obj_ext_palette_a.is_dirty() { - if !self.maps.obj_ext_palette_a.is_null() { - buf.copy_from_slice(&self.maps.obj_ext_palette_a); - } else { - buf.fill(0); - } - self.maps.obj_ext_palette_a.set_dirty(false); - } - } - - pub fn read_bg_b(&mut self, buf: &mut [u8; BG_B_SIZE as usize]) { - self.maps.bg_b.read_all(0, buf) - } - - pub fn read_all_obj_b(&mut self, buf: &mut [u8; OBJ_B_SIZE as usize]) { - self.maps.obj_b.read_all(0, buf) - } - - pub fn read_all_bg_b_ext_palette(&mut self, buf: &mut [u8; BG_EXT_PAL_SIZE as usize]) { - for i in 0..self.maps.bg_ext_palette_b.len() { - let map = &mut self.maps.bg_ext_palette_b[i]; - if map.is_dirty() { - let buf = &mut buf[i << 13..(i << 13) + 8 * 1024]; - if !map.is_null() { - buf.copy_from_slice(map); - } else { - buf.fill(0); - } - map.set_dirty(false); - } - } - } - - pub fn read_all_obj_b_ext_palette(&mut self, buf: &mut [u8; OBJ_EXT_PAL_SIZE as usize]) { - if self.maps.obj_ext_palette_b.is_dirty() { - if !self.maps.obj_ext_palette_b.is_null() { - buf.copy_from_slice(&self.maps.obj_ext_palette_b); - } else { - buf.fill(0); - } - self.maps.obj_ext_palette_b.set_dirty(false); - } - } - - pub fn read_all_tex_rear_plane_img(&mut self, buf: &mut [u8; TEX_REAR_PLANE_IMAGE_SIZE as usize]) { - for i in 0..self.maps.tex_rear_plane_img.len() { - let map = &mut self.maps.tex_rear_plane_img[i]; - if map.is_dirty() { - let buf = &mut buf[i << 17..(i << 17) + 128 * 1024]; - if !map.is_null() { - buf.copy_from_slice(map); - } else { - buf.fill(0); - } - map.set_dirty(false); - } - } - } - - pub fn read_all_tex_palette(&mut self, buf: &mut [u8; TEX_PAL_SIZE as usize]) { - for i in 0..self.maps.tex_palette.len() { - let map = &mut self.maps.tex_palette[i]; - if map.is_dirty() { - let buf = &mut buf[i << 14..(i << 14) + 16 * 1024]; - if !map.is_null() { - buf.copy_from_slice(map); - } else { - buf.fill(0); - } - map.set_dirty(false); - } - } - } } diff --git a/src/main.rs b/src/main.rs index bf351049..124ae730 100644 --- a/src/main.rs +++ b/src/main.rs @@ -320,7 +320,6 @@ pub fn main() { .unwrap(); } -// Must be pub for vita pub fn actual_main() { if cfg!(target_os = "vita") { set_thread_prio_affinity(ThreadPriority::High, ThreadAffinity::Core1);