Restore SC01 continuous phoneme playback from save-state (#1372, PR #1380)

. Save-state: Mockingboard v13: deprecate SS_YAML_KEY_VOTRAX_PHONEME (from Mockingboard card).
. Consolidate the save/loading of the SSI263 & SC01 state into single function (in class SSI263).
This commit is contained in:
TomCh
2025-02-11 21:54:48 +00:00
committed by GitHub
parent fa181922f0
commit b35a4d17d2
3 changed files with 48 additions and 36 deletions
+18 -20
View File
@@ -1148,8 +1148,9 @@ UINT MockingboardCard::AY8910_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, BYTE
// Changed at AppleWin 1.30.14
//11: Added: "Bus Driven by AY"
//12: Added: SSI263: SC01 phoneme & active
// Current Mode changed (added bit5 = enableInts)
// SSI263::m_currentMode changed (added bit5 = enableInts)
//13: Removed SS_YAML_KEY_SSI263_ACTIVE_PHONEME
// Removed SS_YAML_KEY_VOTRAX_PHONEME (as this has been present in the SC01 subunit since v12!)
const UINT kUNIT_VERSION = 13;
#define SS_YAML_KEY_MB_UNIT "Unit"
@@ -1215,8 +1216,6 @@ void MockingboardCard::SaveSnapshot(YamlSaveHelper& yamlSaveHelper)
YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE);
yamlSaveHelper.SaveBool(SS_YAML_KEY_VOTRAX_PHONEME, m_MBSubUnit[0].ssi263.GetVotraxPhoneme()); // SC01 only in subunit 0
for (UINT subunit = 0; subunit < NUM_SUBUNITS_PER_MB; subunit++)
{
MB_SUBUNIT* pMB = &m_MBSubUnit[subunit];
@@ -1225,9 +1224,7 @@ void MockingboardCard::SaveSnapshot(YamlSaveHelper& yamlSaveHelper)
pMB->sy6522.SaveSnapshot(yamlSaveHelper);
AY8910_SaveSnapshot(yamlSaveHelper, subunit, AY8913_DEVICE_A, std::string(""));
pMB->ssi263.SaveSnapshot(yamlSaveHelper);
if (subunit == 0) // has SC01
pMB->ssi263.SC01_SaveSnapshot(yamlSaveHelper);
pMB->ssi263.SaveSnapshot(yamlSaveHelper, subunit);
yamlSaveHelper.SaveHexUint4(SS_YAML_KEY_MB_UNIT_STATE, pMB->state[0]);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_AY_CURR_REG, pMB->nAYCurrentRegister[0]); // save all 8 bits (even though top 4 bits should be 0)
@@ -1252,8 +1249,11 @@ bool MockingboardCard::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version
AY8910UpdateSetCycles();
bool isVotrax = (version >= 6) ? yamlLoadHelper.LoadBool(SS_YAML_KEY_VOTRAX_PHONEME) : false;
m_MBSubUnit[0].ssi263.SetVotraxPhoneme(isVotrax); // SC01 only in subunit 0
if (version >= 6 && version <= 12)
{
bool isVotrax = yamlLoadHelper.LoadBool(SS_YAML_KEY_VOTRAX_PHONEME);
m_MBSubUnit[0].ssi263.SetVotraxPhoneme(isVotrax); // SC01 only in subunit 0
}
for (UINT subunit = 0; subunit < NUM_SUBUNITS_PER_MB; subunit++)
{
@@ -1267,9 +1267,8 @@ bool MockingboardCard::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version
pMB->sy6522.LoadSnapshot(yamlLoadHelper, version);
UpdateIFRandIRQ(pMB, 0, pMB->sy6522.GetReg(SY6522::rIFR)); // Assert any pending IRQs (GH#677)
AY8910_LoadSnapshot(yamlLoadHelper, subunit, AY8913_DEVICE_A, std::string(""));
pMB->ssi263.LoadSnapshot(yamlLoadHelper, PH_Mockingboard, version); // Pre: SetVotraxPhoneme()
if (subunit == 0) // has SC01
pMB->ssi263.SC01_LoadSnapshot(yamlLoadHelper, version);
pMB->ssi263.LoadSnapshot(yamlLoadHelper, PH_Mockingboard, version, subunit);
pMB->nAYCurrentRegister[0] = yamlLoadHelper.LoadUint(SS_YAML_KEY_AY_CURR_REG);
@@ -1324,7 +1323,6 @@ void MockingboardCard::Phasor_SaveSnapshot(YamlSaveHelper& yamlSaveHelper)
YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE);
yamlSaveHelper.SaveUint(SS_YAML_KEY_PHASOR_MODE, m_phasorMode);
yamlSaveHelper.SaveBool(SS_YAML_KEY_VOTRAX_PHONEME, m_MBSubUnit[0].ssi263.GetVotraxPhoneme()); // SC01 only in subunit 0
for (UINT subunit = 0; subunit < NUM_SUBUNITS_PER_MB; subunit++)
{
@@ -1335,9 +1333,7 @@ void MockingboardCard::Phasor_SaveSnapshot(YamlSaveHelper& yamlSaveHelper)
pMB->sy6522.SaveSnapshot(yamlSaveHelper);
AY8910_SaveSnapshot(yamlSaveHelper, subunit, AY8913_DEVICE_A, std::string("-A"));
AY8910_SaveSnapshot(yamlSaveHelper, subunit, AY8913_DEVICE_B, std::string("-B"));
pMB->ssi263.SaveSnapshot(yamlSaveHelper);
if (subunit == 0) // has SC01
pMB->ssi263.SC01_SaveSnapshot(yamlSaveHelper);
pMB->ssi263.SaveSnapshot(yamlSaveHelper, subunit);
yamlSaveHelper.SaveHexUint4(SS_YAML_KEY_MB_UNIT_STATE, pMB->state[0]);
yamlSaveHelper.SaveHexUint4(SS_YAML_KEY_MB_UNIT_STATE_B, pMB->state[1]);
@@ -1374,8 +1370,11 @@ bool MockingboardCard::Phasor_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT
UINT nDeviceNum = 0;
MB_SUBUNIT* pMB = &m_MBSubUnit[0];
bool isVotrax = (version >= 6) ? yamlLoadHelper.LoadBool(SS_YAML_KEY_VOTRAX_PHONEME) : false;
m_MBSubUnit[0].ssi263.SetVotraxPhoneme(isVotrax); // SC01 only in subunit 0
if (version >= 6 && version <= 12)
{
bool isVotrax = yamlLoadHelper.LoadBool(SS_YAML_KEY_VOTRAX_PHONEME);
m_MBSubUnit[0].ssi263.SetVotraxPhoneme(isVotrax); // SC01 only in subunit 0
}
for (UINT subunit = 0; subunit < NUM_SUBUNITS_PER_MB; subunit++)
{
@@ -1405,9 +1404,8 @@ bool MockingboardCard::Phasor_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT
AY8910_LoadSnapshot(yamlLoadHelper, subunit, AY8913_DEVICE_A, std::string("-A"));
AY8910_LoadSnapshot(yamlLoadHelper, subunit, AY8913_DEVICE_B, std::string("-B"));
}
pMB->ssi263.LoadSnapshot(yamlLoadHelper, m_phasorMode, version); // Pre: SetVotraxPhoneme()
if (subunit == 0) // has SC01
pMB->ssi263.SC01_LoadSnapshot(yamlLoadHelper, version);
pMB->ssi263.LoadSnapshot(yamlLoadHelper, m_phasorMode, version, subunit);
pMB->nAYCurrentRegister[0] = yamlLoadHelper.LoadUint(SS_YAML_KEY_AY_CURR_REG);
if (version >= 10)
+25 -11
View File
@@ -1004,19 +1004,25 @@ void SSI263::SetVolume(uint32_t dwVolume, uint32_t dwVolumeMax)
#define SS_YAML_KEY_SSI263_CURRENT_MODE "Current Mode"
#define SS_YAML_KEY_SSI263_ACTIVE_PHONEME "Active Phoneme" // v13: deprecated
void SSI263::SaveSnapshot(YamlSaveHelper& yamlSaveHelper)
void SSI263::SaveSnapshot(YamlSaveHelper& yamlSaveHelper, UINT subunit)
{
YamlSaveHelper::Label label(yamlSaveHelper, "%s:\n", SS_YAML_KEY_SSI263);
// Scope for SSI263 subunit (so that SC01 has same indentation)
{
YamlSaveHelper::Label label(yamlSaveHelper, "%s:\n", SS_YAML_KEY_SSI263);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_SSI263_REG_DUR_PHON, m_durationPhoneme);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_SSI263_REG_INF, m_inflection);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_SSI263_REG_RATE_INF, m_rateInflection);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_SSI263_REG_CTRL_ART_AMP, m_ctrlArtAmp);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_SSI263_REG_FILTER_FREQ, m_filterFreq);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_SSI263_CURRENT_MODE, m_currentMode.mode);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_SSI263_REG_DUR_PHON, m_durationPhoneme);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_SSI263_REG_INF, m_inflection);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_SSI263_REG_RATE_INF, m_rateInflection);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_SSI263_REG_CTRL_ART_AMP, m_ctrlArtAmp);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_SSI263_REG_FILTER_FREQ, m_filterFreq);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_SSI263_CURRENT_MODE, m_currentMode.mode);
}
if (subunit == 0) // has SC01
SC01_SaveSnapshot(yamlSaveHelper);
}
void SSI263::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, PHASOR_MODE mode, UINT version)
void SSI263::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, PHASOR_MODE mode, UINT version, UINT subunit)
{
if (!yamlLoadHelper.GetSubMap(SS_YAML_KEY_SSI263))
throw std::runtime_error("Card: Expected key: " SS_YAML_KEY_SSI263);
@@ -1031,8 +1037,6 @@ void SSI263::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, PHASOR_MODE mode, UINT
if (version >= 7 && version < 13)
yamlLoadHelper.LoadBool(SS_YAML_KEY_SSI263_ACTIVE_PHONEME); // Consume redundant data
m_currentActivePhoneme = !IsPhonemeActive() ? -1 : 0x00; // Not important which phoneme, since UpdateIRQ() resets this
if (version < 12)
{
if (m_currentMode.function == 0) // invalid function (but in older versions this was accepted)
@@ -1057,11 +1061,21 @@ void SSI263::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, PHASOR_MODE mode, UINT
if (m_cardMode == PH_Phasor && IsPhonemeActive() && m_currentMode.enableInts && m_currentMode.D7 == 1)
CpuIrqAssert(IS_SPEECH);
if (subunit == 0) // has SC01
SC01_LoadSnapshot(yamlLoadHelper, version);
// Do this after loading both SSI263 & SC01 state, otherwise IsPhonemeActive() can indicate both are active!
// . EG. After loading SSI263, SSI263.CONTROL==0 (so active); and after loading SC01, m_isVotraxPhoneme==true (so active)
if (m_isVotraxPhoneme)
m_currentActivePhoneme = 0x00; // For IsPhonemeActive() and SC01 chip
if (IsPhonemeActive())
{
// NB. Save-state doesn't preserve the play-position within the phoneme.
// It just sets IRQ (and SSI263.D7) for "phoneme complete"; and restarts it from the beginning.
// This may cause problems for timing sensitive code (eg. mb-audit).
m_currentActivePhoneme = 0x00; // Not important which phoneme, since RepeatPhoneme()->Play() sets this
UpdateIRQ(); // Pre: m_device, m_cardMode
RepeatPhoneme();
}
+5 -5
View File
@@ -97,13 +97,10 @@ public:
void SetSpeechIRQ(void);
void Votrax_Write(BYTE nValue);
bool GetVotraxPhoneme(void) { return m_isVotraxPhoneme; }
void SetVotraxPhoneme(bool value) { m_isVotraxPhoneme = value; }
void SaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
void LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, PHASOR_MODE mode, UINT version);
void SC01_SaveSnapshot(YamlSaveHelper& yamlSaveHelper);
void SC01_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version);
void SaveSnapshot(class YamlSaveHelper& yamlSaveHelper, UINT subunit);
void LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, PHASOR_MODE mode, UINT version, UINT subunit);
private:
void Play(unsigned int nPhoneme);
@@ -120,6 +117,9 @@ private:
bool Init(void);
bool DSInit(void);
void SC01_SaveSnapshot(YamlSaveHelper& yamlSaveHelper);
void SC01_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version);
static const BYTE m_Votrax2SSI263[/*64*/];
static const unsigned short m_kNumChannels = 1;