]> Shamusworld >> Repos - thunder/blobdiff - src/thunder.cpp
Added save states; updated application icon.
[thunder] / src / thunder.cpp
index 2914a96c5ae80eab26a7347e3e388609e6aa77ca..cb91ed1a76e2ebb1062a2a5ff06c3777c71797a8 100644 (file)
 // 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"
@@ -79,8 +79,9 @@ uint32_t banksw1, banksw2;
 // 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);
@@ -405,6 +406,104 @@ bool UnpackFonts(void)
        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
 //
@@ -610,6 +709,12 @@ WriteLog("About to enter main loop...\n");
                                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;