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