diff --git a/BizHawk.Emulation.Cores/Computers/MSX/LibMSX.cs b/BizHawk.Emulation.Cores/Computers/MSX/LibMSX.cs index b03586b41b..e5d298a588 100644 --- a/BizHawk.Emulation.Cores/Computers/MSX/LibMSX.cs +++ b/BizHawk.Emulation.Cores/Computers/MSX/LibMSX.cs @@ -63,6 +63,26 @@ namespace BizHawk.Emulation.Cores.Computers.MSX #endregion + #region State Save / Load + + /// + /// Save State + /// + /// opaque state pointer + /// save buffer + [DllImport("MSXHAWK.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern void MSX_save_state(IntPtr core, byte[] saver); + + /// + /// Load State + /// + /// opaque state pointer + /// load buffer + [DllImport("MSXHAWK.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern void MSX_load_state(IntPtr core, byte[] loader); + + #endregion + #region Memory Domain Functions /// diff --git a/BizHawk.Emulation.Cores/Computers/MSX/MSX.IStatable.cs b/BizHawk.Emulation.Cores/Computers/MSX/MSX.IStatable.cs index 06a3f664b0..05d0a907d2 100644 --- a/BizHawk.Emulation.Cores/Computers/MSX/MSX.IStatable.cs +++ b/BizHawk.Emulation.Cores/Computers/MSX/MSX.IStatable.cs @@ -1,4 +1,5 @@ -using System.IO; +using System; +using System.IO; using BizHawk.Common; using BizHawk.Emulation.Common; @@ -40,14 +41,6 @@ namespace BizHawk.Emulation.Cores.Computers.MSX private void SyncState(Serializer ser) { - byte[] core = null; - if (ser.IsWriter) - { - using var ms = new MemoryStream(); - ms.Close(); - core = ms.ToArray(); - } - ser.BeginSection("MSX"); if (SaveRAM != null) @@ -65,7 +58,15 @@ namespace BizHawk.Emulation.Cores.Computers.MSX if (ser.IsReader) { - SyncAllByteArrayDomains(); + ser.Sync(nameof(MSX_core), ref MSX_core, false); + LibMSX.MSX_load_state(MSX_Pntr, MSX_core); + Console.WriteLine("here1"); + } + else + { + LibMSX.MSX_save_state(MSX_Pntr, MSX_core); + ser.Sync(nameof(MSX_core), ref MSX_core, false); + Console.WriteLine("here2"); } } } diff --git a/BizHawk.Emulation.Cores/Computers/MSX/MSX.cs b/BizHawk.Emulation.Cores/Computers/MSX/MSX.cs index 83216bbd44..1d34cbb1ce 100644 --- a/BizHawk.Emulation.Cores/Computers/MSX/MSX.cs +++ b/BizHawk.Emulation.Cores/Computers/MSX/MSX.cs @@ -60,6 +60,7 @@ namespace BizHawk.Emulation.Cores.Computers.MSX } IntPtr MSX_Pntr { get; set; } = IntPtr.Zero; + byte[] MSX_core = new byte[0x20000]; // Constants private const int BankSize = 16384; diff --git a/libHawk/MSXHawk/MSXHawk/Core.h b/libHawk/MSXHawk/MSXHawk/Core.h index 11a638f0a9..844067c550 100644 --- a/libHawk/MSXHawk/MSXHawk/Core.h +++ b/libHawk/MSXHawk/MSXHawk/Core.h @@ -108,6 +108,26 @@ namespace MSXHawk return psg.sampleclock; } + #pragma region State Save / Load + + void SaveState(uint8_t* saver) + { + saver = vdp.SaveState(saver); + saver = cpu.SaveState(saver); + saver = psg.SaveState(saver); + saver = MemMap.SaveState(saver); + } + + void LoadState(uint8_t* loader) + { + loader = vdp.LoadState(loader); + loader = cpu.LoadState(loader); + loader = psg.LoadState(loader); + loader = MemMap.LoadState(loader); + } + + #pragma endregion + #pragma region Memory Domain Functions uint8_t GetSysBus(uint32_t addr) diff --git a/libHawk/MSXHawk/MSXHawk/MSXHawk.cpp b/libHawk/MSXHawk/MSXHawk/MSXHawk.cpp index 8480c4f676..692eb7cbbb 100644 --- a/libHawk/MSXHawk/MSXHawk/MSXHawk.cpp +++ b/libHawk/MSXHawk/MSXHawk/MSXHawk.cpp @@ -48,6 +48,20 @@ MSXHAWK_EXPORT uint32_t MSX_get_audio(MSXCore* p, uint32_t* dest_L, uint32_t* de return p->GetAudio(dest_L, dest_R, n_samp_L, n_samp_R); } +#pragma region State Save / Load + +// save state +MSXHAWK_EXPORT void MSX_save_state(MSXCore* p, uint8_t* saver) +{ + p->SaveState(saver); +} + +// load state +MSXHAWK_EXPORT void MSX_load_state(MSXCore* p, uint8_t* loader) +{ + p->LoadState(loader); +} + #pragma endregion #pragma region Memory Domain Functions diff --git a/libHawk/MSXHawk/MSXHawk/Memory.cpp b/libHawk/MSXHawk/MSXHawk/Memory.cpp index 2c36592775..23c6cc4ba8 100644 --- a/libHawk/MSXHawk/MSXHawk/Memory.cpp +++ b/libHawk/MSXHawk/MSXHawk/Memory.cpp @@ -155,9 +155,4 @@ namespace MSXHawk } } } - - - - - } \ No newline at end of file diff --git a/libHawk/MSXHawk/MSXHawk/Memory.h b/libHawk/MSXHawk/MSXHawk/Memory.h index 8ecef841d9..15ffa413a3 100644 --- a/libHawk/MSXHawk/MSXHawk/Memory.h +++ b/libHawk/MSXHawk/MSXHawk/Memory.h @@ -14,26 +14,22 @@ namespace MSXHawk class MemoryManager { public: - MemoryManager() - { - - }; VDP* vdp_pntr; SN76489sms* psg_pntr; Z80A* cpu_pntr; - uint8_t* rom; + + // initialized by core loading, not savestated uint32_t rom_size; uint32_t rom_mapper; - uint8_t ram[0x2000]; + // State bool PortDEEnabled = false; bool lagged; bool start_pressed; uint8_t controller_byte_1, controller_byte_2; - uint8_t Port01 = 0xFF; uint8_t Port02 = 0xFF; uint8_t Port03 = 0x00; @@ -41,11 +37,27 @@ namespace MSXHawk uint8_t Port05 = 0x00; uint8_t Port3E = 0xAF; uint8_t Port3F = 0xFF; - uint8_t PortDE = 0x00; - + uint8_t PortDE = 0x00; + uint8_t reg_FFFC, reg_FFFD, reg_FFFE, reg_FFFF; + uint8_t ram[0x2000]; uint8_t cart_ram[0x8000]; - uint8_t reg_FFFC, reg_FFFD, reg_FFFE, reg_FFFF; + MemoryManager() + { + + }; + + uint8_t HardwareRead(uint32_t value); + + void HardwareWrite(uint32_t addr, uint8_t value); + + void remap_ROM_0(); + + void remap_ROM_1(); + + void remap_ROM_2(); + + void remap_RAM(); void Load_ROM(uint8_t* ext_rom, uint32_t ext_rom_size, uint32_t ext_rom_mapper) { @@ -64,18 +76,6 @@ namespace MSXHawk remap_RAM(); } - uint8_t HardwareRead(uint32_t value); - - void HardwareWrite(uint32_t addr, uint8_t value); - - void remap_ROM_0(); - - void remap_ROM_1(); - - void remap_ROM_2(); - - void remap_RAM(); - void MemoryWrite(uint32_t addr, uint8_t value) { switch (addr) @@ -146,5 +146,68 @@ namespace MSXHawk return value; } + + #pragma region State Save / Load + + uint8_t* SaveState(uint8_t* saver) + { + *saver = (uint8_t)(PortDEEnabled ? 1 : 0); saver++; + *saver = (uint8_t)(lagged ? 1 : 0); saver++; + *saver = (uint8_t)(start_pressed ? 1 : 0); saver++; + + *saver = controller_byte_1; saver++; + *saver = controller_byte_2; saver++; + *saver = Port01; saver++; + *saver = Port02; saver++; + *saver = Port03; saver++; + *saver = Port04; saver++; + *saver = Port05; saver++; + *saver = Port3E; saver++; + *saver = Port3F; saver++; + *saver = PortDE; saver++; + *saver = reg_FFFC; saver++; + *saver = reg_FFFD; saver++; + *saver = reg_FFFE; saver++; + *saver = reg_FFFF; saver++; + + std::memcpy(saver, &ram, 0x2000); saver += 0x2000; + std::memcpy(saver, &cart_ram, 0x8000); saver += 0x8000; + + return saver; + } + + uint8_t* LoadState(uint8_t* loader) + { + PortDEEnabled = *loader == 1; loader++; + lagged = *loader == 1; loader++; + start_pressed = *loader == 1; loader++; + + controller_byte_1 = *loader; loader++; + controller_byte_2 = *loader; loader++; + Port01 = *loader; loader++; + Port02 = *loader; loader++; + Port03 = *loader; loader++; + Port04 = *loader; loader++; + Port05 = *loader; loader++; + Port3E = *loader; loader++; + Port3F = *loader; loader++; + PortDE = *loader; loader++; + reg_FFFC = *loader; loader++; + reg_FFFD = *loader; loader++; + reg_FFFE = *loader; loader++; + reg_FFFF = *loader; loader++; + + std::memcpy(&ram, loader, 0x2000); loader += 0x2000; + std::memcpy(&cart_ram, loader, 0x2000); loader += 0x2000; + + remap_ROM_0(); + remap_ROM_1(); + remap_ROM_2(); + remap_RAM(); + + return loader; + } + + #pragma endregion }; } \ No newline at end of file diff --git a/libHawk/MSXHawk/MSXHawk/PSG.h b/libHawk/MSXHawk/MSXHawk/PSG.h index 37632cbda4..de535cd9bd 100644 --- a/libHawk/MSXHawk/MSXHawk/PSG.h +++ b/libHawk/MSXHawk/MSXHawk/PSG.h @@ -239,7 +239,7 @@ namespace MSXHawk #pragma region State Save / Load - void SaveState(uint8_t* saver) + uint8_t* SaveState(uint8_t* saver) { *saver = (uint8_t)(vol_tone ? 1 : 0); saver++; *saver = (uint8_t)(noise_type ? 1 : 0); saver++; @@ -292,10 +292,12 @@ namespace MSXHawk *saver = (uint8_t)((old_sample_L >> 16) & 0xFF); saver++; *saver = (uint8_t)((old_sample_L >> 24) & 0xFF); saver++; *saver = (uint8_t)(old_sample_R & 0xFF); saver++; *saver = (uint8_t)((old_sample_R >> 8) & 0xFF); saver++; - *saver = (uint8_t)((old_sample_R >> 16) & 0xFF); saver++; *saver = (uint8_t)((old_sample_R >> 24) & 0xFF); saver++; + *saver = (uint8_t)((old_sample_R >> 16) & 0xFF); saver++; *saver = (uint8_t)((old_sample_R >> 24) & 0xFF); saver++; + + return saver; } - void LoadState(uint8_t* loader) + uint8_t* LoadState(uint8_t* loader) { vol_tone = *loader == 1; loader++; noise_type = *loader == 1; loader++; @@ -349,6 +351,8 @@ namespace MSXHawk old_sample_R = *loader; loader++; old_sample_R |= (*loader << 8); loader++; old_sample_R |= (*loader << 16); loader++; old_sample_R |= (*loader << 24); loader++; + + return loader; } #pragma endregion diff --git a/libHawk/MSXHawk/MSXHawk/VDP.h b/libHawk/MSXHawk/MSXHawk/VDP.h index 719a87dfee..b8081f74af 100644 --- a/libHawk/MSXHawk/MSXHawk/VDP.h +++ b/libHawk/MSXHawk/MSXHawk/VDP.h @@ -1201,7 +1201,7 @@ namespace MSXHawk #pragma region State Save / Load - void SaveState(uint8_t* saver) + uint8_t* SaveState(uint8_t* saver) { *saver = (uint8_t)(VdpWaitingForLatchInt ? 1 : 0); saver++; *saver = (uint8_t)(VIntPending ? 1 : 0); saver++; @@ -1249,9 +1249,11 @@ namespace MSXHawk *saver = (uint8_t)(ScanLine & 0xFF); saver++; *saver = (uint8_t)((ScanLine >> 8) & 0xFF); saver++; *saver = (uint8_t)((ScanLine >> 16) & 0xFF); saver++; *saver = (uint8_t)((ScanLine >> 24) & 0xFF); saver++; + + return saver; } - void LoadState(uint8_t* loader) + uint8_t* LoadState(uint8_t* loader) { VdpWaitingForLatchInt = *loader == 1; loader++; VIntPending = *loader == 1; loader++; @@ -1300,11 +1302,11 @@ namespace MSXHawk ScanLine = *loader; loader++; ScanLine |= (*loader << 8); loader++; ScanLine |= (*loader << 16); loader++; ScanLine |= (*loader << 24); loader++; - for (uint32_t i = 0; i < 16; i++) - WriteRegister(i, Registers[i]); - for (uint16_t i = 0; i < 0x4000; i++) - UpdatePatternBuffer(i, VRAM[i]); + for (uint32_t i = 0; i < 16; i++) { WriteRegister(i, Registers[i]); } + for (uint16_t i = 0; i < 0x4000; i++) { UpdatePatternBuffer(i, VRAM[i]); } UpdatePrecomputedPalette(); + + return loader; } #pragma endregion diff --git a/libHawk/MSXHawk/MSXHawk/Z80A.h b/libHawk/MSXHawk/MSXHawk/Z80A.h index 3d99f15408..10bcc7c72f 100644 --- a/libHawk/MSXHawk/MSXHawk/Z80A.h +++ b/libHawk/MSXHawk/MSXHawk/Z80A.h @@ -70,7 +70,7 @@ namespace MSXHawk uint32_t BUSRQ[19] = {}; // fixed size - do not change at runtime uint32_t MEMRQ[19] = {}; // fixed size - do not change at runtime - long TotalExecutedCycles; + uint64_t TotalExecutedCycles; // non-state variables uint32_t Ztemp1, Ztemp2, Ztemp3, Ztemp4; @@ -962,46 +962,6 @@ namespace MSXHawk cur_instr[33] = d33; cur_instr[34] = d34; cur_instr[35] = d35; cur_instr[36] = d36; cur_instr[37] = d37; } - /* - // State Save/Load - void SyncState(Serializer ser) - { - ser.BeginSection(nameof(Z80A)); - ser.Sync(nameof(Regs), ref Regs, false); - ser.Sync("NMI", ref nonMaskableInterrupt); - ser.Sync("NMIPending", ref nonMaskableInterruptPending); - ser.Sync("IM", ref interruptMode); - ser.Sync("IFF1", ref iff1); - ser.Sync("IFF2", ref iff2); - ser.Sync("Halted", ref halted); - ser.Sync(nameof(I_skip), ref I_skip); - ser.Sync("ExecutedCycles", ref TotalExecutedCycles); - ser.Sync(nameof(EI_pending), ref EI_pending); - - ser.Sync(nameof(instr_pntr), ref instr_pntr); - ser.Sync(nameof(bus_pntr), ref bus_pntr); - ser.Sync(nameof(mem_pntr), ref mem_pntr); - ser.Sync(nameof(irq_pntr), ref irq_pntr); - ser.Sync(nameof(cur_instr), ref cur_instr, false); - ser.Sync(nameof(BUSRQ), ref BUSRQ, false); - ser.Sync(nameof(IRQS), ref IRQS); - ser.Sync(nameof(MEMRQ), ref MEMRQ, false); - ser.Sync(nameof(opcode), ref opcode); - ser.Sync(nameof(FlagI), ref FlagI); - ser.Sync(nameof(FlagW), ref FlagW); - - ser.Sync(nameof(NO_prefix), ref NO_prefix); - ser.Sync(nameof(CB_prefix), ref CB_prefix); - ser.Sync(nameof(IX_prefix), ref IX_prefix); - ser.Sync(nameof(IY_prefix), ref IY_prefix); - ser.Sync(nameof(IXCB_prefix), ref IXCB_prefix); - ser.Sync(nameof(IYCB_prefix), ref IYCB_prefix); - ser.Sync(nameof(EXTD_prefix), ref EXTD_prefix); - ser.Sync(nameof(PRE_SRC), ref PRE_SRC); - - ser.EndSection(); - } - */ void InitTableParity() { @@ -4553,7 +4513,7 @@ namespace MSXHawk reg_state.append(val_char_1, 4); reg_state.append(" Cy:"); - reg_state.append(val_char_1, sprintf_s(val_char_1, 32, "%16u", TotalExecutedCycles)); + reg_state.append(val_char_1, sprintf_s(val_char_1, 32, "%16u", (unsigned int)TotalExecutedCycles)); reg_state.append(" "); reg_state.append(FlagCget() ? "C" : "c"); @@ -5168,7 +5128,7 @@ namespace MSXHawk #pragma region State Save / Load - void SaveState(uint8_t* saver) + uint8_t* SaveState(uint8_t* saver) { *saver = (uint8_t)(NO_prefix ? 1 : 0); saver++; *saver = (uint8_t)(CB_prefix ? 1 : 0); saver++; @@ -5229,9 +5189,16 @@ namespace MSXHawk *saver = (uint8_t)(MEMRQ[i] & 0xFF); saver++; *saver = (uint8_t)((MEMRQ[i] >> 8) & 0xFF); saver++; *saver = (uint8_t)((MEMRQ[i] >> 16) & 0xFF); saver++; *saver = (uint8_t)((MEMRQ[i] >> 24) & 0xFF); saver++; } + + *saver = (uint8_t)(TotalExecutedCycles & 0xFF); saver++; *saver = (uint8_t)((TotalExecutedCycles >> 8) & 0xFF); saver++; + *saver = (uint8_t)((TotalExecutedCycles >> 16) & 0xFF); saver++; *saver = (uint8_t)((TotalExecutedCycles >> 24) & 0xFF); saver++; + *saver = (uint8_t)((TotalExecutedCycles >> 16) & 0x32); saver++; *saver = (uint8_t)((TotalExecutedCycles >> 40) & 0xFF); saver++; + *saver = (uint8_t)((TotalExecutedCycles >> 16) & 0x48); saver++; *saver = (uint8_t)((TotalExecutedCycles >> 56) & 0xFF); saver++; + + return saver; } - void LoadState(uint8_t* loader) + uint8_t* LoadState(uint8_t* loader) { NO_prefix = *loader == 1; loader++; CB_prefix = *loader == 1; loader++; @@ -5292,6 +5259,13 @@ namespace MSXHawk MEMRQ[i] = *loader; loader++; MEMRQ[i] |= (*loader << 8); loader++; MEMRQ[i] |= (*loader << 16); loader++; MEMRQ[i] |= (*loader << 24); loader++; } + + TotalExecutedCycles = *loader; loader++; TotalExecutedCycles |= (*loader << 8); loader++; + TotalExecutedCycles |= (*loader << 16); loader++; TotalExecutedCycles |= (*loader << 24); loader++; + TotalExecutedCycles |= ((uint64_t)*loader << 32); loader++; TotalExecutedCycles |= ((uint64_t)*loader << 40); loader++; + TotalExecutedCycles |= ((uint64_t)*loader << 48); loader++; TotalExecutedCycles |= ((uint64_t)*loader << 56); loader++; + + return loader; } #pragma endregion