// JLH 04/04/2014 Converted to SDL 2
// JLH 04/17/2014 Removed a metric fuck-tonne of cruft, added YM2151 & MCU
// JLH 01/13/2023 Finally fixed the sprite lag problem :-D
+// JLH 01/13/2023 Added save states
//
-#define THUNDER_VERSION "1.2.1"
+#define THUNDER_VERSION "1.2.2"
#include <SDL2/SDL.h>
#include <string>
-#include <stdio.h>
#include <stdlib.h>
-#include <stdint.h>
#include <time.h>
+#include "fileio.h"
#include "gui.h"
#include "log.h"
#include "psg.h"
// MCU inputs
Byte input1, input2, input3, input4, input5;
-// Copy sprites flag
+// Miscellaneous stuff
bool copySprites = false;
+const uint8_t stateHeader[20] = "THUNDERSAVESTATE1.0";
// Function prototypes
uint8_t MCUReadMemory(uint16_t address);
return true;
}
+void SaveThunderState(const char * filename)
+{
+ WriteLog("Main: Saving Thunder state...\n");
+ FILE * file = fopen(filename, "wb");
+
+ if (!file)
+ {
+ WriteLog("Could not open file \"%s\" for writing!\n", filename);
+ return;
+ }
+
+ // Write out header
+ size_t ignored = fwrite(stateHeader, 1, 19, file);
+
+ // Write out CPUs' state
+ ignored = fwrite(&cpu1, 1, sizeof(cpu1), file);
+ ignored = fwrite(&cpu2, 1, sizeof(cpu2), file);
+ ignored = fwrite(&mcu, 1, sizeof(mcu), file);
+
+ // Write out main memory
+ ignored = fwrite(gram1, 1, 0x10000, file);
+ ignored = fwrite(mcuMem, 1, 0x10000, file);
+
+ // Write out state variables
+ WriteLong(file, banksw1);
+ WriteLong(file, banksw2);
+ fputc((uint8_t)copySprites, file);
+ fputc(input1.byte, file);
+ fputc(input2.byte, file);
+ fputc(input3.byte, file);
+ fputc(input4.byte, file);
+ fputc(input5.byte, file);
+
+ PSGSaveState(file);
+ YMSaveState(file);
+
+ fclose(file);
+}
+
+bool LoadThunderState(const char * filename)
+{
+ WriteLog("Main: Loading Thunder state...\n");
+ FILE * file = fopen(filename, "rb");
+
+ if (!file)
+ {
+ WriteLog("Could not open file \"%s\" for reading!\n", filename);
+ return false;
+ }
+
+ uint8_t buffer[19];
+ size_t ignored = fread(buffer, 1, 19, file);
+
+ // Sanity check...
+ if (memcmp(buffer, stateHeader, 19) != 0)
+ {
+ fclose(file);
+ WriteLog("File \"%s\" is not a valid Thunder save state file!\n", filename);
+ return false;
+ }
+
+ // Read CPUs' state
+ ignored = fread(&cpu1, 1, sizeof(cpu1), file);
+ ignored = fread(&cpu2, 1, sizeof(cpu2), file);
+ ignored = fread(&mcu, 1, sizeof(mcu), file);
+
+ // Read main memory
+ ignored = fread(gram1, 1, 0x10000, file);
+ ignored = fread(mcuMem, 1, 0x10000, file);
+
+ // Read in state variables
+ banksw1 = ReadLong(file);
+ banksw2 = ReadLong(file);
+ copySprites = (bool)fgetc(file);
+ input1.byte = fgetc(file);
+ input2.byte = fgetc(file);
+ input3.byte = fgetc(file);
+ input4.byte = fgetc(file);
+ input5.byte = fgetc(file);
+
+ PSGLoadState(file);
+ YMLoadState(file);
+
+ fclose(file);
+
+ // Make sure things are in a sane state before execution :-P
+ cpu1.RdMem = MainReadMemory;
+ cpu1.WrMem = MainWriteMemory;
+
+ cpu2.RdMem = SubReadMemory;
+ cpu2.WrMem = SubWriteMemory;
+
+ mcu.RdMem = MCUReadMemory;
+ mcu.WrMem = MCUWriteMemory;
+
+ return true;
+}
+
//
// Main loop
//
else if (event.key.keysym.sym == SDLK_i)
input5.bit.b0 = !input5.bit.b0;
+ // Quick'n'Dirty save state handling... :-P
+ else if (event.key.keysym.sym == SDLK_F8)
+ SaveThunderState("thun0001.state");
+ else if (event.key.keysym.sym == SDLK_F9)
+ LoadThunderState("thun0001.state");
+
#else
else if (event.key.keysym.sym == SDLK_1)
input1.bit.b0 = 0;