Optimize emulator frame loop
Syncronize to number of cycles performed instead of VCOUNT when emulating a frame Former-commit-id: 0f9afe6a95a576dbb7a15cd1bf6bfb7d7ce02fff
This commit is contained in:
parent
ff95b67ae1
commit
8f8204a52b
|
@ -24,6 +24,8 @@ pub struct GameBoyAdvance {
|
||||||
pub input_device: Rc<RefCell<dyn InputInterface>>,
|
pub input_device: Rc<RefCell<dyn InputInterface>>,
|
||||||
|
|
||||||
pub cycles_to_next_event: usize,
|
pub cycles_to_next_event: usize,
|
||||||
|
|
||||||
|
overshoot_cycles: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
|
@ -58,6 +60,7 @@ impl GameBoyAdvance {
|
||||||
input_device: input_device,
|
input_device: input_device,
|
||||||
|
|
||||||
cycles_to_next_event: 1,
|
cycles_to_next_event: 1,
|
||||||
|
overshoot_cycles: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
gba.sysbus.created();
|
gba.sysbus.created();
|
||||||
|
@ -93,12 +96,20 @@ impl GameBoyAdvance {
|
||||||
|
|
||||||
pub fn frame(&mut self) {
|
pub fn frame(&mut self) {
|
||||||
self.key_poll();
|
self.key_poll();
|
||||||
while self.sysbus.io.gpu.vcount != DISPLAY_HEIGHT {
|
|
||||||
self.step();
|
let mut remaining_cycles = 280896 - self.overshoot_cycles;
|
||||||
|
|
||||||
|
while remaining_cycles > 0 {
|
||||||
|
let cycles = self.step();
|
||||||
|
if remaining_cycles >= cycles {
|
||||||
|
remaining_cycles -= cycles;
|
||||||
|
} else {
|
||||||
|
self.overshoot_cycles = cycles - remaining_cycles;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
while self.sysbus.io.gpu.vcount == DISPLAY_HEIGHT {
|
|
||||||
self.step();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.overshoot_cycles = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_breakpoint(&mut self, addr: u32) -> Option<usize> {
|
pub fn add_breakpoint(&mut self, addr: u32) -> Option<usize> {
|
||||||
|
@ -137,7 +148,7 @@ impl GameBoyAdvance {
|
||||||
self.cpu.cycles - previous_cycles
|
self.cpu.cycles - previous_cycles
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn step(&mut self) {
|
pub fn step(&mut self) -> usize {
|
||||||
// I hate myself for doing this, but rust left me no choice.
|
// I hate myself for doing this, but rust left me no choice.
|
||||||
let io = unsafe {
|
let io = unsafe {
|
||||||
let ptr = &mut *self.sysbus as *mut SysBus;
|
let ptr = &mut *self.sysbus as *mut SysBus;
|
||||||
|
@ -162,7 +173,7 @@ impl GameBoyAdvance {
|
||||||
} else {
|
} else {
|
||||||
io.dmac.perform_work(&mut self.sysbus, &mut irqs);
|
io.dmac.perform_work(&mut self.sysbus, &mut irqs);
|
||||||
io.intc.request_irqs(irqs);
|
io.intc.request_irqs(irqs);
|
||||||
return;
|
return cycles;
|
||||||
};
|
};
|
||||||
|
|
||||||
cycles += _cycles;
|
cycles += _cycles;
|
||||||
|
@ -174,7 +185,7 @@ impl GameBoyAdvance {
|
||||||
|
|
||||||
// update gpu & sound
|
// update gpu & sound
|
||||||
io.timers.update(cycles, &mut self.sysbus, &mut irqs);
|
io.timers.update(cycles, &mut self.sysbus, &mut irqs);
|
||||||
io.gpu.step(
|
io.gpu.update(
|
||||||
cycles,
|
cycles,
|
||||||
&mut self.sysbus,
|
&mut self.sysbus,
|
||||||
&mut irqs,
|
&mut irqs,
|
||||||
|
@ -185,6 +196,8 @@ impl GameBoyAdvance {
|
||||||
.update(cycles, &mut cycles_to_next_event, &self.audio_device);
|
.update(cycles, &mut cycles_to_next_event, &self.audio_device);
|
||||||
self.cycles_to_next_event = cycles_to_next_event;
|
self.cycles_to_next_event = cycles_to_next_event;
|
||||||
io.intc.request_irqs(irqs);
|
io.intc.request_irqs(irqs);
|
||||||
|
|
||||||
|
cycles
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Query the emulator for the recently drawn framebuffer.
|
/// Query the emulator for the recently drawn framebuffer.
|
||||||
|
|
|
@ -451,7 +451,7 @@ impl Gpu {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the new gpu state
|
// Returns the new gpu state
|
||||||
pub fn step(
|
pub fn update(
|
||||||
&mut self,
|
&mut self,
|
||||||
cycles: usize,
|
cycles: usize,
|
||||||
sb: &mut SysBus,
|
sb: &mut SysBus,
|
||||||
|
|
|
@ -42,7 +42,7 @@ impl Target for GameBoyAdvance {
|
||||||
|
|
||||||
if self.cycles_to_next_event <= unsafe { S_TOTAL_CYCLES } {
|
if self.cycles_to_next_event <= unsafe { S_TOTAL_CYCLES } {
|
||||||
let mut cycles_to_next_event = std::usize::MAX;
|
let mut cycles_to_next_event = std::usize::MAX;
|
||||||
io.gpu.step(
|
io.gpu.update(
|
||||||
unsafe { S_TOTAL_CYCLES },
|
unsafe { S_TOTAL_CYCLES },
|
||||||
&mut self.sysbus,
|
&mut self.sysbus,
|
||||||
&mut irqs,
|
&mut irqs,
|
||||||
|
|
Reference in a new issue