|
|
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.