|
|
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);
229: // STMemory_MemorySnapShot_Capture(true);
230: CycInt_MemorySnapShot_Capture(true);
231: Cycles_MemorySnapShot_Capture(true);
232: M68000_MemorySnapShot_Capture(true);
233: Video_MemorySnapShot_Capture(true);
234: DebugUI_MemorySnapShot_Capture(pszFileName, true);
1.1.1.2 root 235: // IoMem_MemorySnapShot_Capture(true);
1.1 root 236: /* And close */
237: MemorySnapShot_CloseFile();
1.1.1.2 root 238: } else {
239: /* just canceled? */
240: if (!bCaptureError)
241: return;
1.1 root 242: }
243:
244: /* Did error */
245: if (bCaptureError)
246: Log_AlertDlg(LOG_ERROR, "Unable to save memory state to file.");
247: else if (bConfirm)
248: Log_AlertDlg(LOG_INFO, "Memory state file saved.");
249: }
250:
251:
252: /*-----------------------------------------------------------------------*/
253: /**
254: * Restore 'snapshot' of memory/chips/emulation variables
255: */
256: void MemorySnapShot_Restore(const char *pszFileName, bool bConfirm)
257: {
258: /* Set to 'restore' */
259: if (MemorySnapShot_OpenFile(pszFileName, false))
260: {
261: Configuration_MemorySnapShot_Capture(false);
262:
263: /* Reset emulator to get things running */
264: IoMem_UnInit(); IoMem_Init();
265: Reset_Cold();
266:
267: /* Capture each files details */
268: // STMemory_MemorySnapShot_Capture(false);
269: CycInt_MemorySnapShot_Capture(false);
270: Cycles_MemorySnapShot_Capture(false);
271: M68000_MemorySnapShot_Capture(false);
272: Video_MemorySnapShot_Capture(false);
273: DebugUI_MemorySnapShot_Capture(pszFileName, false);
1.1.1.2 root 274: // IoMem_MemorySnapShot_Capture(false);
1.1 root 275:
276: /* And close */
277: MemorySnapShot_CloseFile();
1.1.1.2 root 278:
279: /* changes may affect also info shown in statusbar */
280: Statusbar_UpdateInfo();
1.1 root 281: }
282:
283: /* Did error? */
284: if (bCaptureError)
285: Log_AlertDlg(LOG_ERROR, "Unable to restore memory state from file.");
286: else if (bConfirm)
287: Log_AlertDlg(LOG_INFO, "Memory state file restored.");
288: }
289:
290:
291: /*-----------------------------------------------------------------------*/
292: /*
293: * Save and restore functions required by the UAE CPU core...
294: * ... don't use them in normal Hatari code!
295: */
296: #include <savestate.h>
297:
298: void save_u32(uae_u32 data)
299: {
300: MemorySnapShot_Store(&data, 4);
301: }
302:
303: void save_u16(uae_u16 data)
304: {
305: MemorySnapShot_Store(&data, 2);
306: }
307:
308: uae_u32 restore_u32(void)
309: {
310: uae_u32 data;
311: MemorySnapShot_Store(&data, 4);
312: return data;
313: }
314:
315: uae_u16 restore_u16(void)
316: {
317: uae_u16 data;
318: MemorySnapShot_Store(&data, 2);
319: return data;
320: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.