Annotation of hatari/src/memorySnapShot.c, revision 1.1.1.19

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"
                     32: #include "gemdos.h"
1.1.1.19! root       33: #include "acia.h"
1.1       root       34: #include "ikbd.h"
1.1.1.15  root       35: #include "cycInt.h"
                     36: #include "cycles.h"
1.1.1.10  root       37: #include "ioMem.h"
1.1.1.7   root       38: #include "log.h"
1.1       root       39: #include "m68000.h"
                     40: #include "memorySnapShot.h"
                     41: #include "mfp.h"
                     42: #include "psg.h"
                     43: #include "reset.h"
                     44: #include "sound.h"
1.1.1.14  root       45: #include "str.h"
1.1.1.15  root       46: #include "stMemory.h"
1.1       root       47: #include "tos.h"
1.1.1.16  root       48: #include "screen.h"
1.1       root       49: #include "video.h"
1.1.1.14  root       50: #include "falcon/dsp.h"
1.1.1.16  root       51: #include "falcon/crossbar.h"
                     52: #include "falcon/videl.h"
                     53: #include "statusbar.h"
1.1.1.2   root       54: 
1.1       root       55: 
1.1.1.19! root       56: #define VERSION_STRING      "1.7.0"   /* Version number of compatible memory snapshots - Always 6 bytes (inc' NULL) */
1.1.1.6   root       57: 
1.1.1.8   root       58: #define COMPRESS_MEMORYSNAPSHOT       /* Compress snapshots to reduce disk space used */
1.1       root       59: 
1.1.1.5   root       60: #ifdef COMPRESS_MEMORYSNAPSHOT
1.1       root       61: 
1.1.1.16  root       62: /* Remove possible conflicting mkdir declaration from cpu/sysdeps.h */
                     63: #undef mkdir
1.1.1.5   root       64: #include <zlib.h>
                     65: typedef gzFile MSS_File;
                     66: 
                     67: #else
                     68: 
                     69: typedef FILE* MSS_File;
1.1       root       70: 
1.1.1.5   root       71: #endif
                     72: 
                     73: 
                     74: static MSS_File CaptureFile;
1.1.1.12  root       75: static bool bCaptureSave, bCaptureError;
1.1.1.5   root       76: 
                     77: 
                     78: /*-----------------------------------------------------------------------*/
1.1.1.10  root       79: /**
                     80:  * Open file.
                     81:  */
1.1.1.7   root       82: static MSS_File MemorySnapShot_fopen(const char *pszFileName, const char *pszMode)
1.1       root       83: {
                     84: #ifdef COMPRESS_MEMORYSNAPSHOT
1.1.1.5   root       85:        return gzopen(pszFileName, pszMode);
                     86: #else
                     87:        return fopen(pszFileName, pszMode);
                     88: #endif
1.1       root       89: }
                     90: 
1.1.1.5   root       91: 
                     92: /*-----------------------------------------------------------------------*/
1.1.1.10  root       93: /**
                     94:  * Close file.
                     95:  */
1.1.1.5   root       96: static void MemorySnapShot_fclose(MSS_File fhndl)
1.1       root       97: {
                     98: #ifdef COMPRESS_MEMORYSNAPSHOT
1.1.1.5   root       99:        gzclose(fhndl);
                    100: #else
                    101:        fclose(fhndl);
                    102: #endif
1.1       root      103: }
                    104: 
1.1.1.5   root      105: 
                    106: /*-----------------------------------------------------------------------*/
1.1.1.10  root      107: /**
                    108:  * Read from file.
                    109:  */
1.1.1.5   root      110: static int MemorySnapShot_fread(MSS_File fhndl, char *buf, int len)
1.1       root      111: {
                    112: #ifdef COMPRESS_MEMORYSNAPSHOT
1.1.1.5   root      113:        return gzread(fhndl, buf, len);
                    114: #else
                    115:        return fread(buf, 1, len, fhndl);
                    116: #endif
1.1       root      117: }
                    118: 
1.1.1.5   root      119: 
                    120: /*-----------------------------------------------------------------------*/
