From c9ef6ecee1449824ef31fefc71e8e7c9afc88799 Mon Sep 17 00:00:00 2001 From: tomcw Date: Wed, 10 Jun 2020 20:56:00 +0100 Subject: [PATCH] NoSlotClock: . added to save-state (v6) via a new unit type 'Miscellaneous' . added cmd line switch '-no-nsc' to configure AppleII without an NSC --- source/Applewin.cpp | 9 +++++++++ source/Memory.cpp | 45 +++++++++++++++++++++++++++++++++++++----- source/Memory.h | 5 +++++ source/NoSlotClock.cpp | 40 +++++++++++++++++++++++++++++++++++++ source/NoSlotClock.h | 4 ++++ source/SaveState.cpp | 30 ++++++++++++++++++++++++++-- 6 files changed, 126 insertions(+), 7 deletions(-) diff --git a/source/Applewin.cpp b/source/Applewin.cpp index 4076f944..82d5c611 100644 --- a/source/Applewin.cpp +++ b/source/Applewin.cpp @@ -1318,6 +1318,7 @@ struct CmdLine bSlot0LanguageCard = false; bSlot7EmptyOnExit = false; bSwapButtons0and1 = false; + bRemoveNoSlotClock = false; bestWidth = 0; bestHeight = 0; szImageName_harddisk[HARDDISK_1] = NULL; @@ -1350,6 +1351,7 @@ struct CmdLine bool bSlotEmpty[NUM_SLOTS]; bool bSlot7EmptyOnExit; bool bSwapButtons0and1; + bool bRemoveNoSlotClock; SS_CARDTYPE slotInsert[NUM_SLOTS]; UINT bestWidth; UINT bestHeight; @@ -1802,6 +1804,10 @@ static bool ProcessCmdLine(LPSTR lpCmdLine) lpNextArg = GetNextArg(lpNextArg); g_cmdLine.strCurrentDir = lpCmdLine; } + else if (strcmp(lpCmdLine, "-no-nsc") == 0) + { + g_cmdLine.bRemoveNoSlotClock = true; + } else // unsupported { LogFileOutput("Unsupported arg: %s\n", lpCmdLine); @@ -2036,6 +2042,9 @@ static void RepeatInitialization(void) if (!g_cmdLine.strCurrentDir.empty()) SetCurrentImageDir(g_cmdLine.strCurrentDir); + if (g_cmdLine.bRemoveNoSlotClock) + MemRemoveNoSlotClock(); + MemInitialize(); LogFileOutput("Main: MemInitialize()\n"); diff --git a/source/Memory.cpp b/source/Memory.cpp index 05075352..5a5a7db1 100644 --- a/source/Memory.cpp +++ b/source/Memory.cpp @@ -210,7 +210,7 @@ static LPBYTE g_pMemMainLanguageCard = NULL; static DWORD memmode = LanguageCardUnit::kMemModeInitialState; static BOOL modechanging = 0; // An Optimisation: means delay calling UpdatePaging() for 1 instruction -static CNoSlotClock g_NoSlotClock; +static CNoSlotClock* g_NoSlotClock = new CNoSlotClock; static LanguageCardUnit* g_pLanguageCard = NULL; // For all Apple II, //e and above #ifdef RAMWORKS @@ -832,17 +832,17 @@ static BYTE __stdcall IO_Cxxx(WORD programcounter, WORD address, BYTE write, BYT } } - if (IsPotentialNoSlotClockAccess(address)) + if (g_NoSlotClock && IsPotentialNoSlotClockAccess(address)) { if (!write) { int data = 0; - if (g_NoSlotClock.Read(address, data)) + if (g_NoSlotClock->Read(address, data)) return (BYTE) data; } else { - g_NoSlotClock.Write(address); + g_NoSlotClock->Write(address); return 0; } } @@ -1949,7 +1949,8 @@ void MemReset() z80_reset(); // NB. Also called above in CpuInitialize() - g_NoSlotClock.Reset(); // NB. Power-cycle, but not RESET signal + if (g_NoSlotClock) + g_NoSlotClock->Reset(); // NB. Power-cycle, but not RESET signal } //=========================================================================== @@ -2136,6 +2137,26 @@ bool MemGetAnnunciator(UINT annunciator) //=========================================================================== +bool MemHasNoSlotClock(void) +{ + return g_NoSlotClock != NULL; +} + +void MemInsertNoSlotClock(void) +{ + if (!MemHasNoSlotClock()) + g_NoSlotClock = new CNoSlotClock; + g_NoSlotClock->Reset(); +} + +void MemRemoveNoSlotClock(void) +{ + delete g_NoSlotClock; + g_NoSlotClock = NULL; +} + +//=========================================================================== + // NB. Don't need to save 'modechanging', as this is just an optimisation to save calling UpdatePaging() twice. // . If we were to save the state when 'modechanging' is set, then on restoring the state, the 6502 code will immediately update the read memory mode. // . This will work correctly. @@ -2452,3 +2473,17 @@ bool MemLoadSnapshotAux(YamlLoadHelper& yamlLoadHelper, UINT unitVersion) return true; } + +void NoSlotClockSaveSnapshot(YamlSaveHelper& yamlSaveHelper) +{ + if (g_NoSlotClock) + g_NoSlotClock->SaveSnapshot(yamlSaveHelper); +} + +void NoSlotClockLoadSnapshot(YamlLoadHelper& yamlLoadHelper) +{ + if (!g_NoSlotClock) + g_NoSlotClock = new CNoSlotClock; + + g_NoSlotClock->LoadSnapshot(yamlLoadHelper); +} diff --git a/source/Memory.h b/source/Memory.h index 6226b996..2e65ba18 100644 --- a/source/Memory.h +++ b/source/Memory.h @@ -82,11 +82,16 @@ void MemResetPaging (); void MemUpdatePaging(BOOL initialize); LPVOID MemGetSlotParameters (UINT uSlot); bool MemGetAnnunciator(UINT annunciator); +bool MemHasNoSlotClock(void); +void MemInsertNoSlotClock(void); +void MemRemoveNoSlotClock(void); std::string MemGetSnapshotUnitAuxSlotName(void); void MemSaveSnapshot(class YamlSaveHelper& yamlSaveHelper); bool MemLoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT unitVersion); void MemSaveSnapshotAux(class YamlSaveHelper& yamlSaveHelper); bool MemLoadSnapshotAux(class YamlLoadHelper& yamlLoadHelper, UINT unitVersion); +void NoSlotClockSaveSnapshot(YamlSaveHelper& yamlSaveHelper); +void NoSlotClockLoadSnapshot(YamlLoadHelper& yamlLoadHelper); BYTE __stdcall IO_Null(WORD programcounter, WORD address, BYTE write, BYTE value, ULONG nCycles); diff --git a/source/NoSlotClock.cpp b/source/NoSlotClock.cpp index c25e06c2..25a330e2 100644 --- a/source/NoSlotClock.cpp +++ b/source/NoSlotClock.cpp @@ -41,6 +41,7 @@ All the other drivers and utilities available to me don't define the DOW mapping #include "StdAfx.h" #include "NoSlotClock.h" +#include "YamlHelper.h" CNoSlotClock::CNoSlotClock() : @@ -166,6 +167,45 @@ void CNoSlotClock::PopulateClockRegister() m_ClockRegister.WriteNibble(year / 10); } +#define SS_YAML_KEY_CLOCK_REGISTER_ENABLED "Clock Register Enabled" +#define SS_YAML_KEY_WRITE_ENABLED "Write Enabled" +#define SS_YAML_KEY_CLOCK_REGISTER_MASK "Clock Register Mask" +#define SS_YAML_KEY_CLOCK_REGISTER "Clock Register" +#define SS_YAML_KEY_COMPARISON_REGISTER_MASK "Comparison Register Mask" +#define SS_YAML_KEY_COMPARISON_REGISTER "Comparison Register" + +std::string CNoSlotClock::GetSnapshotStructName(void) +{ + static const std::string name("No Slot Clock"); + return name; +} + +void CNoSlotClock::SaveSnapshot(YamlSaveHelper& yamlSaveHelper) +{ + YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", GetSnapshotStructName().c_str()); + yamlSaveHelper.SaveBool(SS_YAML_KEY_CLOCK_REGISTER_ENABLED, m_bClockRegisterEnabled); + yamlSaveHelper.SaveBool(SS_YAML_KEY_WRITE_ENABLED, m_bWriteEnabled); + yamlSaveHelper.SaveHexUint64(SS_YAML_KEY_CLOCK_REGISTER_MASK, m_ClockRegister.m_Mask); + yamlSaveHelper.SaveHexUint64(SS_YAML_KEY_CLOCK_REGISTER, m_ClockRegister.m_Register); + yamlSaveHelper.SaveHexUint64(SS_YAML_KEY_COMPARISON_REGISTER_MASK, m_ComparisonRegister.m_Mask); + yamlSaveHelper.SaveHexUint64(SS_YAML_KEY_COMPARISON_REGISTER, m_ComparisonRegister.m_Register); +} + +void CNoSlotClock::LoadSnapshot(YamlLoadHelper& yamlLoadHelper) +{ + if (!yamlLoadHelper.GetSubMap(GetSnapshotStructName())) + return; + + m_bClockRegisterEnabled = yamlLoadHelper.LoadBool(SS_YAML_KEY_CLOCK_REGISTER_ENABLED); + m_bWriteEnabled = yamlLoadHelper.LoadBool(SS_YAML_KEY_WRITE_ENABLED); + m_ClockRegister.m_Mask = yamlLoadHelper.LoadUint64(SS_YAML_KEY_CLOCK_REGISTER_MASK); + m_ClockRegister.m_Register = yamlLoadHelper.LoadUint64(SS_YAML_KEY_CLOCK_REGISTER); + m_ComparisonRegister.m_Mask = yamlLoadHelper.LoadUint64(SS_YAML_KEY_COMPARISON_REGISTER_MASK); + m_ComparisonRegister.m_Register = yamlLoadHelper.LoadUint64(SS_YAML_KEY_COMPARISON_REGISTER); + + yamlLoadHelper.PopMap(); +} + CNoSlotClock::RingRegister64::RingRegister64() { Reset(); diff --git a/source/NoSlotClock.h b/source/NoSlotClock.h index 68706bb0..f2f773ad 100644 --- a/source/NoSlotClock.h +++ b/source/NoSlotClock.h @@ -57,6 +57,9 @@ public: bool ClockRead(int& data); void ClockWrite(int address); + void SaveSnapshot(class YamlSaveHelper& yamlSaveHelper); + void LoadSnapshot(class YamlLoadHelper& yamlLoadHelper); + bool m_bClockRegisterEnabled; bool m_bWriteEnabled; RingRegister64 m_ClockRegister; @@ -64,6 +67,7 @@ public: private: void PopulateClockRegister(); + std::string GetSnapshotStructName(void); static const UINT64 kClockInitSequence = 0x5CA33AC55CA33AC5; }; diff --git a/source/SaveState.cpp b/source/SaveState.cpp index 8a070e60..4bd044f7 100644 --- a/source/SaveState.cpp +++ b/source/SaveState.cpp @@ -71,10 +71,13 @@ static YamlHelper yamlHelper; // v3: Extended: memory (added 'AnnunciatorN') // v4: Extended: video (added 'Video Refresh Rate') // v5: Extended: cpu (added 'Defer IRQ By 1 Opcode') -#define UNIT_APPLE2_VER 5 +// v6: Added 'Unit Miscellaneous' for NoSlotClock(NSC) +#define UNIT_APPLE2_VER 6 #define UNIT_SLOTS_VER 1 +#define UNIT_MISC_VER 1 + //----------------------------------------------------------------------------- void Snapshot_SetFilename(const std::string & strPathname) @@ -134,6 +137,12 @@ static std::string GetSnapshotUnitSlotsName(void) return name; } +static std::string GetSnapshotUnitMiscName(void) +{ + static const std::string name("Miscellaneous"); + return name; +} + #define SS_YAML_KEY_MODEL "Model" #define SS_YAML_VALUE_APPLE2 "Apple][" @@ -353,6 +362,9 @@ static void ParseUnit(void) if (unit == GetSnapshotUnitApple2Name()) { ParseUnitApple2(yamlLoadHelper, unitVersion); + + if (unitVersion < 6) MemInsertNoSlotClock(); // NSC always inserted + else MemRemoveNoSlotClock(); // NSC only add if there's a misc unit } else if (unit == MemGetSnapshotUnitAuxSlotName()) { @@ -362,6 +374,11 @@ static void ParseUnit(void) { ParseSlots(yamlLoadHelper, unitVersion); } + else if (unit == GetSnapshotUnitMiscName()) + { + // NB. could extend for other misc devices - see how ParseSlots() calls GetMapNextSlotNumber() + NoSlotClockLoadSnapshot(yamlLoadHelper); + } else { throw std::string(SS_YAML_KEY_UNIT ": Unknown type: " ) + unit; @@ -400,7 +417,7 @@ static void Snapshot_LoadState_v2(void) m_ConfigNew.m_bEnableHDD = false; //m_ConfigNew.m_bEnableTheFreezesF8Rom = ?; // todo: when support saving config - MemReset(); // Also calls CpuInitialize(), CNoSlotClock.Reset() + MemReset(); // Also calls CpuInitialize() PravetsReset(); if (g_CardMgr.IsSSCInstalled()) @@ -570,6 +587,15 @@ void Snapshot_SaveState(void) if (g_CardMgr.QuerySlot(SLOT7) == CT_GenericHDD) HD_SaveSnapshot(yamlSaveHelper); } + + // Miscellaneous + if (MemHasNoSlotClock()) + { + yamlSaveHelper.UnitHdr(GetSnapshotUnitMiscName(), UNIT_MISC_VER); + YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE); + + NoSlotClockSaveSnapshot(yamlSaveHelper); + } } catch(std::string szMessage) {