MB/Phasor: SSI263 - improved save-state for different speech cards' IRQs

This commit is contained in:
tomcw 2020-04-26 18:07:38 +01:00
parent 358573a9db
commit 61a3f06172
1 changed files with 67 additions and 60 deletions

View File

@ -991,6 +991,46 @@ static void MB_Update(void)
//-----------------------------------------------------------------------------
// Called by SSI263Thread(), MB_LoadSnapshot & Phasor_LoadSnapshot
// Pre: g_bVotraxPhoneme, g_bPhasorEnable, g_phasorMode
static void SetSpeechIRQ(SY6522_AY8910* pMB)
{
if (!g_bVotraxPhoneme)
{
// Always set SSI263's D7 pin regardless of SSI263 mode (DR1:0), including MODE_IRQ_DISABLED
pMB->SpeechChip.CurrentMode |= 1; // Set SSI263's D7 pin
if ((pMB->SpeechChip.CurrentMode & DURATION_MODE_MASK) != MODE_IRQ_DISABLED)
{
if (!g_bPhasorEnable || (g_bPhasorEnable && g_phasorMode == PH_Mockingboard))
{
if ((pMB->sy6522.PCR & 1) == 0) // CA1 Latch/Input = 0 (Negative active edge)
UpdateIFR(pMB, 0, IxR_PERIPHERAL);
if (pMB->sy6522.PCR == 0x0C) // CA2 Control = b#110 (Low output)
pMB->SpeechChip.CurrentMode &= ~1; // Clear SSI263's D7 pin (cleared by 6522's PCR CA1/CA2 handshake)
// NB. Don't set CTL=1, as Mockingboard(SMS) speech doesn't work (it sets MODE_IRQ_DISABLED mode during ISR)
//pMB->SpeechChip.CtrlArtAmp |= CONTROL_MASK; // 6522's CA2 sets Power Down mode (pin 18), which sets Control bit
}
else if (g_bPhasorEnable && g_phasorMode == PH_Phasor) // Phasor's SSI263 IRQ (A/!R) line is *also* wired directly to the 6502's IRQ (as well as the 6522's CA1)
{
CpuIrqAssert(IS_SPEECH);
}
}
}
//
if (g_bVotraxPhoneme && pMB->sy6522.PCR == 0xB0)
{
// !A/R: Time-out of old phoneme (signal goes from low to high)
UpdateIFR(pMB, 0, IxR_VOTRAX);
g_bVotraxPhoneme = false;
}
}
static DWORD WINAPI SSI263Thread(LPVOID lpParameter)
{
while(1)
@ -1029,41 +1069,7 @@ static DWORD WINAPI SSI263Thread(LPVOID lpParameter)
// Phoneme complete, so generate IRQ if necessary
SY6522_AY8910* pMB = &g_MB[g_nSSI263Device];
if (!g_bVotraxPhoneme)
{
// Always set SSI263's D7 pin regardless of SSI263 mode (DR1:0), including MODE_IRQ_DISABLED
pMB->SpeechChip.CurrentMode |= 1; // Set SSI263's D7 pin
if (pMB->SpeechChip.CurrentMode != MODE_IRQ_DISABLED)
{
if (!g_bPhasorEnable || (g_bPhasorEnable && g_phasorMode == PH_Mockingboard))
{
if ((pMB->sy6522.PCR & 1) == 0) // CA1 Latch/Input = 0 (Negative active edge)
UpdateIFR(pMB, 0, IxR_PERIPHERAL);
if (pMB->sy6522.PCR == 0x0C) // CA2 Control = b#110 (Low output)
pMB->SpeechChip.CurrentMode &= ~1; // Clear SSI263's D7 pin (cleared by 6522's PCR CA1/CA2 handshake)
// NB. Don't set CTL=1, as Mockingboard(SMS) speech doesn't work (it sets MODE_IRQ_DISABLED mode during ISR)
//pMB->SpeechChip.CtrlArtAmp |= CONTROL_MASK; // 6522's CA2 sets Power Down mode (pin 18), which sets Control bit
}
else if (g_bPhasorEnable && g_phasorMode == PH_Phasor) // Phasor's SSI263 IRQ (A/!R) line is *also* wired directly to the 6502's IRQ (as well as the 6522's CA1)
{
CpuIrqAssert(IS_SPEECH);
}
}
}
//
if (g_bVotraxPhoneme && pMB->sy6522.PCR == 0xB0)
{
// !A/R: Time-out of old phoneme (signal goes from low to high)
UpdateIFR(pMB, 0, IxR_VOTRAX);
g_bVotraxPhoneme = false;
}
SetSpeechIRQ(pMB);
}
return 0;
@ -2056,6 +2062,8 @@ void MB_GetSnapshot_v1(SS_CARD_MOCKINGBOARD_v1* const pSS, const DWORD dwSlot)
// 4: Added: 6522 timerIrqDelay - GH#652
// 5: Added: Unit state-B (Phasor only) - GH#659
// 6: Changed SS_YAML_KEY_PHASOR_MODE from (0,1) to (0,5,7)
// Added SS_YAML_KEY_VOTRAX_PHONEME
// Removed: redundant SS_YAML_KEY_PHASOR_CLOCK_SCALE_FACTOR
const UINT kUNIT_VERSION = 6;
const UINT NUM_MB_UNITS = 2;
@ -2095,9 +2103,11 @@ const UINT NUM_PHASOR_UNITS = 2;
#define SS_YAML_KEY_SY6522_TIMER2_IRQ_DELAY "Timer2 IRQ Delay"
#define SS_YAML_KEY_PHASOR_UNIT "Unit"
#define SS_YAML_KEY_PHASOR_CLOCK_SCALE_FACTOR "Clock Scale Factor"
#define SS_YAML_KEY_PHASOR_CLOCK_SCALE_FACTOR "Clock Scale Factor" // Redundant from v6
#define SS_YAML_KEY_PHASOR_MODE "Mode"
#define SS_YAML_KEY_VOTRAX_PHONEME "Votrax Phoneme"
std::string MB_GetSnapshotCardName(void)
{
static const std::string name("Mockingboard C");
@ -2154,6 +2164,8 @@ void MB_SaveSnapshot(YamlSaveHelper& yamlSaveHelper, const UINT uSlot)
YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE);
yamlSaveHelper.SaveBool(SS_YAML_KEY_VOTRAX_PHONEME, g_bVotraxPhoneme);
for(UINT i=0; i<NUM_MB_UNITS; i++)
{
YamlSaveHelper::Label unit(yamlSaveHelper, "%s%d:\n", SS_YAML_KEY_MB_UNIT, i);
@ -2229,6 +2241,8 @@ bool MB_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version)
if (version < 1 || version > kUNIT_VERSION)
throw std::string("Card: wrong version");
g_bVotraxPhoneme = (version >= 6) ? yamlLoadHelper.LoadBool(SS_YAML_KEY_VOTRAX_PHONEME) : false;
AY8910UpdateSetCycles();
const UINT nMbCardNum = slot - SLOT4;
@ -2280,19 +2294,15 @@ bool MB_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version)
StartTimer1(pMB); // Attempt to start timer
}
// Crude - currently only support a single speech chip
// FIX THIS:
// . Speech chip could be Votrax instead
// . Is this IRQ compatible with Phasor?
if(pMB->SpeechChip.DurationPhoneme)
// FIXME: currently only support a single speech chip
// NB. g_bVotraxPhoneme is never true, as the phoneme playback completes in SSI263Thread() before this point in the save-state.
// NB. SpeechChip.DurationPhoneme will mostly be non-zero during speech playback, as this is the SSI263 register, not whether the phonene is active.
// FIXME: So possible race-condition between saving-state & SSI263Thread()
if (pMB->SpeechChip.DurationPhoneme || g_bVotraxPhoneme)
{
g_nSSI263Device = nDeviceNum;
if((pMB->SpeechChip.CurrentMode != MODE_IRQ_DISABLED) && (pMB->sy6522.PCR == 0x0C) && (pMB->sy6522.IER & IxR_PERIPHERAL))
{
UpdateIFR(pMB, 0, IxR_PERIPHERAL);
pMB->SpeechChip.CurrentMode |= 1; // Set SSI263's D7 pin
}
g_bPhasorEnable = false;
SetSpeechIRQ(pMB);
}
nDeviceNum++;
@ -2318,8 +2328,8 @@ void Phasor_SaveSnapshot(YamlSaveHelper& yamlSaveHelper, const UINT uSlot)
YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE);
yamlSaveHelper.SaveUint(SS_YAML_KEY_PHASOR_CLOCK_SCALE_FACTOR, g_PhasorClockScaleFactor);
yamlSaveHelper.SaveUint(SS_YAML_KEY_PHASOR_MODE, g_phasorMode);
yamlSaveHelper.SaveBool(SS_YAML_KEY_VOTRAX_PHONEME, g_bVotraxPhoneme);
for(UINT i=0; i<NUM_PHASOR_UNITS; i++)
{
@ -2352,7 +2362,8 @@ bool Phasor_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version
if (version < 1 || version > kUNIT_VERSION)
throw std::string("Card: wrong version");
g_PhasorClockScaleFactor = yamlLoadHelper.LoadUint(SS_YAML_KEY_PHASOR_CLOCK_SCALE_FACTOR);
if (version < 6)
yamlLoadHelper.LoadUint(SS_YAML_KEY_PHASOR_CLOCK_SCALE_FACTOR); // Consume redundant data
UINT phasorMode = yamlLoadHelper.LoadUint(SS_YAML_KEY_PHASOR_MODE);
if (version < 6)
@ -2363,6 +2374,9 @@ bool Phasor_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version
phasorMode = PH_Phasor;
}
g_phasorMode = (PHASOR_MODE) phasorMode;
g_PhasorClockScaleFactor = (g_phasorMode == PH_Phasor) ? 2 : 1;
g_bVotraxPhoneme = (version >= 6) ? yamlLoadHelper.LoadBool(SS_YAML_KEY_VOTRAX_PHONEME) : false;
AY8910UpdateSetCycles();
@ -2417,19 +2431,12 @@ bool Phasor_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version
StartTimer1(pMB); // Attempt to start timer
}
// Crude - currently only support a single speech chip
// FIX THIS:
// . Speech chip could be Votrax instead
// . Is this IRQ compatible with Phasor?
if(pMB->SpeechChip.DurationPhoneme)
// FIXME: currently only support a single speech chip
if (pMB->SpeechChip.DurationPhoneme || g_bVotraxPhoneme)
{
g_nSSI263Device = nDeviceNum;
if((pMB->SpeechChip.CurrentMode != MODE_IRQ_DISABLED) && (pMB->sy6522.PCR == 0x0C) && (pMB->sy6522.IER & IxR_PERIPHERAL))
{
UpdateIFR(pMB, 0, IxR_PERIPHERAL);
pMB->SpeechChip.CurrentMode |= 1; // Set SSI263's D7 pin
}
g_bPhasorEnable = true;
SetSpeechIRQ(pMB);
}
nDeviceNum += 2;