]> Shamusworld >> Repos - apple2/commitdiff
Added state save/load support.
authorShamus Hammons <jlhamm@acm.org>
Wed, 2 Apr 2014 18:00:00 +0000 (13:00 -0500)
committerShamus Hammons <jlhamm@acm.org>
Wed, 2 Apr 2014 18:00:00 +0000 (13:00 -0500)
Makefile
src/apple2.cpp
src/charset.cpp
src/charset.h
src/floppy.cpp
src/floppy.h

index 340790a074d69be685fe754f1968b867038ac8cd..60547dfee28c2daaed93708e85508df9847c39ff 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@
 #
 # by James Hammons
 # (C) 2005 Underground Software
-# This software is licensed under the GPL v2
+# This software is licensed under the GPL v3
 #
 
 FIND = find
index 0b3ab42e1e26c3a7f7b382753a0167d68f3a2a36..26cab227e64c2923a83656d14b7befba631621b4 100644 (file)
@@ -245,14 +245,118 @@ bool LoadImg(char * filename, uint8_t * ram, int size)
 }
 
 
+const uint8_t stateHeader[19] = "APPLE2SAVESTATE1.0";
 static void SaveApple2State(const char * filename)
 {
+       WriteLog("Main: Saving Apple2 state...\n");
+       FILE * file = fopen(filename, "wb");
+
+       if (!file)
+       {
+               WriteLog("Could not open file \"%s\" for writing!\n", filename);
+               return;
+       }
+
+       // Write out header
+       fwrite(stateHeader, 1, 18, file);
+
+       // Write out CPU state
+       fwrite(&mainCPU, 1, sizeof(mainCPU), file);
+
+       // Write out main memory
+       fwrite(ram, 1, 0x10000, file);
+       fwrite(ram2, 1, 0x10000, file);
+
+       // Write out state variables
+       fputc((uint8_t)keyDown, file);
+       fputc((uint8_t)openAppleDown, file);
+       fputc((uint8_t)closedAppleDown, file);
+       fputc((uint8_t)store80Mode, file);
+       fputc((uint8_t)vbl, file);
+       fputc((uint8_t)slotCXROM, file);
+       fputc((uint8_t)slotC3ROM, file);
+       fputc((uint8_t)ramrd, file);
+       fputc((uint8_t)ramwrt, file);
+       fputc((uint8_t)altzp, file);
+       fputc((uint8_t)ioudis, file);
+       fputc((uint8_t)dhires, file);
+       fputc((uint8_t)flash, file);
+       fputc((uint8_t)textMode, file);
+       fputc((uint8_t)mixedMode, file);
+       fputc((uint8_t)displayPage2, file);
+       fputc((uint8_t)hiRes, file);
+       fputc((uint8_t)alternateCharset, file);
+       fputc((uint8_t)col80Mode, file);
+       fputc(lcState, file);
+
+       // Write out floppy state
+       floppyDrive.SaveState(file);
+       fclose(file);
 }
 
 
 static bool LoadApple2State(const char * filename)
 {
-       return false;
+       WriteLog("Main: Loading Apple2 state...\n");
+       FILE * file = fopen(filename, "rb");
+
+       if (!file)
+       {
+               WriteLog("Could not open file \"%s\" for reading!\n", filename);
+               return false;
+       }
+
+       uint8_t buffer[18];
+       fread(buffer, 1, 18, file);
+
+       // Sanity check...
+       if (memcmp(buffer, stateHeader, 18) != 0)
+       {
+               fclose(file);
+               WriteLog("File \"%s\" is not a valid Apple2 save state file!\n", filename);
+               return false;
+       }
+
+       // Read CPU state
+       fread(&mainCPU, 1, sizeof(mainCPU), file);
+
+       // Read main memory
+       fread(ram, 1, 0x10000, file);
+       fread(ram2, 1, 0x10000, file);
+
+       // Read in state variables
+       keyDown = (bool)fgetc(file);
+       openAppleDown = (bool)fgetc(file);
+       closedAppleDown = (bool)fgetc(file);
+       store80Mode = (bool)fgetc(file);
+       vbl = (bool)fgetc(file);
+       slotCXROM = (bool)fgetc(file);
+       slotC3ROM = (bool)fgetc(file);
+       ramrd = (bool)fgetc(file);
+       ramwrt = (bool)fgetc(file);
+       altzp = (bool)fgetc(file);
+       ioudis = (bool)fgetc(file);
+       dhires = (bool)fgetc(file);
+       flash = (bool)fgetc(file);
+       textMode = (bool)fgetc(file);
+       mixedMode = (bool)fgetc(file);
+       displayPage2 = (bool)fgetc(file);
+       hiRes = (bool)fgetc(file);
+       alternateCharset = (bool)fgetc(file);
+       col80Mode = (bool)fgetc(file);
+       lcState = fgetc(file);
+
+       // Read in floppy state
+       floppyDrive.LoadState(file);
+
+       fclose(file);
+
+       // Make sure things are in a sane state before execution :-P
+       mainCPU.RdMem = AppleReadMem;
+       mainCPU.WrMem = AppleWriteMem;
+       ResetMMUPointers();
+
+       return true;
 }
 
 
