mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2025-04-10 19:15:14 +00:00
DSB2 IRQ 2 now fires at 1KHz rather than once per frame, improving
music timing in Daytona USA 2 and Sega Rally 2. DSB1 CPU timing increased from 1MHz to 4MHz, improving music fade timing in Scud Race. Thanks to gm_matthew for these discoveries.
This commit is contained in:
parent
e3374256ff
commit
46b1de2238
|
@ -1,7 +1,8 @@
|
|||
/**
|
||||
** Supermodel
|
||||
** A Sega Model 3 Arcade Emulator.
|
||||
** Copyright 2011 Bart Trzynadlowski, Nik Henson
|
||||
** Copyright 2011-2021 Bart Trzynadlowski, Nik Henson, Ian Curtis,
|
||||
** Harry Tuttle, and Spindizzi
|
||||
**
|
||||
** This file is part of Supermodel.
|
||||
**
|
||||
|
@ -438,7 +439,7 @@ void CDSB1::RunFrame(INT16 *audioL, INT16 *audioR)
|
|||
}
|
||||
|
||||
// While FIFO not empty, fire interrupts, run for up to one frame
|
||||
for (cycles = (4000000/60)/4; (cycles > 0) && (fifoIdxR != fifoIdxW); )
|
||||
for (cycles = (4000000/60); (cycles > 0) && (fifoIdxR != fifoIdxW); )
|
||||
{
|
||||
Z80.SetINT(true); // fire an IRQ to indicate pending command
|
||||
//printf("Z80 INT fired\n");
|
||||
|
@ -1015,12 +1016,27 @@ void CDSB2::RunFrame(INT16 *audioL, INT16 *audioR)
|
|||
|
||||
M68KSetIRQ(1); // indicate pending command
|
||||
//printf("68K INT fired\n");
|
||||
M68KRun(500);
|
||||
m_totalCyclesElapsed += M68KRun(500);
|
||||
}
|
||||
|
||||
// Per-frame interrupt
|
||||
// gm_matthew made the interesting discovery that IRQ2 may in fact be a timer interrupt
|
||||
// rather than a per-frame interrupt.For Daytona 2 and Sega Rally 2, assuming a value
|
||||
// of 1KHz fixes music fade outs and some timing issues. It is very likely this is a
|
||||
// configurable timer and we should be on the look-out for games which appear to use
|
||||
// different values. It is equally likely that all games share a similar code base and
|
||||
// use 1KHz as the timer rate.
|
||||
while (m_totalCyclesElapsed < m_nextFrameEndCycles)
|
||||
{
|
||||
if (m_totalCyclesElapsed >= m_nextTimerInterruptCycles)
|
||||
{
|
||||
// Fire timer interrupt and schedule next one
|
||||
M68KSetIRQ(2);
|
||||
M68KRun(4000000/60);
|
||||
m_nextTimerInterruptCycles = (m_totalCyclesElapsed + k_timerPeriod) - (m_totalCyclesElapsed + k_timerPeriod) % k_timerPeriod;
|
||||
}
|
||||
int cyclesToRun = (std::min)(m_nextTimerInterruptCycles, m_nextFrameEndCycles) - m_totalCyclesElapsed;
|
||||
m_totalCyclesElapsed += M68KRun(cyclesToRun);
|
||||
}
|
||||
m_nextFrameEndCycles = (m_totalCyclesElapsed + k_framePeriod) - (m_totalCyclesElapsed + k_framePeriod) % k_framePeriod;
|
||||
|
||||
M68KGetContext(&M68K);
|
||||
|
||||
|
@ -1080,6 +1096,10 @@ void CDSB2::Reset(void)
|
|||
//printf("DSB2 PC=%06X\n", M68KGetPC());
|
||||
M68KGetContext(&M68K);
|
||||
|
||||
m_totalCyclesElapsed = 0;
|
||||
m_nextFrameEndCycles = k_framePeriod;
|
||||
m_nextTimerInterruptCycles = k_timerPeriod;
|
||||
|
||||
DebugLog("DSB2 Reset\n");
|
||||
}
|
||||
|
||||
|
@ -1162,6 +1182,12 @@ void CDSB2::LoadState(CBlockFile *StateFile)
|
|||
M68KLoadState(StateFile, "DSB2 68K");
|
||||
M68KGetContext(&M68K);
|
||||
|
||||
// Technically these should be saved/restored rather than being reset but that would mean
|
||||
// the save state format has to be modified and the difference would be imperceptible anyway
|
||||
m_totalCyclesElapsed = 0;
|
||||
m_nextFrameEndCycles = k_framePeriod;
|
||||
m_nextTimerInterruptCycles = k_timerPeriod;
|
||||
|
||||
// Restart MPEG audio at the appropriate position
|
||||
if (isPlaying)
|
||||
{
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
/**
|
||||
** Supermodel
|
||||
** A Sega Model 3 Arcade Emulator.
|
||||
** Copyright 2011 Bart Trzynadlowski, Nik Henson
|
||||
** Copyright 2011-2021 Bart Trzynadlowski, Nik Henson, Ian Curtis,
|
||||
** Harry Tuttle, and Spindizzi
|
||||
**
|
||||
** This file is part of Supermodel.
|
||||
**
|
||||
|
@ -317,6 +318,11 @@ private:
|
|||
|
||||
// M68K CPU
|
||||
M68KCtx M68K;
|
||||
static const int k_framePeriod = 4000000/60;
|
||||
static const int k_timerPeriod = 4000000/1000; // 1KHz timer
|
||||
int m_totalCyclesElapsed;
|
||||
int m_nextFrameEndCycles;
|
||||
int m_nextTimerInterruptCycles;
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue