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