From ed030082cde2a5a7431d55f6007d54d33e07bf01 Mon Sep 17 00:00:00 2001 From: transistor Date: Mon, 20 Dec 2021 20:41:25 -0800 Subject: [PATCH] Finally fixed the animation speed in sonic 2 It turned out to be an issue with the interrupts and when the vertical interrupt was triggered vs when the vertical blanking bit was set. The interrupt code in sonic 2 tries to read the status bit after the vint occurs, and if the vblank bit is set, it runs the Vint_Level function, but the hacky code I wrote turned the vblanking bit on after 14ms and off when it triggered the vint, instead of turning it on at 15ms, and off at 1.2ms, with the int occuring at the *start* of the time the blanking bit is set. So the code had been waiting for 14ms after the vint until it actually started processing thing, which didn't complete before the next vint, so it only ran the main game loop every 33.2ms which is why doubling the speed of the simulated execution time made it seem about the right speed --- src/peripherals/genesis/ym7101.rs | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/peripherals/genesis/ym7101.rs b/src/peripherals/genesis/ym7101.rs index 2a0c09c..2ca1580 100644 --- a/src/peripherals/genesis/ym7101.rs +++ b/src/peripherals/genesis/ym7101.rs @@ -625,26 +625,29 @@ impl Steppable for Ym7101 { } self.state.h_clock += diff; - if (self.state.status & STATUS_IN_HBLANK) == 0 && self.state.v_clock > 58_820 { - self.state.status |= STATUS_IN_HBLANK; - } - if self.state.h_clock > 63_500 { + if (self.state.status & STATUS_IN_HBLANK) != 0 && self.state.h_clock >= 2_340 && self.state.h_clock <= 61_160 { self.state.status &= !STATUS_IN_HBLANK; - self.state.h_clock = 0; - self.state.h_scanlines = self.state.h_scanlines.wrapping_sub(1); + } + if (self.state.status & STATUS_IN_HBLANK) == 0 && self.state.h_clock >= 61_160 { + self.state.status |= STATUS_IN_HBLANK; + if self.state.hsync_int_enabled() && self.state.h_scanlines == 0 { self.state.h_scanlines = self.state.h_int_lines; system.get_interrupt_controller().set(true, 4, 28)?; } } + if self.state.h_clock > 63_500 { + self.state.h_clock -= 63_500; + self.state.h_scanlines = self.state.h_scanlines.wrapping_sub(1); + } self.state.v_clock += diff; - if (self.state.status & STATUS_IN_VBLANK) == 0 && self.state.v_clock > 14_218_000 { - self.state.status |= STATUS_IN_VBLANK; - } - if self.state.v_clock > 16_630_000 { + if (self.state.status & STATUS_IN_VBLANK) != 0 && self.state.v_clock >= 1_205_992 && self.state.v_clock <= 15_424_008 { self.state.status &= !STATUS_IN_VBLANK; - self.state.v_clock -= 16_630_000; + } + if (self.state.status & STATUS_IN_VBLANK) == 0 && self.state.v_clock >= 15_424_008 { + self.state.status |= STATUS_IN_VBLANK; + if self.state.vsync_int_enabled() { system.get_interrupt_controller().set(true, 6, 30)?; } @@ -654,6 +657,9 @@ impl Steppable for Ym7101 { self.frame_complete.signal(); } + if self.state.v_clock > 16_630_000 { + self.state.v_clock -= 16_630_000; + } if self.state.transfer_run != DmaType::None && (self.state.mode_2 & MODE2_BF_DMA_ENABLED) != 0 { // TODO we will just do the full dma transfer here, but it really should be stepped