diff --git a/source/CardManager.cpp b/source/CardManager.cpp index 0361e280a..31554031a 100644 --- a/source/CardManager.cpp +++ b/source/CardManager.cpp @@ -41,6 +41,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "SerialComms.h" #include "SNESMAX.h" #include "VidHD.h" +#include "LanguageCard.h" +#include "Memory.h" void CardManager::InsertInternal(UINT slot, SS_CARDTYPE type) { @@ -102,18 +104,21 @@ void CardManager::InsertInternal(UINT slot, SS_CARDTYPE type) 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: - { - if (slot != 0) - { - _ASSERT(0); - break; - } - } - m_slot[slot] = new DummyCard(type, slot); + _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_LanguageCardIIe: // not a card default: _ASSERT(0); break; @@ -132,14 +137,27 @@ void CardManager::Insert(UINT slot, SS_CARDTYPE type, bool updateRegistry/*=true void CardManager::RemoveInternal(UINT slot) { - if (m_slot[slot] && m_slot[slot]->QueryType() == CT_MouseInterface) - m_pMouseCard = NULL; // NB. object deleted below: delete m_slot[slot] - - if (m_slot[slot] && m_slot[slot]->QueryType() == CT_SSC) - m_pSSC = NULL; // NB. object deleted below: delete m_slot[slot] + if (m_slot[slot]) + { + // NB. object deleted below: delete m_slot[slot] + switch (m_slot[slot]->QueryType()) + { + case CT_MouseInterface: + m_pMouseCard = NULL; + break; + case CT_SSC: + m_pSSC = NULL; + break; + case CT_LanguageCard: + case CT_Saturn128K: + case CT_LanguageCardIIe: + m_pLanguageCard = NULL; + break; + } - delete m_slot[slot]; - m_slot[slot] = NULL; + delete m_slot[slot]; + m_slot[slot] = NULL; + } } void CardManager::Remove(UINT slot, bool updateRegistry/*=true*/) @@ -195,6 +213,9 @@ void CardManager::RemoveAux(void) void CardManager::InitializeIO(LPBYTE pCxRomPeripheral) { + // if it is a //e then SLOT0 must be CT_LanguageCardIIe (and the other way round) + _ASSERT(IsApple2PlusOrClone(GetApple2Type()) != (m_slot[SLOT0]->QueryType() == CT_LanguageCardIIe)); + for (UINT i = 0; i < NUM_SLOTS; ++i) { if (m_slot[i]) @@ -217,7 +238,7 @@ void CardManager::Update(const ULONG nExecutedCycles) void CardManager::SaveSnapshot(YamlSaveHelper& yamlSaveHelper) { - for (UINT i = 1; i < NUM_SLOTS; ++i) + for (UINT i = 0; i < NUM_SLOTS; ++i) { if (m_slot[i]) { diff --git a/source/CardManager.h b/source/CardManager.h index ea970d88c..0e09ec592 100644 --- a/source/CardManager.h +++ b/source/CardManager.h @@ -9,7 +9,8 @@ class CardManager public: CardManager(void) : m_pMouseCard(NULL), - m_pSSC(NULL) + m_pSSC(NULL), + m_pLanguageCard(NULL) { InsertInternal(SLOT0, CT_Empty); InsertInternal(SLOT1, CT_GenericPrinter); @@ -54,9 +55,11 @@ class CardManager class CSuperSerialCard* GetSSC(void) { return m_pSSC; } bool IsSSCInstalled(void) { return m_pSSC != NULL; } + class LanguageCardUnit* GetLanguageCard(void) { return m_pLanguageCard; } + void InitializeIO(LPBYTE pCxRomPeripheral); void Update(const ULONG nExecutedCycles); - void SaveSnapshot(YamlSaveHelper& yamlSaveHelper); // It DOES NOT save SLOT0 + void SaveSnapshot(YamlSaveHelper& yamlSaveHelper); private: void InsertInternal(UINT slot, SS_CARDTYPE type); @@ -69,4 +72,5 @@ class CardManager Disk2CardManager m_disk2CardMgr; class CMouseInterface* m_pMouseCard; class CSuperSerialCard* m_pSSC; + class LanguageCardUnit* m_pLanguageCard; }; diff --git a/source/Debugger/Debugger_Display.cpp b/source/Debugger/Debugger_Display.cpp index 9e118b459..31478f5d5 100644 --- a/source/Debugger/Debugger_Display.cpp +++ b/source/Debugger/Debugger_Display.cpp @@ -38,6 +38,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../CPU.h" #include "../Windows/Win32Frame.h" #include "../LanguageCard.h" +#include "../CardManager.h" #include "../Memory.h" #include "../Mockingboard.h" #include "../NTSC.h" @@ -2408,7 +2409,7 @@ void _DrawSoftSwitchLanguageCardBank( RECT & rect, const int iBankDisplay, int b int iActiveBank = -1; char sText[ 4 ] = "?"; // Default to RAMWORKS if (GetCurrentExpansionMemType() == CT_RamWorksIII) { sText[0] = 'r'; iActiveBank = GetRamWorksActiveBank(); } - if (GetCurrentExpansionMemType() == CT_Saturn128K) { sText[0] = 's'; iActiveBank = GetLanguageCard()->GetActiveBank(); } + if (GetCurrentExpansionMemType() == CT_Saturn128K) { sText[0] = 's'; iActiveBank = GetCardMgr().GetLanguageCard()->GetActiveBank(); } if (iActiveBank >= 0) { diff --git a/source/LanguageCard.cpp b/source/LanguageCard.cpp index b901b37ad..246285861 100644 --- a/source/LanguageCard.cpp +++ b/source/LanguageCard.cpp @@ -38,10 +38,18 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA const UINT LanguageCardUnit::kMemModeInitialState = MF_BANK2 | MF_WRITERAM; // !INTCXROM -LanguageCardUnit::LanguageCardUnit(SS_CARDTYPE type/*=CT_LanguageCardIIe*/) : - Card(type, kSlot0), +LanguageCardUnit * LanguageCardUnit::create(UINT slot) +{ + return new LanguageCardUnit(CT_LanguageCardIIe, slot); +} + +LanguageCardUnit::LanguageCardUnit(SS_CARDTYPE type, UINT slot) : + Card(type, slot), m_uLastRamWrite(0) { + if (m_slot != LanguageCardUnit::kSlot0) + throw std::string("Card: wrong slot"); + SetMemMainLanguageCard(NULL, true); } @@ -52,12 +60,13 @@ LanguageCardUnit::~LanguageCardUnit(void) void LanguageCardUnit::InitializeIO(LPBYTE pCxRomPeripheral) { - RegisterIoHandler(kSlot0, &LanguageCardUnit::IO, &LanguageCardUnit::IO, NULL, NULL, this, NULL); + RegisterIoHandler(m_slot, &LanguageCardUnit::IO, &LanguageCardUnit::IO, NULL, NULL, this, NULL); } BYTE __stdcall LanguageCardUnit::IO(WORD PC, WORD uAddr, BYTE bWrite, BYTE uValue, ULONG nExecutedCycles) { - LanguageCardUnit* pLC = (LanguageCardUnit*) MemGetSlotParameters(kSlot0); + UINT uSlot = ((uAddr & 0xff) >> 4) - 8; + LanguageCardUnit* pLC = (LanguageCardUnit*) MemGetSlotParameters(uSlot); DWORD memmode = GetMemMode(); DWORD lastmemmode = memmode; @@ -136,12 +145,14 @@ bool LanguageCardUnit::IsOpcodeRMWabs(WORD addr) //------------------------------------- -LanguageCardSlot0::LanguageCardSlot0(SS_CARDTYPE type/*=CT_LanguageCard*/) - : LanguageCardUnit(type) +LanguageCardSlot0 * LanguageCardSlot0::create(UINT slot) { - if (m_slot != LanguageCardUnit::kSlot0) - throw std::string("Card: wrong slot"); + return new LanguageCardSlot0(CT_LanguageCard, slot); +} +LanguageCardSlot0::LanguageCardSlot0(SS_CARDTYPE type, UINT slot) + : LanguageCardUnit(type, slot) +{ m_pMemory = new BYTE[kMemBankSize]; SetMemMainLanguageCard(m_pMemory); } @@ -234,8 +245,10 @@ bool LanguageCardSlot0::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT versio //------------------------------------- -Saturn128K::Saturn128K(UINT banks) - : LanguageCardSlot0(CT_Saturn128K) +UINT Saturn128K::g_uSaturnBanksFromCmdLine = 0; + +Saturn128K::Saturn128K(UINT slot, UINT banks) + : LanguageCardSlot0(CT_Saturn128K, slot) { m_uSaturnTotalBanks = (banks == 0) ? kMaxSaturnBanks : banks; m_uSaturnActiveBank = 0; @@ -265,11 +278,6 @@ Saturn128K::~Saturn128K(void) } } -void Saturn128K::SetMemorySize(UINT banks) -{ - m_uSaturnTotalBanks = banks; -} - UINT Saturn128K::GetActiveBank(void) { return m_uSaturnActiveBank; @@ -277,7 +285,7 @@ UINT Saturn128K::GetActiveBank(void) void Saturn128K::InitializeIO(LPBYTE pCxRomPeripheral) { - RegisterIoHandler(kSlot0, &Saturn128K::IO, &Saturn128K::IO, NULL, NULL, this, NULL); + RegisterIoHandler(m_slot, &Saturn128K::IO, &Saturn128K::IO, NULL, NULL, this, NULL); } BYTE __stdcall Saturn128K::IO(WORD PC, WORD uAddr, BYTE bWrite, BYTE uValue, ULONG nExecutedCycles) @@ -301,7 +309,8 @@ BYTE __stdcall Saturn128K::IO(WORD PC, WORD uAddr, BYTE bWrite, BYTE uValue, ULO 1110 $C0NE select 16K Bank 7 1111 $C0NF select 16K Bank 8 */ - Saturn128K* pLC = (Saturn128K*) MemGetSlotParameters(kSlot0); + UINT uSlot = ((uAddr & 0xff) >> 4) - 8; + Saturn128K* pLC = (Saturn128K*) MemGetSlotParameters(uSlot); _ASSERT(pLC->m_uSaturnTotalBanks); if (!pLC->m_uSaturnTotalBanks) @@ -452,3 +461,13 @@ bool Saturn128K::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version) return true; } + +void Saturn128K::SetSaturnMemorySize(UINT banks) +{ + g_uSaturnBanksFromCmdLine = banks; +} + +UINT Saturn128K::GetSaturnMemorySize() +{ + return g_uSaturnBanksFromCmdLine; +} diff --git a/source/LanguageCard.h b/source/LanguageCard.h index d1adae033..80fd408cc 100644 --- a/source/LanguageCard.h +++ b/source/LanguageCard.h @@ -9,7 +9,9 @@ class LanguageCardUnit : public Card { public: - LanguageCardUnit(SS_CARDTYPE type = CT_LanguageCardIIe); + // in modern C++ this could be a 2nd constructor + static LanguageCardUnit * create(UINT slot); + virtual ~LanguageCardUnit(void); virtual void Init(void) {} @@ -18,7 +20,6 @@ class LanguageCardUnit : public Card virtual void InitializeIO(LPBYTE pCxRomPeripheral); - virtual void SetMemorySize(UINT banks) {} // No-op for //e and slot-0 16K LC virtual UINT GetActiveBank(void) { return 0; } // Always 0 as only 1x 16K bank virtual void SaveSnapshot(YamlSaveHelper& yamlSaveHelper) { _ASSERT(0); } // Not used for //e virtual bool LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version) { _ASSERT(0); return false; } // Not used for //e @@ -33,6 +34,9 @@ class LanguageCardUnit : public Card static const UINT kMemModeInitialState; static const UINT kSlot0 = SLOT0; +protected: + LanguageCardUnit(SS_CARDTYPE type, UINT slot); + private: UINT m_uLastRamWrite; }; @@ -44,7 +48,9 @@ class LanguageCardUnit : public Card class LanguageCardSlot0 : public LanguageCardUnit { public: - LanguageCardSlot0(SS_CARDTYPE = CT_LanguageCard); + // in modern C++ this could be a 2nd constructor + static LanguageCardSlot0 * create(UINT slot); + virtual ~LanguageCardSlot0(void); virtual void SaveSnapshot(YamlSaveHelper& yamlSaveHelper); @@ -54,6 +60,7 @@ class LanguageCardSlot0 : public LanguageCardUnit static std::string GetSnapshotCardName(void); protected: + LanguageCardSlot0(SS_CARDTYPE type, UINT slot); void SaveLCState(class YamlSaveHelper& yamlSaveHelper); void LoadLCState(class YamlLoadHelper& yamlLoadHelper); @@ -70,15 +77,17 @@ class LanguageCardSlot0 : public LanguageCardUnit class Saturn128K : public LanguageCardSlot0 { public: - Saturn128K(UINT banks); + Saturn128K(UINT slot, UINT banks); virtual ~Saturn128K(void); virtual void InitializeIO(LPBYTE pCxRomPeripheral); - virtual void SetMemorySize(UINT banks); virtual UINT GetActiveBank(void); virtual void SaveSnapshot(YamlSaveHelper& yamlSaveHelper); virtual bool LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version); + static UINT GetSaturnMemorySize(); + static void SetSaturnMemorySize(UINT banks); + static BYTE __stdcall IO(WORD PC, WORD uAddr, BYTE bWrite, BYTE uValue, ULONG nExecutedCycles); // "The boards consist of 16K banks of memory (4 banks for the 64K board, 8 banks for the 128K), accessed one at a time" - Ref: "64K/128K RAM BOARD", Saturn Systems, Ch.1 Introduction(pg-5) @@ -88,6 +97,8 @@ class Saturn128K : public LanguageCardSlot0 private: std::string GetSnapshotMemStructName(void); + static UINT g_uSaturnBanksFromCmdLine; + UINT m_uSaturnTotalBanks; // Will be > 0 if Saturn card is installed UINT m_uSaturnActiveBank; // Saturn 128K Language Card Bank 0 .. 7 LPBYTE m_aSaturnBanks[kMaxSaturnBanks]; diff --git a/source/Memory.cpp b/source/Memory.cpp index 48af597f3..9803bc46f 100644 --- a/source/Memory.cpp +++ b/source/Memory.cpp @@ -239,7 +239,6 @@ static BOOL modechanging = 0; // An Optimisation: means delay calling Upda static UINT memrompages = 1; static CNoSlotClock* g_NoSlotClock = new CNoSlotClock; -static LanguageCardUnit* g_pLanguageCard = NULL; // For all Apple II, //e and above #ifdef RAMWORKS static UINT g_uMaxExPages = 1; // user requested ram pages (default to 1 aux bank: so total = 128KB) @@ -259,7 +258,6 @@ BYTE __stdcall IO_Annunciator(WORD programcounter, WORD address, BYTE write, BYT static SS_CARDTYPE g_MemTypeAppleII = CT_Empty; static SS_CARDTYPE g_MemTypeAppleIIPlus = CT_LanguageCard; // Keep a copy so it's not lost if machine type changes, eg: A][ -> A//e -> A][ static SS_CARDTYPE g_MemTypeAppleIIe = CT_Extended80Col; // Keep a copy so it's not lost if machine type changes, eg: A//e -> A][ -> A//e -static UINT g_uSaturnBanksFromCmdLine = 0; const UINT CxRomSize = 4 * 1024; @@ -307,7 +305,7 @@ void SetExpansionMemType(const SS_CARDTYPE type) } else // Apple //e or above { - newSlot0Card = CT_Empty; // NB. No slot0 for //e + newSlot0Card = CT_LanguageCardIIe; // NB. No slot0 for //e newSlotAuxCard = CT_Extended80Col; } @@ -335,21 +333,24 @@ void SetExpansionMemType(const SS_CARDTYPE type) void CreateLanguageCard(void) { - delete g_pLanguageCard; - g_pLanguageCard = NULL; - + SS_CARDTYPE slot0CardType = GetCardMgr().QuerySlot(SLOT0); if (IsApple2PlusOrClone(GetApple2Type())) { - if (GetCardMgr().QuerySlot(SLOT0) == CT_Saturn128K) - g_pLanguageCard = new Saturn128K(g_uSaturnBanksFromCmdLine); - else if (GetCardMgr().QuerySlot(SLOT0) == CT_LanguageCard) - g_pLanguageCard = new LanguageCardSlot0; - else - g_pLanguageCard = NULL; + switch (slot0CardType) { + case CT_Empty: // OK + case CT_Saturn128K: // OK + case CT_LanguageCard: // OK + break; + default: // Anything else is invalid + GetCardMgr().Remove(SLOT0); + break; + } } else { - g_pLanguageCard = new LanguageCardUnit; + // only ever a CT_LanguageCardIIe for a //e + if (slot0CardType != CT_LanguageCardIIe) + GetCardMgr().Insert(SLOT0, CT_LanguageCardIIe); } } @@ -373,24 +374,19 @@ UINT GetRamWorksActiveBank(void) return g_uActiveBank; } -void SetSaturnMemorySize(UINT banks) -{ - g_uSaturnBanksFromCmdLine = banks; -} - // static BOOL GetLastRamWrite(void) { - if (g_pLanguageCard) - return g_pLanguageCard->GetLastRamWrite(); + if (GetCardMgr().GetLanguageCard()) + return GetCardMgr().GetLanguageCard()->GetLastRamWrite(); return 0; } static void SetLastRamWrite(BOOL count) { - if (g_pLanguageCard) - g_pLanguageCard->SetLastRamWrite(count); + if (GetCardMgr().GetLanguageCard()) + GetCardMgr().GetLanguageCard()->SetLastRamWrite(count); } // @@ -403,12 +399,6 @@ void SetMemMainLanguageCard(LPBYTE ptr, bool bMemMain /*=false*/) g_pMemMainLanguageCard = ptr; } -LanguageCardUnit* GetLanguageCard(void) -{ - _ASSERT(g_pLanguageCard); - return g_pLanguageCard; -} - LPBYTE GetCxRomPeripheral(void) { return pCxRomPeripheral; // Can be NULL if at MODE_LOGO @@ -1305,9 +1295,6 @@ void MemDestroy() RWpages[0]=NULL; #endif - delete g_pLanguageCard; - g_pLanguageCard = NULL; - memaux = NULL; memmain = NULL; memdirty = NULL; @@ -1736,11 +1723,6 @@ void MemInitializeIO(void) { InitIoHandlers(); - if (g_pLanguageCard) - g_pLanguageCard->InitializeIO(NULL); - else - RegisterIoHandler(LanguageCardUnit::kSlot0, IO_Null, IO_Null, NULL, NULL, NULL, NULL); - GetCardMgr().InitializeIO(pCxRomPeripheral); } @@ -2436,7 +2418,6 @@ static void MemLoadSnapshotAuxCommon(YamlLoadHelper& yamlLoadHelper, const std:: yamlLoadHelper.PopMap(); } - GetCardMgr().Remove(SLOT0); GetCardMgr().InsertAux(type); memaux = RWpages[g_uActiveBank]; diff --git a/source/Memory.h b/source/Memory.h index b782909fd..996a5afca 100644 --- a/source/Memory.h +++ b/source/Memory.h @@ -107,15 +107,11 @@ BYTE __stdcall MemSetPaging(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExec BYTE __stdcall IO_F8xx(WORD programcounter, WORD address, BYTE write, BYTE value, ULONG nCycles); -enum SS_CARDTYPE; void SetExpansionMemType(const SS_CARDTYPE type); SS_CARDTYPE GetCurrentExpansionMemType(void); -void CreateLanguageCard(void); void SetRamWorksMemorySize(UINT pages); UINT GetRamWorksActiveBank(void); -void SetSaturnMemorySize(UINT banks); void SetMemMainLanguageCard(LPBYTE ptr, bool bMemMain=false); -class LanguageCardUnit* GetLanguageCard(void); LPBYTE GetCxRomPeripheral(void); diff --git a/source/SaveState.cpp b/source/SaveState.cpp index 0c4b12e50..e0dc186ca 100644 --- a/source/SaveState.cpp +++ b/source/SaveState.cpp @@ -298,8 +298,6 @@ static void ParseSlots(YamlLoadHelper& yamlLoadHelper, UINT unitVersion) if (unitVersion != UNIT_SLOTS_VER) throw std::string(SS_YAML_KEY_UNIT ": Slots: Version mismatch"); - bool cardInserted[NUM_SLOTS] = {}; - while (1) { std::string scalar = yamlLoadHelper.GetMapNextSlotNumber(); @@ -390,28 +388,18 @@ static void ParseSlots(YamlLoadHelper& yamlLoadHelper, UINT unitVersion) if (slot == 0) { SetExpansionMemType(type); // calls GetCardMgr().Insert() & InsertAux() - CreateLanguageCard(); - bRes = GetLanguageCard()->LoadSnapshot(yamlLoadHelper, cardVersion); } else { GetCardMgr().Insert(slot, type); - bRes = GetCardMgr().GetRef(slot).LoadSnapshot(yamlLoadHelper, cardVersion); } - cardInserted[slot] = true; + bRes = GetCardMgr().GetRef(slot).LoadSnapshot(yamlLoadHelper, cardVersion); yamlLoadHelper.PopMap(); yamlLoadHelper.PopMap(); } - // Save-state may not contain any info about empty slots, so ensure they are set to empty - for (UINT slot = SLOT0; slot < NUM_SLOTS; slot++) - { - if (cardInserted[slot]) - continue; - GetCardMgr().Remove(slot); - } } //--- @@ -593,9 +581,6 @@ void Snapshot_SaveState(void) yamlSaveHelper.UnitHdr(GetSnapshotUnitSlotsName(), UNIT_SLOTS_VER); YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE); - if (GetCardMgr().QuerySlot(SLOT0) != CT_Empty && IsApple2PlusOrClone(GetApple2Type())) - GetLanguageCard()->SaveSnapshot(yamlSaveHelper); // Language Card or Saturn 128K - GetCardMgr().SaveSnapshot(yamlSaveHelper); } diff --git a/source/Windows/AppleWin.cpp b/source/Windows/AppleWin.cpp index 65f683fdb..aa19a6bef 100644 --- a/source/Windows/AppleWin.cpp +++ b/source/Windows/AppleWin.cpp @@ -44,6 +44,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "SaveState.h" #include "SoundCore.h" #include "Speaker.h" +#include "LanguageCard.h" #ifdef USE_SPEECH_API #include "Speech.h" #endif @@ -709,7 +710,7 @@ static void RepeatInitialization(void) #endif if (g_cmdLine.uSaturnBanks) { - SetSaturnMemorySize(g_cmdLine.uSaturnBanks); // Set number of banks before constructing Saturn card + Saturn128K::SetSaturnMemorySize(g_cmdLine.uSaturnBanks); // Set number of banks before constructing Saturn card SetExpansionMemType(CT_Saturn128K); g_cmdLine.uSaturnBanks = 0; // Don't reapply after a restart }