diff --git a/apu/SNES_SPC.cpp b/apu/SNES_SPC.cpp index 7f4f9b7d..d6f6c927 100644 --- a/apu/SNES_SPC.cpp +++ b/apu/SNES_SPC.cpp @@ -511,7 +511,7 @@ int SNES_SPC::cpu_read( int addr, rel_time_t time ) BOOST::uint8_t* SNES_SPC::run_until_( time_t end_time )\ {\ rel_time_t rel_time = m.spc_time - end_time;\ - assert( rel_time <= 0 );\ + /*assert( rel_time <= 0 );*/\ m.spc_time = end_time;\ m.dsp_time += rel_time;\ m.timers [0].next_time += rel_time;\ @@ -524,7 +524,7 @@ BOOST::uint8_t* SNES_SPC::run_until_( time_t end_time )\ m.timers [0].next_time -= rel_time;\ m.timers [1].next_time -= rel_time;\ m.timers [2].next_time -= rel_time;\ - assert( m.spc_time <= end_time );\ + /*assert( m.spc_time >= end_time );*/\ return ®S [r_cpuio0];\ } @@ -543,7 +543,7 @@ void SNES_SPC::end_frame( time_t end_time ) // Greatest number of clocks early that emulation can stop early due to // not being able to execute current instruction without going over // allowed time. - assert( -cpu_lag_max <= m.spc_time && m.spc_time <= 0 ); + assert( -cpu_lag_max <= m.spc_time && m.spc_time <= cpu_lag_max ); // Catch timers up to CPU for ( int i = 0; i < timer_count; i++ ) diff --git a/apu/SNES_SPC.h b/apu/SNES_SPC.h index a0868693..bc69e94d 100644 --- a/apu/SNES_SPC.h +++ b/apu/SNES_SPC.h @@ -106,6 +106,8 @@ public: //// Snes9x Accessor + void spc_allow_time_overflow( bool ); + void dsp_set_spc_snapshot_callback( void (*callback) (void) ); void dsp_dump_spc_snapshot( void ); void dsp_set_stereo_switch( int ); @@ -258,6 +260,9 @@ private: static char const signature [signature_size + 1]; void save_regs( uint8_t out [reg_count] ); + +// Snes9x timing hack + bool allow_time_overflow; }; #include @@ -285,4 +290,6 @@ inline void SNES_SPC::disable_surround( bool disable ) { dsp.disable_surround( d inline bool SNES_SPC::check_kon() { return dsp.check_kon(); } #endif +inline void SNES_SPC::spc_allow_time_overflow( bool allow ) { allow_time_overflow = allow; } + #endif diff --git a/apu/SNES_SPC_misc.cpp b/apu/SNES_SPC_misc.cpp index 659377ae..52899157 100644 --- a/apu/SNES_SPC_misc.cpp +++ b/apu/SNES_SPC_misc.cpp @@ -68,6 +68,8 @@ blargg_err_t SNES_SPC::init() m.cycle_table [i * 2 + 0] = n >> 4; m.cycle_table [i * 2 + 1] = n & 0x0F; } + + allow_time_overflow = false; #if SPC_LESS_ACCURATE memcpy( reg_times, reg_times_, sizeof reg_times ); diff --git a/apu/SPC_CPU.h b/apu/SPC_CPU.h index 664fc488..0bd56fcd 100644 --- a/apu/SPC_CPU.h +++ b/apu/SPC_CPU.h @@ -196,7 +196,9 @@ loop: check( (unsigned) y < 0x100 ); opcode = *pc; - if ( (rel_time += m.cycle_table [opcode]) > 0 ) + if (allow_time_overflow && rel_time >= 0 ) + goto stop; + if ( (rel_time += m.cycle_table [opcode]) > 0 && !allow_time_overflow) goto out_of_time; #ifdef SPC_CPU_OPCODE_HOOK diff --git a/apu/apu.cpp b/apu/apu.cpp index 5dbd9319..c486e4b8 100644 --- a/apu/apu.cpp +++ b/apu/apu.cpp @@ -598,6 +598,11 @@ void S9xAPUTimingSetSpeedup (int ticks) UpdatePlaybackRate(); } +void S9xAPUAllowTimeOverflow (bool allow) +{ + spc_core->spc_allow_time_overflow(allow); +} + void S9xResetAPU (void) { spc::reference_time = 0; diff --git a/apu/apu.h b/apu/apu.h index a8ed9db9..48a0e082 100644 --- a/apu/apu.h +++ b/apu/apu.h @@ -195,6 +195,7 @@ void S9xAPUExecute (void); void S9xAPUEndScanline (void); void S9xAPUSetReferenceTime (int32); void S9xAPUTimingSetSpeedup (int); +void S9xAPUAllowTimeOverflow (bool); void S9xAPULoadState (uint8 *); void S9xAPUSaveState (uint8 *); void S9xDumpSPCSnapshot (void); diff --git a/memmap.cpp b/memmap.cpp index 7790ee0b..b5065dd3 100644 --- a/memmap.cpp +++ b/memmap.cpp @@ -3513,6 +3513,7 @@ void CMemory::ApplyROMFixes (void) //// APU timing hacks :( Timings.APUSpeedup = 0; + Timings.APUAllowTimeOverflow = FALSE; if (!Settings.DisableGameSpecificHacks) { @@ -3554,9 +3555,15 @@ void CMemory::ApplyROMFixes (void) match_na("HEIWA Parlor!Mini8") || // Parlor mini 8 match_nn("SANKYO Fever! \xCC\xA8\xB0\xCA\xDE\xB0!")) // SANKYO Fever! Fever! Timings.APUSpeedup = 1; + + if (match_na ("EARTHWORM JIM 2") || // Earthworm Jim 2 + match_na ("NBA Hangtime") || // NBA Hang Time + match_na ("MSPACMAN")) // Ms Pacman + Timings.APUAllowTimeOverflow = TRUE; } S9xAPUTimingSetSpeedup(Timings.APUSpeedup); + S9xAPUAllowTimeOverflow(Timings.APUAllowTimeOverflow); //// Other timing hacks :( diff --git a/snes9x.h b/snes9x.h index 692d01ab..a58be71f 100644 --- a/snes9x.h +++ b/snes9x.h @@ -334,6 +334,7 @@ struct STimings int32 NMIDMADelay; // The delay of NMI trigger after DMA transfers. Snes9x cannot emulate correctly. int32 IRQPendCount; // This value is just a hack, because Snes9x cannot emulate any events in an opcode. int32 APUSpeedup; + bool8 APUAllowTimeOverflow; }; struct SSettings