Dirty bit detection for Video RAM
The DMD library now keeps track of when writes to video RAM occur, and sets a dirty bit. This dirty bit is reset when the video RAM is requested by the library user, and can be used to avoid repainting when video ram has not changed.
This commit is contained in:
parent
03d0d36061
commit
31f1008458
36
src/bus.rs
36
src/bus.rs
|
@ -63,6 +63,7 @@ pub struct Bus {
|
|||
vid: Mem, // TODO: Figure out what device this really is
|
||||
bbram: Mem, // TODO: change to BBRAM when implemented
|
||||
ram: Mem,
|
||||
video_ram_dirty: bool,
|
||||
}
|
||||
|
||||
impl Bus {
|
||||
|
@ -74,6 +75,7 @@ impl Bus {
|
|||
vid: Mem::new(0x500000, 0x2, false),
|
||||
bbram: Mem::new(0x600000, 0x2000, false),
|
||||
ram: Mem::new(0x700000, mem_size, false),
|
||||
video_ram_dirty: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,6 +107,18 @@ impl Bus {
|
|||
Err(BusError::NoDevice(address))
|
||||
}
|
||||
|
||||
fn video_ram_range(&self) -> Range<usize> {
|
||||
let vid_register = (u16::from(self.vid[0]) << 8 | u16::from(self.vid[1])) as usize;
|
||||
let start = vid_register * 4;
|
||||
let end = start + 0x19000;
|
||||
start..end
|
||||
}
|
||||
|
||||
fn is_video_ram(&self, address: usize) -> bool {
|
||||
(0x700000..0x800000).contains(&address)
|
||||
&& self.video_ram_range().contains(&(address - 0x700000))
|
||||
}
|
||||
|
||||
pub fn read_byte(&mut self, address: usize, access: AccessCode) -> Result<u8, BusError> {
|
||||
self.get_device(address)?.read_byte(address, access)
|
||||
}
|
||||
|
@ -140,6 +154,9 @@ impl Bus {
|
|||
}
|
||||
|
||||
pub fn write_byte(&mut self, address: usize, val: u8) -> Result<(), BusError> {
|
||||
if self.is_video_ram(address) {
|
||||
self.video_ram_dirty = true;
|
||||
}
|
||||
self.get_device(address)?.write_byte(address, val, AccessCode::Write)
|
||||
}
|
||||
|
||||
|
@ -147,6 +164,9 @@ impl Bus {
|
|||
if address & 1 != 0 {
|
||||
return Err(BusError::Alignment(address));
|
||||
}
|
||||
if self.is_video_ram(address) {
|
||||
self.video_ram_dirty = true;
|
||||
}
|
||||
self.get_device(address)?.write_half(address, val, AccessCode::Write)
|
||||
}
|
||||
|
||||
|
@ -154,6 +174,9 @@ impl Bus {
|
|||
if address & 3 != 0 {
|
||||
return Err(BusError::Alignment(address));
|
||||
}
|
||||
if self.is_video_ram(address) {
|
||||
self.video_ram_dirty = true;
|
||||
}
|
||||
self.get_device(address)?.write_word(address, val, AccessCode::Write)
|
||||
}
|
||||
|
||||
|
@ -161,11 +184,14 @@ impl Bus {
|
|||
self.get_device(address)?.load(address, data)
|
||||
}
|
||||
|
||||
pub fn video_ram(&self) -> &[u8] {
|
||||
let vid_register = (u16::from(self.vid[0]) << 8 | u16::from(self.vid[1])) as usize;
|
||||
let start = vid_register * 4;
|
||||
let end = start + 0x19000;
|
||||
self.ram.as_slice(start..end)
|
||||
pub fn video_ram(&mut self) -> &[u8] {
|
||||
self.video_ram_dirty = false;
|
||||
let range = self.video_ram_range();
|
||||
self.ram.as_slice(range)
|
||||
}
|
||||
|
||||
pub fn video_ram_dirty(&self) -> bool {
|
||||
self.video_ram_dirty
|
||||
}
|
||||
|
||||
pub fn service(&mut self) {
|
||||
|
|
19
src/dmd.rs
19
src/dmd.rs
|
@ -64,10 +64,14 @@ impl Dmd {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn video_ram(&self) -> &[u8] {
|
||||
pub fn video_ram(&mut self) -> &[u8] {
|
||||
self.bus.video_ram()
|
||||
}
|
||||
|
||||
pub fn video_ram_dirty(&self) -> bool {
|
||||
self.bus.video_ram_dirty()
|
||||
}
|
||||
|
||||
pub fn get_pc(&self) -> u32 {
|
||||
self.cpu.get_pc()
|
||||
}
|
||||
|
@ -167,11 +171,22 @@ fn dmd_init(version: u8) -> c_int {
|
|||
#[no_mangle]
|
||||
fn dmd_video_ram() -> *const u8 {
|
||||
match DMD.lock() {
|
||||
Ok(dmd) => dmd.video_ram().as_ptr(),
|
||||
Ok(mut dmd) => dmd.video_ram().as_ptr(),
|
||||
Err(_) => ptr::null(),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
fn dmd_video_ram_dirty() -> c_int {
|
||||
match DMD.lock() {
|
||||
Ok(dmd) => match dmd.video_ram_dirty() {
|
||||
true => 1,
|
||||
false => 0,
|
||||
},
|
||||
Err(_) => 0,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
fn dmd_step() -> c_int {
|
||||
match DMD.lock() {
|
||||
|
|
Loading…
Reference in New Issue