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

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

unix.superglobalmegacorp.com

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