|
|
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.10! root 19: const char MemorySnapShot_rcsid[] = "Hatari $Id: memorySnapShot.c,v 1.37 2008/02/24 20:10:47 thothy Exp $";
! 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.10! root 53: #define VERSION_STRING "1.0.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;
72: static BOOL bCaptureSave, bCaptureError;
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.8 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.8 root 178: Log_AlertDlg(LOG_WARN, "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: */
! 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: */
! 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.