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