@@ -322,7 +426,6 @@ int main(int /*argc*/, char * /*argv*/[])
 //Load up disk image from config file (for now)...
        floppyDrive.LoadImage(settings.diskImagePath1, 0);
        floppyDrive.LoadImage(settings.diskImagePath2, 1);
-//     floppyDrive.LoadImage("./disks/temp.nib", 1);   // Load temp .nib file into second drive...
 
        WriteLog("About to initialize video...\n");
 
index 0b32c694a0731d6fa5f45a43538b69786bc6fd03..3e436237ee55bb5a603ec8a6e4b77f8cd0990bff 100644 (file)
@@ -10,7 +10,9 @@
 
 // Apple II character set has 64 chars (56 bytes for each character)
 
-char textChar[0x0E00] = {
+#include <stdint.h>
+
+uint8_t textChar[0x0E00] = {
        0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
@@ -79,7 +81,7 @@ char textChar[0x0E00] = {
 
 // Apple IIe/IIc character set has 256 chars (56 bytes for each character)
 
-char textChar2e[0x3800] = {
+uint8_t textChar2e[0x3800] = {
        0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
index f0b3291c8af6ccd77beaf2c0adba104f404c376d..126a6496e03ca56071cb5e4b6b11ee9e42a3e347 100644 (file)
@@ -1,8 +1,10 @@
 #ifndef __CHARSET_H__
 #define __CHARSET_H__
 
-extern char textChar[];
-extern char textChar2e[];
+#include <stdint.h>
+
+extern uint8_t textChar[];
+extern uint8_t textChar2e[];
 
 #endif // __CHARSET_H__
 
index ca78135c37a04f2943dcdbf2934f7fbf5ca0da5a..3a33e8de0a60b5dd3dc29a14cf2e71f236d37622 100644 (file)
@@ -611,6 +611,109 @@ int FloppyDrive::DriveLightStatus(uint8_t driveNum/*= 0*/)
 }
 
 
+void FloppyDrive::SaveState(FILE * file)
+{
+       // Internal state vars
+       fputc(motorOn, file);
+       fputc(activeDrive, file);
+       fputc(ioMode, file);
+       fputc(latchValue, file);
+       fputc(phase, file);
+       fputc(track, file);
+       fputc((ioHappened ? 1 : 0), file);
+       WriteLong(file, currentPos);
+
+       // Disk #1
+       if (disk[0] != NULL)
+       {
+               WriteLong(file, diskSize[0]);
+               WriteLong(file, diskType[0]);
+               fputc((imageDirty[0] ? 1 : 0), file);
+               fputc((writeProtected[0] ? 1 : 0), file);
+               fwrite(nybblizedImage[0], 1, 232960, file);
+               fwrite(imageName[0], 1, MAX_PATH, file);
+       }
+       else
+               WriteLong(file, 0);
+
+       // Disk #2
+       if (disk[1] != NULL)
+       {
+               WriteLong(file, diskSize[1]);
+               WriteLong(file, diskType[1]);
+               fputc((imageDirty[1] ? 1 : 0), file);
+               fputc((writeProtected[1] ? 1 : 0), file);
+               fwrite(nybblizedImage[1], 1, 232960, file);
+               fwrite(imageName[1], 1, MAX_PATH, file);
+       }
+       else
+               WriteLong(file, 0);
+}
+
+
+void FloppyDrive::LoadState(FILE * file)
+{
+       // Eject images if they're loaded
+       EjectImage(0);
+       EjectImage(1);
+
+       // Read internal state variables
+       motorOn = fgetc(file);
+       activeDrive = fgetc(file);
+       ioMode = fgetc(file);
+       latchValue = fgetc(file);
+       phase = fgetc(file);
+       track = fgetc(file);
+       ioHappened = (fgetc(file) == 1 ? true : false);
+       currentPos = ReadLong(file);
+
+       diskSize[0] = ReadLong(file);
+
+       if (diskSize[0])
+       {
+               disk[0] = new uint8_t[diskSize[0]];
+               diskType[0] = (uint8_t)ReadLong(file);
+               imageDirty[0] = (fgetc(file) == 1 ? true : false);
+               writeProtected[0] = (fgetc(file) == 1 ? true : false);
+               fread(nybblizedImage[0], 1, 232960, file);
+               fread(imageName[0], 1, MAX_PATH, file);
+       }
+
+       diskSize[1] = ReadLong(file);
+
+       if (diskSize[1])
+       {
+               disk[1] = new uint8_t[diskSize[1]];
+               diskType[1] = (uint8_t)ReadLong(file);
+               imageDirty[1] = (fgetc(file) == 1 ? true : false);
+               writeProtected[1] = (fgetc(file) == 1 ? true : false);
+               fread(nybblizedImage[1], 1, 232960, file);
+               fread(imageName[1], 1, MAX_PATH, file);
+       }
+}
+
+
+uint32_t FloppyDrive::ReadLong(FILE * file)
+{
+       uint32_t r = 0;
+
+       for(int i=0; i<4; i++)
+               r = (r << 8) | fgetc(file);
+
+       return r;
+}
+
+
+void FloppyDrive::WriteLong(FILE * file, uint32_t l)
+{
+       for(int i=0; i<4; i++)
+       {
+               fputc((l >> 24) & 0xFF, file);
+               l = l << 8;
+       }
+}
+
+
 // Memory mapped I/O functions
 
 /*
index 6adb039c6022328f75396307c2df6dff7b6b8847..d439bfe84d9393348f5038d5b32026ae0bf0607e 100644 (file)
@@ -13,6 +13,7 @@
 #include <stdlib.h>                                                            // for MAX_PATH on MinGW/Darwin
 #endif
 #include <stdint.h>
+#include <stdio.h>
 
 enum { DFT_UNKNOWN, DT_DOS33, DT_DOS33_HDR, DT_PRODOS, DT_NYBBLE };
 enum { DLS_OFF, DLS_READ, DLS_WRITE };
@@ -34,9 +35,16 @@ class FloppyDrive
                bool IsWriteProtected(uint8_t driveNum = 0);
                void SetWriteProtect(bool, uint8_t driveNum = 0);
                int DriveLightStatus(uint8_t driveNum = 0);
+               void SaveState(FILE *);
+               void LoadState(FILE *);
+
+       private:
+               uint32_t ReadLong(FILE *);
+               void WriteLong(FILE *, uint32_t);
 
                // I/O functions ($C0Ex accesses)
 
+       public:
                void ControlStepper(uint8_t addr);
                void ControlMotor(uint8_t addr);
                void DriveEnable(uint8_t addr);