mirror of
https://github.com/AppleWin/AppleWin.git
synced 2024-12-23 00:30:17 +00:00
Mockingboard: support multiple TIMER1 interrupts, with one for MB reg updates (#685)
This commit is contained in:
parent
64bdd7192a
commit
11323e2aba
@ -211,12 +211,18 @@ static const double g_f6522TimerPeriod_NoIRQ = CLK_6502_NTSC / 60.0; // Constant
|
||||
static bool g_bCritSectionValid = false; // Deleting CritialSection when not valid causes crash on Win98
|
||||
static CRITICAL_SECTION g_CriticalSection; // To guard 6522's IFR
|
||||
|
||||
// If we have 2 timer ints: 50Hz and 60Hz, then need to be able to determine the AY8910 reg update freq
|
||||
static bool g_waitFirstAYWriteAfterTimer1Int = false;
|
||||
static UINT64 g_lastAY8910cycleAccess = 0;
|
||||
static UINT64 g_AYWriteAccessTimer1IntPeriod = 0;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// Forward refs:
|
||||
static DWORD WINAPI SSI263Thread(LPVOID);
|
||||
static void Votrax_Write(BYTE nDevice, BYTE nValue);
|
||||
static double MB_GetFramePeriod(void);
|
||||
static void MB_Update(void);
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@ -229,7 +235,7 @@ static void StartTimer1(SY6522_AY8910* pMB)
|
||||
|
||||
if (pMB->sy6522.IER & IxR_TIMER1) // Using 6522 interrupt
|
||||
g_nMBTimerDevice = pMB->nAY8910Number;
|
||||
else if (pMB->sy6522.ACR & RM_FREERUNNING) // Polling 6522 IFR
|
||||
else if (pMB->sy6522.ACR & RM_FREERUNNING) // Polling 6522 IFR (GH#496)
|
||||
g_nMBTimerDevice = pMB->nAY8910Number;
|
||||
}
|
||||
|
||||
@ -403,6 +409,19 @@ static void SY6522_Write(BYTE nDevice, BYTE nReg, BYTE nValue)
|
||||
AY8910_Write(nDevice, nReg, nValue, 0);
|
||||
}
|
||||
|
||||
if (g_waitFirstAYWriteAfterTimer1Int) // GH#685: Multiple TIMER1 interrupts
|
||||
{
|
||||
g_waitFirstAYWriteAfterTimer1Int = false;
|
||||
//CpuCalcCycles(uExecutedCycles); // Done in parent MB_Write() via MB_UpdateCycles()
|
||||
|
||||
g_AYWriteAccessTimer1IntPeriod = g_nCumulativeCycles - g_lastAY8910cycleAccess;
|
||||
if (g_AYWriteAccessTimer1IntPeriod > 0xffff)
|
||||
g_AYWriteAccessTimer1IntPeriod = (UINT64) g_f6522TimerPeriod_NoIRQ;
|
||||
g_lastAY8910cycleAccess = g_nCumulativeCycles;
|
||||
|
||||
MB_Update();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x01: // ORA
|
||||
@ -769,7 +788,8 @@ static void Votrax_Write(BYTE nDevice, BYTE nValue)
|
||||
// Called by:
|
||||
// . MB_UpdateCycles() - when g_nMBTimerDevice == {0,1,2,3}
|
||||
// . MB_EndOfVideoFrame() - when g_nMBTimerDevice == kTIMERDEVICE_INVALID
|
||||
static void MB_Update()
|
||||
// . SY6522_Write() - when multiple TIMER1s (interrupt sources) are active
|
||||
static void MB_Update(void)
|
||||
{
|
||||
//char szDbg[200];
|
||||
|
||||
@ -1475,6 +1495,10 @@ static void ResetState()
|
||||
g_nPhasorMode = 0;
|
||||
g_PhasorClockScaleFactor = 1;
|
||||
|
||||
g_waitFirstAYWriteAfterTimer1Int = false;
|
||||
g_lastAY8910cycleAccess = 0;
|
||||
g_AYWriteAccessTimer1IntPeriod = 0;
|
||||
|
||||
// Not these, as they don't change on a CTRL+RESET or power-cycle:
|
||||
// g_bMBAvailable = false;
|
||||
// g_SoundcardType = CT_Empty; // Don't uncomment, else _ASSERT will fire in MB_Read() after an F2->MB_Reset()
|
||||
@ -1786,6 +1810,10 @@ void MB_UpdateCycles(ULONG uExecutedCycles)
|
||||
_ASSERT(uCycles < 0x10000);
|
||||
USHORT nClocks = (USHORT) uCycles;
|
||||
|
||||
UINT numActiveTimer1s = 0;
|
||||
for (int i=0; i<NUM_SY6522; i++)
|
||||
numActiveTimer1s += g_MB[i].bTimer1Active ? 1 : 0;
|
||||
|
||||
for (int i=0; i<NUM_SY6522; i++)
|
||||
{
|
||||
SY6522_AY8910* pMB = &g_MB[i];
|
||||
@ -1811,9 +1839,16 @@ void MB_UpdateCycles(ULONG uExecutedCycles)
|
||||
{
|
||||
UpdateIFR(pMB, 0, IxR_TIMER1);
|
||||
|
||||
// Do MB_Update() before StopTimer1()
|
||||
if (g_nMBTimerDevice == i)
|
||||
MB_Update();
|
||||
if (numActiveTimer1s == 1)
|
||||
{
|
||||
// Do MB_Update() before StopTimer1()
|
||||
if (g_nMBTimerDevice == i)
|
||||
MB_Update();
|
||||
}
|
||||
else // GH#685: Multiple TIMER1 interrupts
|
||||
{
|
||||
g_waitFirstAYWriteAfterTimer1Int = true; // Defer MB_Update() until MB_Write()
|
||||
}
|
||||
|
||||
if ((pMB->sy6522.ACR & RUNMODE) == RM_ONESHOT)
|
||||
{
|
||||
@ -1877,6 +1912,9 @@ static double MB_GetFramePeriod(void)
|
||||
// -> MB_GetFramePeriod()
|
||||
// NB. Removing this Phasor-IFR check means the occasional 'g_f6522TimerPeriod_NoIRQ' gets returned.
|
||||
|
||||
if (g_AYWriteAccessTimer1IntPeriod)
|
||||
return (double)g_AYWriteAccessTimer1IntPeriod;
|
||||
|
||||
if ((g_nMBTimerDevice != kTIMERDEVICE_INVALID) ||
|
||||
(g_bPhasorEnable && (g_MB[0].sy6522.IFR & IxR_TIMER1))) // [*1]
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user