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

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

unix.superglobalmegacorp.com

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