From 1efa629bed496f61b3a2cb10f23a49e8914c0020 Mon Sep 17 00:00:00 2001 From: tomcw Date: Sun, 3 Mar 2024 21:36:30 +0000 Subject: [PATCH] II+: Working with Saturns in s0 and s3, including save/load state --- source/CardManager.cpp | 24 +++++++++++++++++------- source/CmdLine.cpp | 26 ++++++++++++++------------ source/LanguageCard.cpp | 27 ++++++++++++++++++--------- source/LanguageCard.h | 2 ++ source/Memory.cpp | 23 ++++++++++++++++++++++- source/Memory.h | 2 +- source/SaveState.cpp | 5 +++-- source/Windows/AppleWin.cpp | 5 +++-- 8 files changed, 80 insertions(+), 34 deletions(-) diff --git a/source/CardManager.cpp b/source/CardManager.cpp index a1986e39..f641098e 100644 --- a/source/CardManager.cpp +++ b/source/CardManager.cpp @@ -115,22 +115,28 @@ void CardManager::InsertInternal(UINT slot, SS_CARDTYPE type) case CT_Uthernet2: m_slot[slot] = new Uthernet2(slot); break; - case CT_LanguageCard: _ASSERT(m_pLanguageCard == NULL); if (m_pLanguageCard) break; // Only support one language card m_slot[slot] = m_pLanguageCard = LanguageCardSlot0::create(slot); break; - case CT_Saturn128K: - _ASSERT(m_pLanguageCard == NULL); - if (m_pLanguageCard) break; // Only support one language card - m_slot[slot] = m_pLanguageCard = new Saturn128K(slot, Saturn128K::GetSaturnMemorySize()); - break; case CT_LanguageCardIIe: _ASSERT(m_pLanguageCard == NULL); if (m_pLanguageCard) break; // Only support one language card m_slot[slot] = m_pLanguageCard = LanguageCardUnit::create(slot); break; + case CT_Saturn128K: + if (slot == SLOT0) + { + _ASSERT(m_pLanguageCard == NULL); + if (m_pLanguageCard) break; // Only support one language card + m_slot[slot] = m_pLanguageCard = new Saturn128K(slot, Saturn128K::GetSaturnMemorySize()); + } + else + { + m_slot[slot] = new Saturn128K(slot, Saturn128K::kMaxSaturnBanks); + } + break; default: _ASSERT(0); @@ -165,10 +171,14 @@ void CardManager::RemoveInternal(UINT slot) m_pParallelPrinterCard = NULL; break; case CT_LanguageCard: - case CT_Saturn128K: case CT_LanguageCardIIe: + _ASSERT(slot == SLOT0); m_pLanguageCard = NULL; break; + case CT_Saturn128K: + if (slot == SLOT0) + m_pLanguageCard = NULL; + break; case CT_Z80: m_pZ80Card = NULL; break; diff --git a/source/CmdLine.cpp b/source/CmdLine.cpp index 3ad9d64b..9015ae47 100644 --- a/source/CmdLine.cpp +++ b/source/CmdLine.cpp @@ -157,6 +157,18 @@ bool ProcessCmdLine(LPSTR lpCmdLine) lpNextArg = GetNextArg(lpNextArg); g_cmdLine.szImageName_harddisk[SLOT7][HARDDISK_2] = lpCmdLine; } + else if (strcmp(lpCmdLine, "-s0") == 0) // Language Card options for Apple II/II+ + { + lpCmdLine = GetCurrArg(lpNextArg); + lpNextArg = GetNextArg(lpNextArg); + + if (strcmp(lpCmdLine, "saturn") == 0 || strcmp(lpCmdLine, "saturn128") == 0) + g_cmdLine.uSaturnBanks = Saturn128K::kMaxSaturnBanks; + else if (strcmp(lpCmdLine, "saturn64") == 0) + g_cmdLine.uSaturnBanks = Saturn128K::kMaxSaturnBanks / 2; + else if (strcmp(lpCmdLine, "languagecard") == 0 || strcmp(lpCmdLine, "lc") == 0) + g_cmdLine.bSlot0LanguageCard = true; + } else if (lpCmdLine[0] == '-' && lpCmdLine[1] == 's' && lpCmdLine[2] >= '1' && lpCmdLine[2] <= '7') { const UINT slot = lpCmdLine[2] - '0'; @@ -176,6 +188,8 @@ bool ProcessCmdLine(LPSTR lpCmdLine) } if (strcmp(lpCmdLine, "hdc") == 0) g_cmdLine.slotInsert[slot] = CT_GenericHDD; + if (strcmp(lpCmdLine, "saturn") == 0 || strcmp(lpCmdLine, "saturn128") == 0) // Support Saturn128 card in slot 1-7 too (GH#1279) + g_cmdLine.slotInsert[slot] = CT_Saturn128K; if (strcmp(lpCmdLine, "megaaudio") == 0) { g_cmdLine.slotInsert[slot] = CT_MegaAudio; @@ -343,18 +357,6 @@ bool ProcessCmdLine(LPSTR lpCmdLine) g_cmdLine.uRamWorksExPages = 1; } #endif - else if (strcmp(lpCmdLine, "-s0") == 0) - { - lpCmdLine = GetCurrArg(lpNextArg); - lpNextArg = GetNextArg(lpNextArg); - - if (strcmp(lpCmdLine, "saturn") == 0 || strcmp(lpCmdLine, "saturn128") == 0) - g_cmdLine.uSaturnBanks = Saturn128K::kMaxSaturnBanks; - else if (strcmp(lpCmdLine, "saturn64") == 0) - g_cmdLine.uSaturnBanks = Saturn128K::kMaxSaturnBanks/2; - else if (strcmp(lpCmdLine, "languagecard") == 0 || strcmp(lpCmdLine, "lc") == 0) - g_cmdLine.bSlot0LanguageCard = true; - } else if (strcmp(lpCmdLine, "-f8rom") == 0) // Use custom 2K ROM at [$F800..$FFFF] { lpCmdLine = GetCurrArg(lpNextArg); diff --git a/source/LanguageCard.cpp b/source/LanguageCard.cpp index 6d8079b5..bcce7e75 100644 --- a/source/LanguageCard.cpp +++ b/source/LanguageCard.cpp @@ -47,15 +47,17 @@ LanguageCardUnit::LanguageCardUnit(SS_CARDTYPE type, UINT slot) : Card(type, slot), m_uLastRamWrite(0) { - if (m_slot != LanguageCardUnit::kSlot0) + if (type != CT_Saturn128K && m_slot != LanguageCardUnit::kSlot0) ThrowErrorInvalidSlot(); - SetMemMainLanguageCard(NULL, true); + if (m_slot == SLOT0) + SetMemMainLanguageCard(NULL, SLOT0, true); } LanguageCardUnit::~LanguageCardUnit(void) { - SetMemMainLanguageCard(NULL); + if (m_slot == SLOT0) + SetMemMainLanguageCard(NULL, SLOT0); } void LanguageCardUnit::InitializeIO(LPBYTE pCxRomPeripheral) @@ -154,7 +156,8 @@ LanguageCardSlot0::LanguageCardSlot0(SS_CARDTYPE type, UINT slot) : LanguageCardUnit(type, slot) { m_pMemory = new BYTE[kMemBankSize]; - SetMemMainLanguageCard(m_pMemory); + if (m_slot == SLOT0) + SetMemMainLanguageCard(m_pMemory, SLOT0); } LanguageCardSlot0::~LanguageCardSlot0(void) @@ -261,7 +264,8 @@ Saturn128K::Saturn128K(UINT slot, UINT banks) for (UINT i = 1; i < m_uSaturnTotalBanks; i++) m_aSaturnBanks[i] = new BYTE[kMemBankSize]; // Saturn banks are 16K, max 8 banks/card - SetMemMainLanguageCard( m_aSaturnBanks[ m_uSaturnActiveBank ] ); + if (slot == SLOT0) + SetMemMainLanguageCard(m_aSaturnBanks[m_uSaturnActiveBank], SLOT0); } Saturn128K::~Saturn128K(void) @@ -334,7 +338,7 @@ BYTE __stdcall Saturn128K::IO(WORD PC, WORD uAddr, BYTE bWrite, BYTE uValue, ULO pLC->m_uSaturnActiveBank = pLC->m_uSaturnTotalBanks-1; // FIXME: just prevent crash for now! } - SetMemMainLanguageCard( pLC->m_aSaturnBanks[ pLC->m_uSaturnActiveBank ] ); + SetMemMainLanguageCard(pLC->m_aSaturnBanks[pLC->m_uSaturnActiveBank], uSlot); bBankChanged = true; } else @@ -453,13 +457,18 @@ bool Saturn128K::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version) yamlLoadHelper.PopMap(); } - SetMemMainLanguageCard( m_aSaturnBanks[ m_uSaturnActiveBank ] ); - - // NB. MemUpdatePaging(TRUE) called at end of Snapshot_LoadState_v2() + // NB. MemInitializeFromSnapshot() called at end of Snapshot_LoadState_v2(): + // . SetMemMainLanguageCard() for the slot/card that last set the 16KB LC bank + // . MemUpdatePaging(TRUE) return true; } +void Saturn128K::SetMainMemLanguageCard(void) +{ + SetMemMainLanguageCard(m_aSaturnBanks[m_uSaturnActiveBank], m_slot); +} + void Saturn128K::SetSaturnMemorySize(UINT banks) { g_uSaturnBanksFromCmdLine = banks; diff --git a/source/LanguageCard.h b/source/LanguageCard.h index b30e694c..88e3f0a3 100644 --- a/source/LanguageCard.h +++ b/source/LanguageCard.h @@ -85,6 +85,8 @@ public: virtual void SaveSnapshot(YamlSaveHelper& yamlSaveHelper); virtual bool LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version); + void SetMainMemLanguageCard(void); + static UINT GetSaturnMemorySize(); static void SetSaturnMemorySize(UINT banks); diff --git a/source/Memory.cpp b/source/Memory.cpp index a92ffa27..d2778e9d 100644 --- a/source/Memory.cpp +++ b/source/Memory.cpp @@ -241,6 +241,8 @@ static LPBYTE RWpages[kMaxExMemoryBanks]; // pointers to RW memory banks static const UINT kNumAnnunciators = 4; static bool g_Annunciator[kNumAnnunciators] = {}; +static UINT g_lastSlotToSetMainMemLC = SLOT0; +static UINT g_lastSlotToSetMainMemLCFromSnapshot = SLOT0; BYTE __stdcall IO_Annunciator(WORD programcounter, WORD address, BYTE write, BYTE value, ULONG nCycles); @@ -384,12 +386,14 @@ static void SetLastRamWrite(BOOL count) // -void SetMemMainLanguageCard(LPBYTE ptr, bool bMemMain /*=false*/) +void SetMemMainLanguageCard(LPBYTE ptr, UINT slot, bool bMemMain /*=false*/) { if (bMemMain) g_pMemMainLanguageCard = memmain+0xC000; else g_pMemMainLanguageCard = ptr; + + g_lastSlotToSetMainMemLC = slot; } LPBYTE GetCxRomPeripheral(void) @@ -1777,6 +1781,15 @@ void MemInitializeFromSnapshot(void) // NB. Copied to /mem/ by UpdatePaging(TRUE) } + // If multiple "Language Cards" (eg. LC+Saturn or 2xSaturn) then setup via the last card that selected the 16KB LC bank. + // NB. Skip if not Saturn card (ie. a LC), since LC's are only in slot0 and in the ctor it has called SetMainMemLanguageCard() + if (GetCardMgr().QuerySlot(g_lastSlotToSetMainMemLCFromSnapshot) == CT_Saturn128K) + { + Saturn128K& saturn = dynamic_cast(GetCardMgr().GetRef(g_lastSlotToSetMainMemLCFromSnapshot)); + saturn.SetMainMemLanguageCard(); + } + + // Finally setup the paging tables MemUpdatePaging(TRUE); // @@ -2208,6 +2221,7 @@ void MemRemoveNoSlotClock(void) #define SS_YAML_KEY_EXPANSIONROMTYPE "Expansion ROM Type" #define SS_YAML_KEY_PERIPHERALROMSLOT "Peripheral ROM Slot" #define SS_YAML_KEY_ANNUNCIATOR "Annunciator" +#define SS_YAML_KEY_LASTSLOTTOSETMAINMEMLC "Last Slot to Set Main Mem LC" // @@ -2282,6 +2296,7 @@ void MemSaveSnapshot(YamlSaveHelper& yamlSaveHelper) yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_IOSELECT_INT, INTC8ROM ? 1 : 0); yamlSaveHelper.SaveUint(SS_YAML_KEY_EXPANSIONROMTYPE, (UINT) g_eExpansionRomType); yamlSaveHelper.SaveUint(SS_YAML_KEY_PERIPHERALROMSLOT, g_uPeripheralRomSlot); + yamlSaveHelper.SaveUint(SS_YAML_KEY_LASTSLOTTOSETMAINMEMLC, g_lastSlotToSetMainMemLC); for (UINT i=0; i= 9) + { + g_lastSlotToSetMainMemLCFromSnapshot = yamlLoadHelper.LoadUint(SS_YAML_KEY_LASTSLOTTOSETMAINMEMLC); + } + yamlLoadHelper.PopMap(); // diff --git a/source/Memory.h b/source/Memory.h index 2d733463..cfa885ac 100644 --- a/source/Memory.h +++ b/source/Memory.h @@ -115,6 +115,6 @@ SS_CARDTYPE GetCurrentExpansionMemType(void); void SetRamWorksMemorySize(UINT pages); UINT GetRamWorksActiveBank(void); -void SetMemMainLanguageCard(LPBYTE ptr, bool bMemMain=false); +void SetMemMainLanguageCard(LPBYTE ptr, UINT slot, bool bMemMain=false); LPBYTE GetCxRomPeripheral(void); diff --git a/source/SaveState.cpp b/source/SaveState.cpp index eea5b11c..5c079951 100644 --- a/source/SaveState.cpp +++ b/source/SaveState.cpp @@ -67,7 +67,8 @@ static YamlHelper yamlHelper; // v6: Added 'Unit Miscellaneous' for NoSlotClock(NSC) // v7: Extended: joystick (added 'Paddle Inactive Cycle') // v8: Added 'Unit Game I/O Connector' for Game I/O Connector -#define UNIT_APPLE2_VER 8 +// v9: Extended: memory (added 'Last Slot to Set Main Mem LC') +#define UNIT_APPLE2_VER 9 #define UNIT_SLOTS_VER 1 @@ -292,7 +293,7 @@ static void ParseSlots(YamlLoadHelper& yamlLoadHelper, UINT unitVersion) SS_CARDTYPE type = Card::GetCardType(card); bool bRes = false; - if (slot == 0) + if (slot == SLOT0) { SetExpansionMemType(type); // calls GetCardMgr().Insert() & InsertAux() } diff --git a/source/Windows/AppleWin.cpp b/source/Windows/AppleWin.cpp index 82a796a3..8889e058 100644 --- a/source/Windows/AppleWin.cpp +++ b/source/Windows/AppleWin.cpp @@ -770,9 +770,10 @@ static void RepeatInitialization(void) GetCardMgr().GetParallelPrinterCard()->SetEnableDumpToRealPrinter(true); } - if (g_cmdLine.slotInsert[SLOT3] != CT_Empty && g_cmdLine.slotInsert[SLOT3] == CT_VidHD) // For now just support VidHD in slot 3 + if (g_cmdLine.slotInsert[SLOT3] != CT_Empty) { - GetCardMgr().Insert(SLOT3, g_cmdLine.slotInsert[SLOT3]); + if (g_cmdLine.slotInsert[SLOT3] == CT_VidHD || g_cmdLine.slotInsert[SLOT3] == CT_Saturn128K) // For now just support VidHD and Saturn128 in slot 3) + GetCardMgr().Insert(SLOT3, g_cmdLine.slotInsert[SLOT3]); } if (g_cmdLine.slotInsert[SLOT4] != CT_Empty)