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