1.1.1.10  root      121: /**
                    122:  * Write data to file.
                    123:  */
1.1.1.7   root      124: static int MemorySnapShot_fwrite(MSS_File fhndl, const char *buf, int len)
1.1       root      125: {
1.1.1.5   root      126: #ifdef COMPRESS_MEMORYSNAPSHOT
                    127:        return gzwrite(fhndl, buf, len);
                    128: #else
                    129:        return fwrite(buf, 1, len, fhndl);
                    130: #endif
1.1       root      131: }
                    132: 
1.1.1.5   root      133: 
                    134: /*-----------------------------------------------------------------------*/
1.1.1.10  root      135: /**
                    136:  * Open/Create snapshot file, and set flag so 'MemorySnapShot_Store' knows
                    137:  * how to handle data.
                    138:  */
1.1.1.12  root      139: static bool MemorySnapShot_OpenFile(const char *pszFileName, bool bSave)
1.1       root      140: {
1.1.1.16  root      141:        char VersionString[] = VERSION_STRING;
1.1.1.3   root      142: 
1.1.1.5   root      143:        /* Set error */
1.1.1.14  root      144:        bCaptureError = false;
1.1       root      145: 
1.1.1.16  root      146:        /* after opening file, set bCaptureSave to indicate whether
                    147:         * 'MemorySnapShot_Store' should load from or save to a file
                    148:         */
1.1.1.5   root      149:        if (bSave)
                    150:        {
1.1.1.16  root      151:                if (!File_QueryOverwrite(pszFileName))
                    152:                        return false;
                    153: 
1.1.1.5   root      154:                /* Save */
                    155:                CaptureFile = MemorySnapShot_fopen(pszFileName, "wb");
                    156:                if (!CaptureFile)
                    157:                {
                    158:                        fprintf(stderr, "Failed to open save file '%s': %s\n",
                    159:                                pszFileName, strerror(errno));
1.1.1.14  root      160:                        bCaptureError = true;
                    161:                        return false;
1.1.1.5   root      162:                }
1.1.1.14  root      163:                bCaptureSave = true;
1.1.1.5   root      164:                /* Store version string */
1.1.1.16  root      165:                MemorySnapShot_Store(VersionString, sizeof(VersionString));
1.1.1.5   root      166:        }
                    167:        else
                    168:        {
                    169:                /* Restore */
                    170:                CaptureFile = MemorySnapShot_fopen(pszFileName, "rb");
                    171:                if (!CaptureFile)
                    172:                {
                    173:                        fprintf(stderr, "Failed to open file '%s': %s\n",
                    174:                                pszFileName, strerror(errno));
1.1.1.14  root      175:                        bCaptureError = true;
                    176:                        return false;
1.1.1.5   root      177:                }
1.1.1.14  root      178:                bCaptureSave = false;
1.1.1.5   root      179:                /* Restore version string */
1.1.1.16  root      180:                MemorySnapShot_Store(VersionString, sizeof(VersionString));
1.1.1.5   root      181:                /* Does match current version? */
                    182:                if (strcasecmp(VersionString, VERSION_STRING))
                    183:                {
                    184:                        /* No, inform user and error */
1.1.1.16  root      185:                        Log_AlertDlg(LOG_ERROR, "Unable to restore Hatari memory state. File\n"
                    186:                                               "is compatible only with Hatari version %s.",
                    187:                                     VersionString);
1.1.1.14  root      188:                        bCaptureError = true;
                    189:                        return false;
1.1.1.5   root      190:                }
                    191:        }
1.1       root      192: 
1.1.1.5   root      193:        /* All OK */
1.1.1.14  root      194:        return true;
1.1       root      195: }
                    196: 
1.1.1.5   root      197: 
                    198: /*-----------------------------------------------------------------------*/
1.1.1.10  root      199: /**
                    200:  * Close snapshot file.
                    201:  */
1.1.1.5   root      202: static void MemorySnapShot_CloseFile(void)
1.1       root      203: {
1.1.1.5   root      204:        MemorySnapShot_fclose(CaptureFile);
1.1       root      205: }
                    206: 
