|
|
1.1 ! root 1: /* ! 2: Hatari - memorySnapShot.c ! 3: ! 4: This file is distributed under the GNU Public License, version 2 or at ! 5: your option any later version. Read the file gpl.txt for details. ! 6: ! 7: Memory Snapshot ! 8: ! 9: This handles the saving/restoring of the emulator's state so any game or ! 10: application can be saved and restored at any time. This is quite complicated ! 11: as we need to store all STRam, all chip states, all emulation variables and ! 12: then things get really complicated as we need to restore file handles ! 13: and such like. ! 14: To help keep things simple each file has one function which is used to ! 15: save/restore all variables that are local to it. We use one function to ! 16: reduce redundancy and the function 'MemorySnapShot_Store' decides if it ! 17: should save or restore the data. ! 18: */ ! 19: const char MemorySnapShot_fileid[] = "Hatari memorySnapShot.c : " __DATE__ " " __TIME__; ! 20: ! 21: #include <SDL_types.h> ! 22: #include <errno.h> ! 23: ! 24: #include "main.h" ! 25: #include "configuration.h" ! 26: #include "debugui.h" ! 27: #include "file.h" ! 28: #include "cycInt.h" ! 29: #include "cycles.h" ! 30: #include "ioMem.h" ! 31: #include "log.h" ! 32: #include "m68000.h" ! 33: #include "memorySnapShot.h" ! 34: #include "reset.h" ! 35: #include "str.h" ! 36: #include "nextMemory.h" ! 37: #include "video.h" ! 38: ! 39: ! 40: #define VERSION_STRING "0.0.1" /* Version number of compatible memory snapshots - Always 6 bytes (inc' NULL) */ ! 41: #define VERSION_STRING_SIZE 6 /* Size of above (inc' NULL) */ ! 42: ! 43: ! 44: #define COMPRESS_MEMORYSNAPSHOT /* Compress snapshots to reduce disk space used */ ! 45: ! 46: #ifdef COMPRESS_MEMORYSNAPSHOT ! 47: ! 48: #include <zlib.h> ! 49: typedef gzFile MSS_File; ! 50: ! 51: #else ! 52: ! 53: typedef FILE* MSS_File; ! 54: ! 55: #endif ! 56: ! 57: ! 58: static MSS_File CaptureFile; ! 59: static bool bCaptureSave, bCaptureError; ! 60: ! 61: ! 62: /*-----------------------------------------------------------------------*/ ! 63: /** ! 64: * Open file. ! 65: */ ! 66: static MSS_File MemorySnapShot_fopen(const char *pszFileName, const char *pszMode) ! 67: { ! 68: #ifdef COMPRESS_MEMORYSNAPSHOT ! 69: return gzopen(pszFileName, pszMode); ! 70: #else ! 71: return fopen(pszFileName, pszMode); ! 72: #endif ! 73: } ! 74: ! 75: ! 76: /*-----------------------------------------------------------------------*/ ! 77: /** ! 78: * Close file. ! 79: */ ! 80: static void MemorySnapShot_fclose(MSS_File fhndl) ! 81: { ! 82: #ifdef COMPRESS_MEMORYSNAPSHOT ! 83: gzclose(fhndl); ! 84: #else ! 85: fclose(fhndl); ! 86: #endif ! 87: } ! 88: ! 89: ! 90: /*-----------------------------------------------------------------------*/ ! 91: /** ! 92: * Read from file. ! 93: */ ! 94: static int MemorySnapShot_fread(MSS_File fhndl, char *buf, int len) ! 95: { ! 96: #ifdef COMPRESS_MEMORYSNAPSHOT ! 97: return gzread(fhndl, buf, len); ! 98: #else ! 99: return fread(buf, 1, len, fhndl); ! 100: #endif ! 101: } ! 102: ! 103: ! 104: /*-----------------------------------------------------------------------*/ ! 105: /** ! 106: * Write data to file. ! 107: */ ! 108: static int MemorySnapShot_fwrite(MSS_File fhndl, const char *buf, int len) ! 109: { ! 110: #ifdef COMPRESS_MEMORYSNAPSHOT ! 111: return gzwrite(fhndl, buf, len); ! 112: #else ! 113: return fwrite(buf, 1, len, fhndl); ! 114: #endif ! 115: } ! 116: ! 117: ! 118: /*-----------------------------------------------------------------------*/ ! 119: /** ! 120: * Open/Create snapshot file, and set flag so 'MemorySnapShot_Store' knows ! 121: * how to handle data. ! 122: */ ! 123: static bool MemorySnapShot_OpenFile(const char *pszFileName, bool bSave) ! 124: { ! 125: char VersionString[VERSION_STRING_SIZE]; ! 126: ! 127: /* Set error */ ! 128: bCaptureError = false; ! 129: ! 130: /* Open file, set flag so 'MemorySnapShot_Store' can load to/save from file */ ! 131: if (bSave) ! 132: { ! 133: /* Save */ ! 134: CaptureFile = MemorySnapShot_fopen(pszFileName, "wb"); ! 135: if (!CaptureFile) ! 136: { ! 137: fprintf(stderr, "Failed to open save file '%s': %s\n", ! 138: pszFileName, strerror(errno)); ! 139: bCaptureError = true; ! 140: return false; ! 141: } ! 142: bCaptureSave = true; ! 143: /* Store version string */ ! 144: strcpy(VersionString, VERSION_STRING); ! 145: MemorySnapShot_Store(VersionString, VERSION_STRING_SIZE); ! 146: } ! 147: else ! 148: { ! 149: /* Restore */ ! 150: CaptureFile = MemorySnapShot_fopen(pszFileName, "rb"); ! 151: if (!CaptureFile) ! 152: { ! 153: fprintf(stderr, "Failed to open file '%s': %s\n", ! 154: pszFileName, strerror(errno)); ! 155: bCaptureError = true; ! 156: return false; ! 157: } ! 158: bCaptureSave = false; ! 159: /* Restore version string */ ! 160: MemorySnapShot_Store(VersionString, VERSION_STRING_SIZE); ! 161: /* Does match current version? */ ! 162: if (strcasecmp(VersionString, VERSION_STRING)) ! 163: { ! 164: /* No, inform user and error */ ! 165: Log_AlertDlg(LOG_ERROR, "Unable to Restore Memory State.\nFile is " ! 166: "only compatible with Hatari v%s", VersionString); ! 167: bCaptureError = true; ! 168: return false; ! 169: } ! 170: } ! 171: ! 172: /* All OK */ ! 173: return true; ! 174: } ! 175: ! 176: ! 177: /*-----------------------------------------------------------------------*/ ! 178: /** ! 179: * Close snapshot file. ! 180: */ ! 181: static void MemorySnapShot_CloseFile(void) ! 182: { ! 183: MemorySnapShot_fclose(CaptureFile); ! 184: } ! 185: ! 186: ! 187: /*-----------------------------------------------------------------------*/ ! 188: /** ! 189: * Save/Restore data to/from file. ! 190: */ ! 191: void MemorySnapShot_Store(void *pData, int Size) ! 192: { ! 193: long nBytes; ! 194: ! 195: /* Check no file errors */ ! 196: if (CaptureFile != NULL) ! 197: { ! 198: /* Saving or Restoring? */ ! 199: if (bCaptureSave) ! 200: nBytes = MemorySnapShot_fwrite(CaptureFile, (char *)pData, Size); ! 201: else ! 202: nBytes = MemorySnapShot_fread(CaptureFile, (char *)pData, Size); ! 203: ! 204: /* Did save OK? */ ! 205: if (nBytes != Size) ! 206: bCaptureError = true; ! 207: } ! 208: } ! 209: ! 210: ! 211: /*-----------------------------------------------------------------------*/ ! 212: /** ! 213: * Save 'snapshot' of memory/chips/emulation variables ! 214: */ ! 215: void MemorySnapShot_Capture(const char *pszFileName, bool bConfirm) ! 216: { ! 217: /* Set to 'saving' */ ! 218: if (MemorySnapShot_OpenFile(pszFileName, true)) ! 219: { ! 220: /* Capture each files details */ ! 221: Configuration_MemorySnapShot_Capture(true); ! 222: // STMemory_MemorySnapShot_Capture(true); ! 223: CycInt_MemorySnapShot_Capture(true); ! 224: Cycles_MemorySnapShot_Capture(true); ! 225: M68000_MemorySnapShot_Capture(true); ! 226: Video_MemorySnapShot_Capture(true); ! 227: DebugUI_MemorySnapShot_Capture(pszFileName, true); ! 228: ! 229: /* And close */ ! 230: MemorySnapShot_CloseFile(); ! 231: } ! 232: ! 233: /* Did error */ ! 234: if (bCaptureError) ! 235: Log_AlertDlg(LOG_ERROR, "Unable to save memory state to file."); ! 236: else if (bConfirm) ! 237: Log_AlertDlg(LOG_INFO, "Memory state file saved."); ! 238: } ! 239: ! 240: ! 241: /*-----------------------------------------------------------------------*/ ! 242: /** ! 243: * Restore 'snapshot' of memory/chips/emulation variables ! 244: */ ! 245: void MemorySnapShot_Restore(const char *pszFileName, bool bConfirm) ! 246: { ! 247: /* Set to 'restore' */ ! 248: if (MemorySnapShot_OpenFile(pszFileName, false)) ! 249: { ! 250: Configuration_MemorySnapShot_Capture(false); ! 251: ! 252: /* Reset emulator to get things running */ ! 253: IoMem_UnInit(); IoMem_Init(); ! 254: Reset_Cold(); ! 255: ! 256: /* Capture each files details */ ! 257: // STMemory_MemorySnapShot_Capture(false); ! 258: CycInt_MemorySnapShot_Capture(false); ! 259: Cycles_MemorySnapShot_Capture(false); ! 260: M68000_MemorySnapShot_Capture(false); ! 261: Video_MemorySnapShot_Capture(false); ! 262: DebugUI_MemorySnapShot_Capture(pszFileName, false); ! 263: ! 264: /* And close */ ! 265: MemorySnapShot_CloseFile(); ! 266: } ! 267: ! 268: /* Did error? */ ! 269: if (bCaptureError) ! 270: Log_AlertDlg(LOG_ERROR, "Unable to restore memory state from file."); ! 271: else if (bConfirm) ! 272: Log_AlertDlg(LOG_INFO, "Memory state file restored."); ! 273: } ! 274: ! 275: ! 276: /*-----------------------------------------------------------------------*/ ! 277: /* ! 278: * Save and restore functions required by the UAE CPU core... ! 279: * ... don't use them in normal Hatari code! ! 280: */ ! 281: #include <savestate.h> ! 282: ! 283: void save_u32(uae_u32 data) ! 284: { ! 285: MemorySnapShot_Store(&data, 4); ! 286: } ! 287: ! 288: void save_u16(uae_u16 data) ! 289: { ! 290: MemorySnapShot_Store(&data, 2); ! 291: } ! 292: ! 293: uae_u32 restore_u32(void) ! 294: { ! 295: uae_u32 data; ! 296: MemorySnapShot_Store(&data, 4); ! 297: return data; ! 298: } ! 299: ! 300: uae_u16 restore_u16(void) ! 301: { ! 302: uae_u16 data; ! 303: MemorySnapShot_Store(&data, 2); ! 304: return data; ! 305: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.