Introduce new APU timing hack

Timings.APUAllowTimeOverflow allows the SPC to cross the time limit
set by CPU.Cycles. Currently fixes Earthworm Jim 2, Ms. Pacman and
NBA Hang Time.
This commit is contained in:
OV2 2010-10-16 21:55:03 +02:00
parent 6df2bb515a
commit 33b1a63238
8 changed files with 29 additions and 4 deletions

View File

@ -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 &REGS [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++ )

View File

@ -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 <assert.h>
@ -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

View File

@ -69,6 +69,8 @@ blargg_err_t SNES_SPC::init()
m.cycle_table [i * 2 + 1] = n & 0x0F;
}
allow_time_overflow = false;
#if SPC_LESS_ACCURATE
memcpy( reg_times, reg_times_, sizeof reg_times );
#endif

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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 :(

View File

@ -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