1.1.1.5   root      207: 
                    208: /*-----------------------------------------------------------------------*/
1.1.1.10  root      209: /**
                    210:  * Save/Restore data to/from file.
                    211:  */
1.1       root      212: void MemorySnapShot_Store(void *pData, int Size)
                    213: {
1.1.1.5   root      214:        long nBytes;
1.1.1.3   root      215: 
1.1.1.5   root      216:        /* Check no file errors */
                    217:        if (CaptureFile != NULL)
                    218:        {
                    219:                /* Saving or Restoring? */
                    220:                if (bCaptureSave)
                    221:                        nBytes = MemorySnapShot_fwrite(CaptureFile, (char *)pData, Size);
                    222:                else
                    223:                        nBytes = MemorySnapShot_fread(CaptureFile, (char *)pData, Size);
                    224: 
                    225:                /* Did save OK? */
                    226:                if (nBytes != Size)
1.1.1.14  root      227:                        bCaptureError = true;
1.1.1.5   root      228:        }
1.1       root      229: }
                    230: 
1.1.1.5   root      231: 
                    232: /*-----------------------------------------------------------------------*/
1.1.1.10  root      233: /**
                    234:  * Save 'snapshot' of memory/chips/emulation variables
                    235:  */
1.1.1.12  root      236: void MemorySnapShot_Capture(const char *pszFileName, bool bConfirm)
1.1       root      237: {
1.1.1.5   root      238:        /* Set to 'saving' */
1.1.1.14  root      239:        if (MemorySnapShot_OpenFile(pszFileName, true))
1.1.1.5   root      240:        {
                    241:                /* Capture each files details */
1.1.1.14  root      242:                Configuration_MemorySnapShot_Capture(true);
                    243:                TOS_MemorySnapShot_Capture(true);
1.1.1.15  root      244:                STMemory_MemorySnapShot_Capture(true);
1.1.1.14  root      245:                FDC_MemorySnapShot_Capture(true);
                    246:                Floppy_MemorySnapShot_Capture(true);
                    247:                GemDOS_MemorySnapShot_Capture(true);
1.1.1.19! root      248:                ACIA_MemorySnapShot_Capture(true);
1.1.1.14  root      249:                IKBD_MemorySnapShot_Capture(true);
1.1.1.15  root      250:                CycInt_MemorySnapShot_Capture(true);
                    251:                Cycles_MemorySnapShot_Capture(true);
1.1.1.14  root      252:                M68000_MemorySnapShot_Capture(true);
                    253:                MFP_MemorySnapShot_Capture(true);
                    254:                PSG_MemorySnapShot_Capture(true);
                    255:                Sound_MemorySnapShot_Capture(true);
                    256:                Video_MemorySnapShot_Capture(true);
                    257:                Blitter_MemorySnapShot_Capture(true);
                    258:                DmaSnd_MemorySnapShot_Capture(true);
1.1.1.16  root      259:                Crossbar_MemorySnapShot_Capture(true);
                    260:                VIDEL_MemorySnapShot_Capture(true);
1.1.1.14  root      261:                DSP_MemorySnapShot_Capture(true);
1.1.1.15  root      262:                DebugUI_MemorySnapShot_Capture(pszFileName, true);
1.1.1.16  root      263:                IoMem_MemorySnapShot_Capture(true);
1.1.1.5   root      264:                /* And close */
                    265:                MemorySnapShot_CloseFile();
1.1.1.16  root      266:        } else {
                    267:                /* just canceled? */
                    268:                if (!bCaptureError)
                    269:                        return;
1.1.1.5   root      270:        }
                    271: 
                    272:        /* Did error */
                    273:        if (bCaptureError)
1.1.1.7   root      274:                Log_AlertDlg(LOG_ERROR, "Unable to save memory state to file.");
1.1.1.10  root      275:        else if (bConfirm)
1.1.1.7   root      276:                Log_AlertDlg(LOG_INFO, "Memory state file saved.");
1.1       root      277: }
                    278: 
1.1.1.5   root      279: 
                    280: /*-----------------------------------------------------------------------*/
