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