|
|
1.1 root 1: /*
1.1.1.4 root 2: Hatari - memorySnapShot.c
3:
1.1.1.19 root 4: This file is distributed under the GNU General Public License, version 2
5: or at 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.13 root 19: const char MemorySnapShot_fileid[] = "Hatari memorySnapShot.c : " __DATE__ " " __TIME__;
1.1.1.10 root 20:
1.1.1.4 root 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.1.8 root 26: #include "configuration.h"
1.1.1.14 root 27: #include "debugui.h"
1.1.1.8 root 28: #include "dmaSnd.h"
1.1 root 29: #include "fdc.h"
30: #include "file.h"
31: #include "floppy.h"
1.1.1.20 root 32: #include "floppy_ipf.h"
33: #include "floppy_stx.h"
1.1 root 34: #include "gemdos.h"
1.1.1.19 root 35: #include "acia.h"
1.1 root 36: #include "ikbd.h"
1.1.1.15 root 37: #include "cycInt.h"
38: #include "cycles.h"
1.1.1.10 root 39: #include "ioMem.h"
1.1.1.7 root 40: #include "log.h"
1.1 root 41: #include "m68000.h"
42: #include "memorySnapShot.h"
43: #include "mfp.h"
1.1.1.21 root 44: #include "midi.h"
1.1 root 45: #include "psg.h"
46: #include "reset.h"
1.1.1.24! root 47: #include "scc.h"
1.1 root 48: #include "sound.h"
1.1.1.14 root 49: #include "str.h"
1.1.1.15 root 50: #include "stMemory.h"
1.1 root 51: #include "tos.h"
1.1.1.16 root 52: #include "screen.h"
1.1.1.22 root 53: #include "screenConvert.h"
1.1 root 54: #include "video.h"
1.1.1.14 root 55: #include "falcon/dsp.h"
1.1.1.16 root 56: #include "falcon/crossbar.h"
57: #include "falcon/videl.h"
58: #include "statusbar.h"
1.1.1.24! root 59: #include "hatari-glue.h"
1.1.1.2 root 60:
1.1 root 61:
1.1.1.24! root 62: #define VERSION_STRING "2.2.0" /* Version number of compatible memory snapshots - Always 6 bytes (inc' NULL) */
1.1.1.21 root 63: #define SNAPSHOT_MAGIC 0xDeadBeef
1.1.1.6 root 64:
1.1.1.20 root 65: #if HAVE_LIBZ
1.1.1.8 root 66: #define COMPRESS_MEMORYSNAPSHOT /* Compress snapshots to reduce disk space used */
1.1.1.20 root 67: #endif
1.1 root 68:
1.1.1.5 root 69: #ifdef COMPRESS_MEMORYSNAPSHOT
1.1 root 70:
1.1.1.16 root 71: /* Remove possible conflicting mkdir declaration from cpu/sysdeps.h */
72: #undef mkdir
1.1.1.5 root 73: #include <zlib.h>
74: typedef gzFile MSS_File;
75:
76: #else
77:
78: typedef FILE* MSS_File;
1.1 root 79:
1.1.1.5 root 80: #endif
81:
82:
83: static MSS_File CaptureFile;
1.1.1.12 root 84: static bool bCaptureSave, bCaptureError;
1.1.1.5 root 85:
86:
1.1.1.24! root 87: static char Temp_FileName[FILENAME_MAX];
! 88: static bool Temp_Confirm;
! 89:
! 90:
1.1.1.5 root 91: /*-----------------------------------------------------------------------*/
1.1.1.10 root 92: /**
93: * Open file.
94: */
1.1.1.7 root 95: static MSS_File MemorySnapShot_fopen(const char *pszFileName, const char *pszMode)
1.1 root 96: {
97: #ifdef COMPRESS_MEMORYSNAPSHOT
1.1.1.5 root 98: return gzopen(pszFileName, pszMode);
99: #else
100: return fopen(pszFileName, pszMode);
101: #endif
1.1 root 102: }
103:
1.1.1.5 root 104:
105: /*-----------------------------------------------------------------------*/
1.1.1.10 root 106: /**
107: * Close file.
108: */
1.1.1.5 root 109: static void MemorySnapShot_fclose(MSS_File fhndl)
1.1 root 110: {
111: #ifdef COMPRESS_MEMORYSNAPSHOT
1.1.1.5 root 112: gzclose(fhndl);
113: #else
114: fclose(fhndl);
115: #endif
1.1 root 116: }
117:
1.1.1.5 root 118:
119: /*-----------------------------------------------------------------------*/
1.1.1.10 root 120: /**
121: * Read from file.
122: */
1.1.1.5 root 123: static int MemorySnapShot_fread(MSS_File fhndl, char *buf, int len)
1.1 root 124: {
125: #ifdef COMPRESS_MEMORYSNAPSHOT
1.1.1.5 root 126: return gzread(fhndl, buf, len);
127: #else
128: return fread(buf, 1, len, fhndl);
129: #endif
1.1 root 130: }
131:
1.1.1.5 root 132:
133: /*-----------------------------------------------------------------------*/
1.1.1.10 root 134: /**
135: * Write data to file.
136: */
1.1.1.7 root 137: static int MemorySnapShot_fwrite(MSS_File fhndl, const char *buf, int len)
1.1 root 138: {
1.1.1.5 root 139: #ifdef COMPRESS_MEMORYSNAPSHOT
140: return gzwrite(fhndl, buf, len);
141: #else
142: return fwrite(buf, 1, len, fhndl);
143: #endif
1.1 root 144: }
145:
1.1.1.5 root 146:
147: /*-----------------------------------------------------------------------*/
1.1.1.10 root 148: /**
1.1.1.20 root 149: * Seek into file from current position
150: */
151: static int MemorySnapShot_fseek(MSS_File fhndl, int pos)
152: {
153: #ifdef COMPRESS_MEMORYSNAPSHOT
154: return (int)gzseek(fhndl, pos, SEEK_CUR); /* return -1 if error, new position >=0 if OK */
155: #else
1.1.1.21 root 156: return fseek(fhndl, pos, SEEK_CUR); /* return -1 if error, 0 if OK */
1.1.1.20 root 157: #endif
158: }
159:
160:
161: /*-----------------------------------------------------------------------*/
162: /**
1.1.1.10 root 163: * Open/Create snapshot file, and set flag so 'MemorySnapShot_Store' knows
164: * how to handle data.
165: */
1.1.1.22 root 166: static bool MemorySnapShot_OpenFile(const char *pszFileName, bool bSave, bool bConfirm)
1.1 root 167: {
1.1.1.16 root 168: char VersionString[] = VERSION_STRING;
1.1.1.21 root 169: #if ENABLE_WINUAE_CPU
170: # define CORE_VERSION 1
171: #else
172: # define CORE_VERSION 0
173: #endif
174: Uint8 CpuCore;
1.1.1.3 root 175:
1.1.1.5 root 176: /* Set error */
1.1.1.14 root 177: bCaptureError = false;
1.1 root 178:
1.1.1.16 root 179: /* after opening file, set bCaptureSave to indicate whether
180: * 'MemorySnapShot_Store' should load from or save to a file
181: */
1.1.1.5 root 182: if (bSave)
183: {
1.1.1.22 root 184: if (bConfirm && !File_QueryOverwrite(pszFileName))
185: {
186: /* info for debugger invocation */
187: Log_Printf(LOG_INFO, "Save canceled.");
1.1.1.16 root 188: return false;
1.1.1.22 root 189: }
1.1.1.5 root 190: /* Save */
191: CaptureFile = MemorySnapShot_fopen(pszFileName, "wb");
192: if (!CaptureFile)
193: {
1.1.1.22 root 194: Log_Printf(LOG_WARN, "Save file open error: %s",strerror(errno));
1.1.1.14 root 195: bCaptureError = true;
196: return false;
1.1.1.5 root 197: }
1.1.1.14 root 198: bCaptureSave = true;
1.1.1.5 root 199: /* Store version string */
1.1.1.16 root 200: MemorySnapShot_Store(VersionString, sizeof(VersionString));
1.1.1.21 root 201: /* Store CPU core version */
202: CpuCore = CORE_VERSION;
203: MemorySnapShot_Store(&CpuCore, sizeof(CpuCore));
1.1.1.5 root 204: }
205: else
206: {
207: /* Restore */
208: CaptureFile = MemorySnapShot_fopen(pszFileName, "rb");
209: if (!CaptureFile)
210: {
1.1.1.22 root 211: Log_Printf(LOG_WARN, "File open error: %s", strerror(errno));
1.1.1.14 root 212: bCaptureError = true;
213: return false;
1.1.1.5 root 214: }
1.1.1.14 root 215: bCaptureSave = false;
1.1.1.5 root 216: /* Restore version string */
1.1.1.16 root 217: MemorySnapShot_Store(VersionString, sizeof(VersionString));
1.1.1.5 root 218: /* Does match current version? */
1.1.1.21 root 219: if (strcmp(VersionString, VERSION_STRING))
1.1.1.5 root 220: {
221: /* No, inform user and error */
1.1.1.21 root 222: Log_AlertDlg(LOG_ERROR,
223: "Unable to restore Hatari memory state.\n"
224: "Given state file is compatible only with\n"
225: "Hatari version " VERSION_STRING ".");
226: bCaptureError = true;
227: return false;
228: }
229: /* Check CPU core version */
230: MemorySnapShot_Store(&CpuCore, sizeof(CpuCore));
231: if (CpuCore != CORE_VERSION)
232: {
233: Log_AlertDlg(LOG_ERROR,
234: "Unable to restore Hatari memory state.\n"
235: "Given state file is for different Hatari\n"
236: "CPU core version.");
1.1.1.14 root 237: bCaptureError = true;
238: return false;
1.1.1.5 root 239: }
240: }
1.1 root 241:
1.1.1.5 root 242: /* All OK */
1.1.1.14 root 243: return true;
1.1 root 244: }
245:
1.1.1.5 root 246:
247: /*-----------------------------------------------------------------------*/
1.1.1.10 root 248: /**
249: * Close snapshot file.
250: */
1.1.1.5 root 251: static void MemorySnapShot_CloseFile(void)
1.1 root 252: {
1.1.1.5 root 253: MemorySnapShot_fclose(CaptureFile);
1.1 root 254: }
255:
1.1.1.5 root 256:
257: /*-----------------------------------------------------------------------*/
1.1.1.10 root 258: /**
1.1.1.20 root 259: * Skip Nb bytes when reading from/writing to file.
260: */
261: void MemorySnapShot_Skip(int Nb)
262: {
263: int res;
264:
265: /* Check no file errors */
266: if (CaptureFile != NULL)
267: {
268: res = MemorySnapShot_fseek(CaptureFile, Nb);
269:
270: /* Did seek OK? */
271: if (res < 0)
272: bCaptureError = true;
273: }
274: }
275:
276:
277: /*-----------------------------------------------------------------------*/
278: /**
1.1.1.10 root 279: * Save/Restore data to/from file.
280: */
1.1 root 281: void MemorySnapShot_Store(void *pData, int Size)
282: {
1.1.1.5 root 283: long nBytes;
1.1.1.3 root 284:
1.1.1.5 root 285: /* Check no file errors */
286: if (CaptureFile != NULL)
287: {
288: /* Saving or Restoring? */
289: if (bCaptureSave)
290: nBytes = MemorySnapShot_fwrite(CaptureFile, (char *)pData, Size);
291: else
292: nBytes = MemorySnapShot_fread(CaptureFile, (char *)pData, Size);
293:
294: /* Did save OK? */
295: if (nBytes != Size)
1.1.1.14 root 296: bCaptureError = true;
1.1.1.5 root 297: }
1.1 root 298: }
299:
1.1.1.5 root 300:
301: /*-----------------------------------------------------------------------*/
1.1.1.10 root 302: /**
303: * Save 'snapshot' of memory/chips/emulation variables
304: */
1.1.1.12 root 305: void MemorySnapShot_Capture(const char *pszFileName, bool bConfirm)
1.1 root 306: {
1.1.1.24! root 307: //fprintf ( stderr , "MemorySnapShot_Capture in\n" );
! 308: /* Make a temporary copy of the parameters for MemorySnapShot_Capture_Do() */
! 309: strlcpy ( Temp_FileName , pszFileName , FILENAME_MAX );
! 310: Temp_Confirm = bConfirm;
! 311:
! 312: #ifndef WINUAE_FOR_HATARI
! 313: /* With old cpu core, capture is immediate */
! 314: MemorySnapShot_Capture_Do ();
! 315: #else
! 316: /* With WinUAE cpu core, capture is done from m68k_run_xxx() after the end of the current instruction */
! 317: UAE_Set_State_Save ();
! 318: #endif
! 319: //fprintf ( stderr , "MemorySnapShot_Capture out\n" );
! 320: }
! 321:
! 322:
! 323:
! 324: /*
! 325: * Same as MemorySnapShot_Capture, but snapshot is saved immediately
! 326: * without restarting emulation (used in the debugger)
! 327: */
! 328: void MemorySnapShot_Capture_Immediate(const char *pszFileName, bool bConfirm)
! 329: {
! 330: /* Make a temporary copy of the parameters for MemorySnapShot_Capture_Do() */
! 331: strlcpy ( Temp_FileName , pszFileName , FILENAME_MAX );
! 332: Temp_Confirm = bConfirm;
! 333:
! 334: MemorySnapShot_Capture_Do ();
! 335: }
! 336:
! 337:
! 338:
! 339: /*
! 340: * Do the real saving (called from newcpu.c / m68k_go()
! 341: */
! 342: void MemorySnapShot_Capture_Do(void)
! 343: {
1.1.1.21 root 344: Uint32 magic = SNAPSHOT_MAGIC;
345:
1.1.1.5 root 346: /* Set to 'saving' */
1.1.1.24! root 347: if (MemorySnapShot_OpenFile(Temp_FileName, true, Temp_Confirm))
1.1.1.5 root 348: {
349: /* Capture each files details */
1.1.1.14 root 350: Configuration_MemorySnapShot_Capture(true);
351: TOS_MemorySnapShot_Capture(true);
1.1.1.15 root 352: STMemory_MemorySnapShot_Capture(true);
1.1.1.20 root 353: Cycles_MemorySnapShot_Capture(true); /* Before fdc (for CyclesGlobalClockCounter) */
1.1.1.14 root 354: FDC_MemorySnapShot_Capture(true);
355: Floppy_MemorySnapShot_Capture(true);
1.1.1.20 root 356: IPF_MemorySnapShot_Capture(true); /* After fdc/floppy are saved */
357: STX_MemorySnapShot_Capture(true); /* After fdc/floppy are saved */
1.1.1.14 root 358: GemDOS_MemorySnapShot_Capture(true);
1.1.1.19 root 359: ACIA_MemorySnapShot_Capture(true);
1.1.1.14 root 360: IKBD_MemorySnapShot_Capture(true);
1.1.1.21 root 361: MIDI_MemorySnapShot_Capture(true);
1.1.1.15 root 362: CycInt_MemorySnapShot_Capture(true);
1.1.1.14 root 363: M68000_MemorySnapShot_Capture(true);
364: MFP_MemorySnapShot_Capture(true);
365: PSG_MemorySnapShot_Capture(true);
366: Sound_MemorySnapShot_Capture(true);
367: Video_MemorySnapShot_Capture(true);
368: Blitter_MemorySnapShot_Capture(true);
369: DmaSnd_MemorySnapShot_Capture(true);
1.1.1.16 root 370: Crossbar_MemorySnapShot_Capture(true);
371: VIDEL_MemorySnapShot_Capture(true);
1.1.1.14 root 372: DSP_MemorySnapShot_Capture(true);
1.1.1.24! root 373: DebugUI_MemorySnapShot_Capture(Temp_FileName, true);
1.1.1.16 root 374: IoMem_MemorySnapShot_Capture(true);
1.1.1.22 root 375: ScreenConv_MemorySnapShot_Capture(true);
1.1.1.24! root 376: SCC_MemorySnapShot_Capture(true);
1.1.1.22 root 377:
1.1.1.21 root 378: /* end marker */
379: MemorySnapShot_Store(&magic, sizeof(magic));
1.1.1.5 root 380: /* And close */
381: MemorySnapShot_CloseFile();
1.1.1.16 root 382: } else {
383: /* just canceled? */
384: if (!bCaptureError)
385: return;
1.1.1.5 root 386: }
387:
388: /* Did error */
389: if (bCaptureError)
1.1.1.24! root 390: Log_AlertDlg(LOG_ERROR, "Unable to save memory state to file: %s", Temp_FileName);
! 391: else if (Temp_Confirm)
! 392: Log_AlertDlg(LOG_INFO, "Memory state file saved: %s", Temp_FileName);
1.1.1.22 root 393: else
1.1.1.24! root 394: Log_Printf(LOG_INFO, "Memory state file saved: %s", Temp_FileName);
1.1 root 395: }
396:
1.1.1.5 root 397:
398: /*-----------------------------------------------------------------------*/
1.1.1.10 root 399: /**
400: * Restore 'snapshot' of memory/chips/emulation variables
401: */
1.1.1.12 root 402: void MemorySnapShot_Restore(const char *pszFileName, bool bConfirm)
1.1 root 403: {
1.1.1.24! root 404: //fprintf ( stderr , "MemorySnapShot_Restore in\n" );
! 405: /* Make a temporary copy of the parameters for MemorySnapShot_Restore_Do() */
! 406: strlcpy ( Temp_FileName , pszFileName , FILENAME_MAX );
! 407: Temp_Confirm = bConfirm;
! 408:
! 409: #ifndef WINUAE_FOR_HATARI
! 410: /* With old cpu core, restore is immediate */
! 411: MemorySnapShot_Restore_Do ();
! 412: #else
! 413: /* With WinUAE cpu core, restore is done from m68k_go() after the end of the current instruction */
! 414: UAE_Set_State_Restore ();
! 415: UAE_Set_Quit_Reset ( false ); /* Ask for "quit" to start restoring state */
! 416: set_special(SPCFLAG_MODE_CHANGE); /* exit m68k_run_xxx() loop and check "quit" */
! 417: #endif
! 418: //fprintf ( stderr , "MemorySnapShot_Restore out\n" );
! 419: }
! 420:
! 421:
! 422:
! 423: /*
! 424: * Do the real restoring (called from newcpu.c / m68k_go()
! 425: */
! 426: void MemorySnapShot_Restore_Do(void)
! 427: {
1.1.1.21 root 428: Uint32 magic;
429:
1.1.1.24! root 430: //fprintf ( stderr , "MemorySnapShot_Restore_Do in\n" );
1.1.1.5 root 431: /* Set to 'restore' */
1.1.1.24! root 432: if (MemorySnapShot_OpenFile(Temp_FileName, false, Temp_Confirm))
1.1.1.5 root 433: {
1.1.1.14 root 434: Configuration_MemorySnapShot_Capture(false);
435: TOS_MemorySnapShot_Capture(false);
1.1.1.10 root 436:
1.1.1.24! root 437: /* FIXME [NP] : Reset_Cold calls TOS_InitImage which calls */
! 438: /* memory_init. memory_init allocs STRam and TTRam, but TTRam */
! 439: /* requires currprefs.address_space_24 which is not restored yet */
! 440: /* (it's from M68000_MemorySnapShot_Capture). To resolve this */
! 441: /* circular dependancy, we init currprefs.address_space_24 here */
! 442: /* This should be splitted in different functions / order to avoid this loop */
! 443: currprefs.address_space_24 = ConfigureParams.System.bAddressSpace24;
! 444:
1.1.1.5 root 445: /* Reset emulator to get things running */
1.1.1.10 root 446: IoMem_UnInit(); IoMem_Init();
1.1.1.5 root 447: Reset_Cold();
448:
449: /* Capture each files details */
1.1.1.15 root 450: STMemory_MemorySnapShot_Capture(false);
1.1.1.20 root 451: Cycles_MemorySnapShot_Capture(false); /* Before fdc (for CyclesGlobalClockCounter) */
1.1.1.14 root 452: FDC_MemorySnapShot_Capture(false);
453: Floppy_MemorySnapShot_Capture(false);
1.1.1.20 root 454: IPF_MemorySnapShot_Capture(false); /* After fdc/floppy are restored, as IPF depends on them */
455: STX_MemorySnapShot_Capture(false); /* After fdc/floppy are restored, as STX depends on them */
1.1.1.14 root 456: GemDOS_MemorySnapShot_Capture(false);
1.1.1.19 root 457: ACIA_MemorySnapShot_Capture(false);
458: IKBD_MemorySnapShot_Capture(false); /* After ACIA */
1.1.1.21 root 459: MIDI_MemorySnapShot_Capture(false);
1.1.1.15 root 460: CycInt_MemorySnapShot_Capture(false);
1.1.1.14 root 461: M68000_MemorySnapShot_Capture(false);
462: MFP_MemorySnapShot_Capture(false);
463: PSG_MemorySnapShot_Capture(false);
464: Sound_MemorySnapShot_Capture(false);
465: Video_MemorySnapShot_Capture(false);
466: Blitter_MemorySnapShot_Capture(false);
467: DmaSnd_MemorySnapShot_Capture(false);
1.1.1.16 root 468: Crossbar_MemorySnapShot_Capture(false);
469: VIDEL_MemorySnapShot_Capture(false);
1.1.1.14 root 470: DSP_MemorySnapShot_Capture(false);
1.1.1.24! root 471: DebugUI_MemorySnapShot_Capture(Temp_FileName, false);
1.1.1.16 root 472: IoMem_MemorySnapShot_Capture(false);
1.1.1.22 root 473: ScreenConv_MemorySnapShot_Capture(false);
1.1.1.24! root 474: SCC_MemorySnapShot_Capture(false);
1.1.1.5 root 475:
1.1.1.21 root 476: /* version string check catches release-to-release
477: * state changes, bCaptureError catches too short
478: * state file, this check a too long state file.
479: */
480: MemorySnapShot_Store(&magic, sizeof(magic));
481: if (!bCaptureError && magic != SNAPSHOT_MAGIC)
482: bCaptureError = true;
483:
1.1.1.5 root 484: /* And close */
485: MemorySnapShot_CloseFile();
1.1.1.16 root 486:
487: /* changes may affect also info shown in statusbar */
488: Statusbar_UpdateInfo();
1.1.1.21 root 489:
490: if (bCaptureError)
491: {
492: Log_AlertDlg(LOG_ERROR, "Full memory state restore failed!\nPlease reboot emulation.");
493: return;
494: }
1.1.1.5 root 495: }
496:
1.1.1.24! root 497: //fprintf ( stderr , "MemorySnapShot_Restore_Do out\n" );
! 498:
1.1.1.5 root 499: /* Did error? */
500: if (bCaptureError)
1.1.1.24! root 501: Log_AlertDlg(LOG_ERROR, "Unable to restore memory state from file: %s", Temp_FileName);
! 502: else if (Temp_Confirm)
! 503: Log_AlertDlg(LOG_INFO, "Memory state file restored: %s", Temp_FileName);
1.1.1.22 root 504: else
1.1.1.24! root 505: Log_Printf(LOG_INFO, "Memory state file restored: %s", Temp_FileName);
1.1 root 506: }
1.1.1.10 root 507:
508:
509: /*-----------------------------------------------------------------------*/
510: /*
511: * Save and restore functions required by the UAE CPU core...
512: * ... don't use them in normal Hatari code!
513: */
514: #include <savestate.h>
515:
1.1.1.21 root 516: void save_u64(uae_u64 data)
517: {
518: MemorySnapShot_Store(&data, 8);
519: }
520:
1.1.1.10 root 521: void save_u32(uae_u32 data)
522: {
523: MemorySnapShot_Store(&data, 4);
1.1.1.21 root 524: //printf ("s32 %x\n", data);
1.1.1.10 root 525: }
526:
527: void save_u16(uae_u16 data)
528: {
529: MemorySnapShot_Store(&data, 2);
1.1.1.21 root 530: //printf ("s16 %x\n", data);
531: }
532:
533: void save_u8(uae_u8 data)
534: {
535: MemorySnapShot_Store(&data, 1);
536: //printf ("s8 %x\n", data);
537: }
538:
539: uae_u64 restore_u64(void)
540: {
541: uae_u64 data;
542: MemorySnapShot_Store(&data, 8);
543: return data;
1.1.1.10 root 544: }
545:
546: uae_u32 restore_u32(void)
547: {
548: uae_u32 data;
549: MemorySnapShot_Store(&data, 4);
1.1.1.21 root 550: //printf ("r32 %x\n", data);
1.1.1.10 root 551: return data;
552: }
553:
554: uae_u16 restore_u16(void)
555: {
556: uae_u16 data;
557: MemorySnapShot_Store(&data, 2);
1.1.1.21 root 558: //printf ("r16 %x\n", data);
1.1.1.10 root 559: return data;
560: }
1.1.1.21 root 561:
562: uae_u8 restore_u8(void)
563: {
564: uae_u8 data;
565: MemorySnapShot_Store(&data, 1);
566: //printf ("r8 %x\n", data);
567: return data;
568: }
569:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.