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