1.1.1.10  root      281: /**
                    282:  * Restore 'snapshot' of memory/chips/emulation variables
                    283:  */
1.1.1.12  root      284: void MemorySnapShot_Restore(const char *pszFileName, bool bConfirm)
1.1       root      285: {
1.1.1.5   root      286:        /* Set to 'restore' */
1.1.1.14  root      287:        if (MemorySnapShot_OpenFile(pszFileName, false))
1.1.1.5   root      288:        {
1.1.1.14  root      289:                Configuration_MemorySnapShot_Capture(false);
                    290:                TOS_MemorySnapShot_Capture(false);
1.1.1.10  root      291: 
1.1.1.5   root      292:                /* Reset emulator to get things running */
1.1.1.10  root      293:                IoMem_UnInit();  IoMem_Init();
1.1.1.5   root      294:                Reset_Cold();
                    295: 
                    296:                /* Capture each files details */
1.1.1.15  root      297:                STMemory_MemorySnapShot_Capture(false);
1.1.1.14  root      298:                FDC_MemorySnapShot_Capture(false);
                    299:                Floppy_MemorySnapShot_Capture(false);
                    300:                GemDOS_MemorySnapShot_Capture(false);
1.1.1.19! root      301:                ACIA_MemorySnapShot_Capture(false);
        !           302:                IKBD_MemorySnapShot_Capture(false);                     /* After ACIA */
1.1.1.15  root      303:                CycInt_MemorySnapShot_Capture(false);
                    304:                Cycles_MemorySnapShot_Capture(false);
1.1.1.14  root      305:                M68000_MemorySnapShot_Capture(false);
                    306:                MFP_MemorySnapShot_Capture(false);
                    307:                PSG_MemorySnapShot_Capture(false);
                    308:                Sound_MemorySnapShot_Capture(false);
                    309:                Video_MemorySnapShot_Capture(false);
                    310:                Blitter_MemorySnapShot_Capture(false);
                    311:                DmaSnd_MemorySnapShot_Capture(false);
1.1.1.16  root      312:                Crossbar_MemorySnapShot_Capture(false);
                    313:                VIDEL_MemorySnapShot_Capture(false);
1.1.1.14  root      314:                DSP_MemorySnapShot_Capture(false);
1.1.1.15  root      315:                DebugUI_MemorySnapShot_Capture(pszFileName, false);
1.1.1.16  root      316:                IoMem_MemorySnapShot_Capture(false);
1.1.1.5   root      317: 
                    318:                /* And close */
                    319:                MemorySnapShot_CloseFile();
1.1.1.16  root      320: 
                    321:                /* changes may affect also info shown in statusbar */
                    322:                Statusbar_UpdateInfo();
1.1.1.5   root      323:        }
                    324: 
                    325:        /* Did error? */
                    326:        if (bCaptureError)
1.1.1.7   root      327:                Log_AlertDlg(LOG_ERROR, "Unable to restore memory state from file.");
1.1.1.10  root      328:        else if (bConfirm)
1.1.1.7   root      329:                Log_AlertDlg(LOG_INFO, "Memory state file restored.");
1.1       root      330: }
1.1.1.10  root      331: 
                    332: 
                    333: /*-----------------------------------------------------------------------*/
                    334: /*
                    335:  * Save and restore functions required by the UAE CPU core...
                    336:  * ... don't use them in normal Hatari code!
                    337:  */
                    338: #include <savestate.h>
                    339: 
                    340: void save_u32(uae_u32 data)
                    341: {
                    342:        MemorySnapShot_Store(&data, 4);
                    343: }
                    344: 
                    345: void save_u16(uae_u16 data)
                    346: {
                    347:        MemorySnapShot_Store(&data, 2);
                    348: }
                    349: 
                    350: uae_u32 restore_u32(void)
                    351: {
                    352:        uae_u32 data;
                    353:        MemorySnapShot_Store(&data, 4);
                    354:        return data;
                    355: }
                    356: 
                    357: uae_u16 restore_u16(void)
                    358: {
                    359:        uae_u16 data;
                    360:        MemorySnapShot_Store(&data, 2);
                    361:        return data;
                    362: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.