Annotation of uae/src/savestate.c, revision 1.1.1.2

1.1       root        1:  /*
                      2:   * UAE - The Un*x Amiga Emulator
                      3:   *
                      4:   * Save/restore emulator state
                      5:   *
                      6:   * (c) 1999-2001 Toni Wilen
                      7:   *
                      8:   * see below for ASF-structure
                      9:   */
                     10: 
                     11:  /* Features:
                     12:   *
                     13:   * - full CPU state (68000/68010/68020, no FPU)
                     14:   * - full CIA-A and CIA-B state (with all internal registers)
                     15:   * - saves all custom registers and audio internal state but not all registers are restored yet.
                     16:   * - only Chip-ram and Bogo-ram are saved and restored.
                     17:   * - disk drive type, imagefile, track and motor state
                     18:   * - Kickstart ROM version, address and size is saved. This data is not used during restore yet.
                     19:   */
                     20: 
                     21:  /* Notes:
                     22:   *
                     23:   * - blitter state is not saved, blitter is forced to finish immediately if it
                     24:   *   was active
                     25:   * - disk DMA state is completely saved (I hope so..)
                     26:   * - does not ask for statefile name and description. Currently uses DF0's disk
                     27:   *   image name (".adf" is replaced with ".asf")
                     28:   * - only Amiga state is restored, harddisk support, autoconfig, expansion boards etc..
                     29:   *   are not saved/restored (and probably never will).
                     30:   * - use this for saving games that can't be saved to disk
                     31:   */
                     32: 
                     33:  /* Usage :
                     34:   *
                     35:   * save:
                     36:   * 
                     37:   * set savestate_state = STATE_DOSAVE, savestate_filename = "..."
                     38:   *
                     39:   * restore:
                     40:   * 
                     41:   * set savestate_state = STATE_DORESTORE, savestate_filename = "..."
                     42:   *
                     43:   */
                     44: 
                     45: #include "sysconfig.h"
                     46: #include "sysdeps.h"
                     47: 
                     48: #include "config.h"
                     49: #include "options.h"
                     50: #include "memory.h"
                     51: 
                     52: #include "savestate.h"
                     53: 
                     54: int savestate_state;
                     55: 
                     56: char *savestate_filename;
                     57: FILE *savestate_file;
                     58: 
                     59: /* functions for reading/writing bytes, shorts and longs in big-endian
                     60:  * format independent of host machine's endianess */
                     61: 
                     62: void save_u32_func (uae_u8 **dstp, uae_u32 v)
                     63: {
                     64:     uae_u8 *dst = *dstp;
                     65:     *dst++ = (uae_u8)(v >> 24);
                     66:     *dst++ = (uae_u8)(v >> 16);
                     67:     *dst++ = (uae_u8)(v >> 8);
                     68:     *dst++ = (uae_u8)(v >> 0);
                     69:     *dstp = dst;
                     70: }
                     71: void save_u16_func (uae_u8 **dstp, uae_u16 v)
                     72: {
                     73:     uae_u8 *dst = *dstp;
                     74:     *dst++ = (uae_u8)(v >> 8);
                     75:     *dst++ = (uae_u8)(v >> 0);
                     76:     *dstp = dst;
                     77: }
                     78: void save_u8_func (uae_u8 **dstp, uae_u8 v)
                     79: {
                     80:     uae_u8 *dst = *dstp;
                     81:     *dst++ = v;
                     82:     *dstp = dst;
                     83: }
                     84: void save_string_func (uae_u8 **dstp, char *from)
                     85: {
                     86:     uae_u8 *dst = *dstp;
                     87:     while(*from)
                     88:        *dst++ = *from++;
                     89:     *dst++ = 0;
                     90:     *dstp = dst;
                     91: }
                     92: 
                     93: uae_u32 restore_u32_func (uae_u8 **dstp)
                     94: {
                     95:     uae_u32 v;
                     96:     uae_u8 *dst = *dstp;
                     97:     v = (dst[0] << 24) | (dst[1] << 16) | (dst[2] << 8) | (dst[3]);
                     98:     *dstp = dst + 4;
                     99:     return v;
                    100: }
                    101: uae_u16 restore_u16_func (uae_u8 **dstp)
                    102: {
                    103:     uae_u16 v;
                    104:     uae_u8 *dst = *dstp;
                    105:     v=(dst[0] << 8) | (dst[1]);
                    106:     *dstp = dst + 2;
                    107:     return v;
                    108: }
                    109: uae_u8 restore_u8_func (uae_u8 **dstp)
                    110: {
                    111:     uae_u8 v;
                    112:     uae_u8 *dst = *dstp;
                    113:     v = dst[0];
                    114:     *dstp = dst + 1;
                    115:     return v;
                    116: }
                    117: char *restore_string_func (uae_u8 **dstp)
                    118: {
                    119:     int len;
                    120:     uae_u8 v;
                    121:     uae_u8 *dst = *dstp;
                    122:     char *top, *to;
                    123:     len = strlen(dst) + 1;
                    124:     top = to = malloc (len);
                    125:     do {
                    126:        v = *dst++;
                    127:        *top++ = v;
                    128:     } while(v);
                    129:     *dstp = dst;
                    130:     return to; 
                    131: }
                    132: 
                    133: /* read and write IFF-style hunks */
                    134: 
                    135: static void save_chunk (FILE *f, uae_u8 *chunk, long len, char *name)
                    136: {
                    137:     uae_u8 tmp[4], *dst;
                    138:     uae_u8 zero[4]= { 0, 0, 0, 0 };
                    139: 
                    140:     if (!chunk)
                    141:        return;
                    142: 
                    143:     /* chunk name */
                    144:     fwrite (name, 1, 4, f);
                    145:     /* chunk size */
                    146:     dst = &tmp[0];
                    147:     save_u32 (len + 4 + 4 + 4);
                    148:     fwrite (&tmp[0], 1, 4, f);
                    149:     /* chunk flags */
                    150:     dst = &tmp[0];
                    151:     save_u32 (0);
                    152:     fwrite (&tmp[0], 1, 4, f);
                    153:     /* chunk data */
                    154:     fwrite (chunk, 1, len, f);
                    155:     /* alignment */
                    156:     len = 4 - (len & 3);
                    157:     if (len)
                    158:        fwrite (zero, 1, len, f);
                    159: }
                    160: 
                    161: static uae_u8 *restore_chunk (FILE *f, char *name, long *len, long *filepos)
                    162: {
                    163:     uae_u8 tmp[4], dummy[4], *mem, *src;
                    164:     uae_u32 flags;
                    165:     long len2;
                    166: 
                    167:     /* chunk name */
                    168:     fread (name, 1, 4, f);
                    169:     name[4] = 0;
                    170:     /* chunk size */
                    171:     fread (tmp, 1, 4, f);
                    172:     src = tmp;
                    173:     len2 = restore_u32 () - 4 - 4 - 4;
                    174:     if (len2 < 0)
                    175:        len2 = 0;
                    176:     *len = len2;
                    177:     if (len2 == 0)
                    178:        return 0;
                    179: 
                    180:     /* chunk flags */
                    181:     fread (tmp, 1, 4, f);
                    182:     src = tmp;
                    183:     flags = restore_u32 ();
                    184: 
                    185:     *filepos = ftell (f);
                    186:     /* chunk data.  RAM contents will be loaded during the reset phase,
                    187:        no need to malloc multiple megabytes here.  */
                    188:     if (strcmp (name, "CRAM") != 0
                    189:        && strcmp (name, "BRAM") != 0
                    190:        && strcmp (name, "FRAM") != 0
                    191:        && strcmp (name, "ZRAM") != 0)
                    192:     {
                    193:        mem = malloc (len2);
                    194:        fread (mem, 1, len2, f);
                    195:     } else {
                    196:        mem = 0;
                    197:        fseek (f, len2, SEEK_CUR);
                    198:     }
                    199: 
                    200:     /* alignment */
                    201:     len2 = 4 - (len2 & 3);
                    202:     if (len2)
                    203:        fread (dummy, 1, len2, f);
                    204:     return mem;
                    205: }
                    206: 
                    207: static void restore_header (uae_u8 *src)
                    208: {
                    209:     char *emuname, *emuversion, *description;
                    210: 
                    211:     restore_u32();
                    212:     emuname = restore_string ();
                    213:     emuversion = restore_string ();
                    214:     description = restore_string ();
                    215:     write_log ("Saved with: '%s %s', description: '%s'\n",
                    216:        emuname,emuversion,description);
                    217:     free (description);
                    218:     free (emuversion);
                    219:     free (emuname);
                    220: }
                    221: 
                    222: /* restore all subsystems */
                    223: 
                    224: void restore_state (char *filename)
                    225: {
                    226:     FILE *f;
                    227:     uae_u8 *chunk,*end;
                    228:     char name[5];
                    229:     long len;
                    230:     long filepos;
                    231: 
                    232:     chunk = 0;
                    233:     f = fopen (filename, "rb");
                    234:     if (!f)
                    235:        goto error;
                    236: 
                    237:     chunk = restore_chunk (f, name, &len, &filepos);
                    238:     if (!chunk || memcmp (name, "ASF ", 4)) {
                    239:        write_log ("%s is not an AmigaStateFile\n",filename);
                    240:        goto error;
                    241:     }
                    242:     savestate_file = f;
                    243:     restore_header (chunk);
                    244:     free (chunk);
                    245:     savestate_state = STATE_RESTORE;
                    246:     for (;;) {
                    247:        chunk = restore_chunk (f, name, &len, &filepos);
                    248:        write_log ("Chunk '%s' size %d\n", name, len);
                    249:        if (!strcmp (name, "END "))
                    250:            break;
                    251:        if (!strcmp (name, "CRAM")) {
                    252:            restore_cram (len, filepos);
                    253:            continue;
                    254:        }
                    255:        else if (!strcmp (name, "BRAM")) {
                    256:            restore_bram (len, filepos);
                    257:            continue;
                    258:        } else if (!strcmp (name, "FRAM")) {
                    259:            restore_fram (len, filepos);
                    260:            continue;
                    261:        } else if (!strcmp (name, "ZRAM")) {
                    262:            restore_zram (len, filepos);
                    263:            continue;
                    264:        }
                    265: 
                    266:        if (!strcmp (name, "CPU "))
                    267:            end = restore_cpu (chunk);
                    268:        else if (!strcmp (name, "AGAC"))
                    269:            end = restore_custom_agacolors (chunk);
                    270:        else if (!strcmp (name, "SPR0"))
                    271:            end = restore_custom_sprite (chunk, 0);
                    272:        else if (!strcmp (name, "SPR1"))
                    273:            end = restore_custom_sprite (chunk, 1);
                    274:        else if (!strcmp (name, "SPR2"))
                    275:            end = restore_custom_sprite (chunk, 2);
                    276:        else if (!strcmp (name, "SPR3"))
                    277:            end = restore_custom_sprite (chunk, 3);
                    278:        else if (!strcmp (name, "SPR4"))
                    279:            end = restore_custom_sprite (chunk, 4);
                    280:        else if (!strcmp (name, "SPR5"))
                    281:            end = restore_custom_sprite (chunk, 5);
                    282:        else if (!strcmp (name, "SPR6"))
                    283:            end = restore_custom_sprite (chunk, 6);
                    284:        else if (!strcmp (name, "SPR7"))
                    285:            end = restore_custom_sprite (chunk, 7);
                    286:        else if (!strcmp (name, "CIAA"))
                    287:            end = restore_cia (0, chunk);
                    288:        else if (!strcmp (name, "CIAB"))
                    289:            end = restore_cia (1, chunk);
                    290:        else if (!strcmp (name, "CHIP"))
                    291:            end = restore_custom (chunk);
                    292:        else if (!strcmp (name, "AUD0"))
                    293:            end = restore_audio (chunk, 0);
                    294:        else if (!strcmp (name, "AUD1"))
                    295:            end = restore_audio (chunk, 1);
                    296:        else if (!strcmp (name, "AUD2"))
                    297:            end = restore_audio (chunk, 2);
                    298:        else if (!strcmp (name, "AUD3"))
                    299:            end = restore_audio (chunk, 3);
                    300: #if 0
                    301:        else if (!strcmp (name, "BLIT"))
                    302:            end = restore_custom_blitter (chunk);
                    303: #endif
                    304:        else if (!strcmp (name, "DISK"))
                    305:            end = restore_floppy (chunk);
                    306:        else if (!strcmp (name, "DSK0"))
                    307:            end = restore_disk (0, chunk);
                    308:        else if (!strcmp (name, "DSK1"))
                    309:            end = restore_disk (1, chunk);
                    310:        else if (!strcmp (name, "DSK2"))
                    311:            end = restore_disk (2, chunk);
                    312:        else if (!strcmp (name, "DSK3"))
                    313:            end = restore_disk (3, chunk);
                    314:        else if (!strcmp (name, "EXPA"))
                    315:            end = restore_expansion (chunk);
                    316:        else if (!strcmp (name, "ROM "))
                    317:            end = restore_rom (chunk);
                    318:        else
                    319:            write_log ("unknown chunk '%s' size %d bytes\n", name, len);
                    320:        if (len != end - chunk)
                    321:            write_log ("Chunk '%s' total size %d bytes but read %d bytes!\n",
                    322:                       name, len, end - chunk);
                    323:        free (chunk);
                    324:     }
                    325:     return;
                    326: 
                    327:     error:
                    328:     savestate_state = 0;
                    329:     savestate_file = 0;
                    330:     if (chunk)
                    331:        free (chunk);
                    332:     if (f)
                    333:        fclose (f);
                    334: }
                    335: 
                    336: void savestate_restore_finish (void)
                    337: {
                    338:     if (savestate_state != STATE_RESTORE)
                    339:        return;
                    340:     fclose (savestate_file);
                    341:     savestate_file = 0;
                    342:     savestate_state = 0;
                    343: }
                    344: 
                    345: /* Save all subsystems  */
                    346: 
                    347: void save_state (char *filename, char *description)
                    348: {
                    349:     uae_u8 header[1000];
                    350:     char tmp[100];
                    351:     uae_u8 *dst;
                    352:     FILE *f;
                    353:     int len,i;
                    354:     char name[5];
                    355: 
                    356:     f = fopen (filename, "wb");
                    357:     if (!f)
                    358:        return;
                    359: 
                    360:     dst = header;
                    361:     save_u32 (0);
                    362:     save_string("UAE");
                    363:     sprintf (tmp, "%d.%d.%d", UAEMAJOR, UAEMINOR, UAESUBREV);
                    364:     save_string (tmp);
                    365:     save_string (description);
                    366:     save_chunk (f, header, dst-header, "ASF ");
                    367: 
                    368:     dst = save_cpu (&len);
                    369:     save_chunk (f, dst, len, "CPU ");
                    370:     free (dst);
                    371: 
                    372:     strcpy(name, "DSKx");
                    373:     for (i = 0; i < 4; i++) {
                    374:        dst = save_disk (i, &len);
                    375:        if (dst) {
                    376:            name[3] = i + '0';
                    377:            save_chunk (f, dst, len, name);
                    378:            free (dst);
                    379:        }
                    380:     }
                    381:     dst = save_floppy (&len);
                    382:     save_chunk (f, dst, len, "DISK");
                    383:     free (dst);
                    384: 
                    385:     dst = save_custom (&len);
                    386:     save_chunk (f, dst, len, "CHIP");
                    387:     free (dst);
                    388: 
                    389: #if 0
                    390:     dst = save_custom_blitter (&len);
                    391:     save_chunk (f, dst, len, "BLIT");
                    392:     free (dst);
                    393: #endif
                    394: 
                    395:     dst = save_custom_agacolors (&len);
                    396:     save_chunk (f, dst, len, "AGAC");
                    397:     free (dst);
                    398: 
                    399:     strcpy (name, "SPRx");
                    400:     for (i = 0; i < 8; i++) {
                    401:        dst = save_custom_sprite (&len, i);
                    402:        name[3] = i + '0';
                    403:        save_chunk (f, dst, len, name);
                    404:        free (dst);
                    405:     }
                    406: 
                    407:     strcpy (name, "AUDx");
                    408:     for (i = 0; i < 4; i++) {
                    409:        dst = save_audio (&len, i);
                    410:        name[3] = i + '0';
                    411:        save_chunk (f, dst, len, name);
                    412:        free (dst);
                    413:     }
                    414: 
                    415:     dst = save_cia (0, &len);
                    416:     save_chunk (f, dst, len, "CIAA");
                    417:     free (dst);
                    418: 
                    419:     dst = save_cia (1, &len);
                    420:     save_chunk (f, dst, len, "CIAB");
                    421:     free (dst);
                    422: 
                    423:     dst = save_expansion (&len);
                    424:     save_chunk (f, dst, len, "EXPA");
                    425:     dst = save_cram (&len);
                    426:     save_chunk (f, dst, len, "CRAM");
                    427:     dst = save_bram (&len);
                    428:     save_chunk (f, dst, len, "BRAM");
                    429:     dst = save_fram (&len);
                    430:     save_chunk (f, dst, len, "FRAM");
                    431:     dst = save_zram (&len);
                    432:     save_chunk (f, dst, len, "ZRAM");
                    433: 
                    434:     dst = save_rom (1, &len);
                    435:     do {
                    436:        if (!dst)
                    437:            break;
                    438:        save_chunk (f, dst, len, "ROM ");
                    439:        free (dst);
                    440:     } while ((dst = save_rom (0, &len)));
                    441: 
                    442:     fwrite ("END ", 1, 4, f);
                    443:     fwrite ("\0\0\0\08", 1, 4, f);
                    444:     write_log ("Save of '%s' complete\n", filename);
                    445:     fclose (f);
                    446: }
                    447: 
                    448: /*
                    449: 
                    450: My (Toni Wilen <[email protected]>)
                    451: proposal for Amiga-emulators' state-save format
                    452: 
                    453: Feel free to comment...
                    454: 
                    455: This is very similar to IFF-fileformat
                    456: Every hunk must end to 4 byte boundary,
                    457: fill with zero bytes if needed
                    458: 
                    459: version 0.7
                    460: 
                    461: HUNK HEADER (beginning of every hunk)
                    462: 
                    463:         hunk name (4 ascii-characters)
                    464:         hunk size (including header)
                    465:         hunk flags             
                    466: 
                    467:         bit 0 = chunk contents are compressed with zlib (maybe RAM chunks only?)
                    468: 
                    469: HEADER
                    470: 
                    471:         "ASF " (AmigaStateFile)
                    472:         
                    473:        statefile version
                    474:         emulator name ("uae", "fellow" etc..)
                    475:         emulator version string (example: "0.8.15")
                    476:         free user writable comment string
                    477: 
                    478: CPU
                    479: 
                    480:          "CPU "
                    481: 
                    482:         CPU model               4 (68000,68010 etc..)
                    483:         CPU typeflags           bit 0=EC-model or not
                    484:         D0-D7                   8*4=32
                    485:         A0-A6                   7*4=32
                    486:         PC                      4
                    487:         prefetch address        4
                    488:         prefetch data           4
                    489:         USP                     4
                    490:         ISP                     4
                    491:         SR/CCR                  2
                    492:         flags                   4 (bit 0=CPU was HALTed)
                    493: 
                    494:         CPU specific registers
                    495: 
                    496:         68000: SR/CCR is last saved register
                    497:         68010: save also DFC,SFC and VBR
                    498:         68020: all 68010 registers and CAAR,CACR and MSP
                    499:         etc..
                    500: 
                    501:         DFC                     4 (010+)
                    502:         SFC                     4 (010+)
                    503:         VBR                     4 (010+)
                    504: 
                    505:         CAAR                    4 (020-030)
                    506:         CACR                    4 (020+)
                    507:         MSP                     4 (020+)
                    508: 
                    509: MMU (when and if MMU is supported in future..)
                    510: 
                    511:         MMU model               4 (68851,68030,68040)
                    512: 
                    513:         // 68040 fields
                    514: 
                    515:         ITT0                    4
                    516:         ITT1                    4
                    517:         DTT0                    4
                    518:         DTT1                    4
                    519:         URP                     4
                    520:         SRP                     4
                    521:         MMUSR                   4
                    522:         TC                      2
                    523: 
                    524:                
                    525: FPU (only if used)
                    526: 
                    527:        "FPU "
                    528: 
                    529:         FPU model               4 (68881 or 68882)
                    530:         FPU typeflags           4 (keep zero)
                    531: 
                    532:         FP0-FP7                 4+2 (80 bits)
                    533:         FPCR                    4
                    534:         FPSR                    4
                    535:         FPIAR                   4
                    536: 
                    537: CUSTOM CHIPS
                    538: 
                    539:         "CHIP"
                    540: 
                    541:         chipset flags   4      OCS=0,ECSAGNUS=1,ECSDENISE=2,AGA=4
                    542:                                ECSAGNUS and ECSDENISE can be combined
                    543: 
                    544:         DFF000-DFF1FF   352    (0x120 - 0x17f and 0x0a0 - 0xdf excluded)
                    545: 
                    546:         sprite registers (0x120 - 0x17f) saved with SPRx chunks
                    547:         audio registers (0x0a0 - 0xdf) saved with AUDx chunks
                    548: 
                    549: AGA COLORS
                    550: 
                    551:         "AGAC"
                    552: 
                    553:         AGA color               8 banks * 32 registers *
                    554:         registers               LONG (XRGB) = 1024
                    555: 
                    556: SPRITE
                    557: 
                    558:         "SPR0" - "SPR7"
                    559: 
                    560: 
                    561:         SPRxPT                  4
                    562:         SPRxPOS                 2
                    563:         SPRxCTL                 2
                    564:         SPRxDATA                2
                    565:         SPRxDATB                2
                    566:         AGA sprite DATA/DATB    3 * 2 * 2
                    567:         sprite "armed" status   1
                    568: 
                    569:         sprites maybe armed in non-DMA mode
                    570:         use bit 0 only, other bits are reserved
                    571: 
                    572: 
                    573: AUDIO
                    574:         "AUD0" "AUD1" "AUD2" "AUD3"
                    575: 
                    576:         audio state             1
                    577:         machine mode
                    578:         AUDxVOL                 1
                    579:        irq?                    1
                    580:        data_written?           1
                    581:         internal AUDxLEN        2
                    582:         AUDxLEN                 2
                    583:        internal AUDxPER        2
                    584:        AUDxPER                 2
                    585:         internal AUDxLC         4
                    586:        AUDxLC                  4
                    587:        evtime?                 4
                    588: 
                    589: BLITTER
                    590: 
                    591:         "BLIT"
                    592: 
                    593:         internal blitter state
                    594: 
                    595:         blitter running         1
                    596:         anything else?
                    597: 
                    598: CIA
                    599: 
                    600:         "CIAA" and "CIAB"
                    601: 
                    602:         BFE001-BFEF01   16*1 (CIAA)
                    603:         BFD000-BFDF00   16*1 (CIAB)
                    604: 
                    605:         internal registers
                    606: 
                    607:         IRQ mask (ICR)  1 BYTE
                    608:         timer latches   2 timers * 2 BYTES (LO/HI)
                    609:         latched tod     3 BYTES (LO/MED/HI)
                    610:         alarm           3 BYTES (LO/MED/HI)
                    611:         flags           1 BYTE
                    612:                         bit 0=tod latched (read)
                    613:                         bit 1=tod stopped (write)
                    614:        div10 counter   1 BYTE
                    615: 
                    616: FLOPPY DRIVES
                    617: 
                    618:         "DSK0" "DSK1" "DSK2" "DSK3"
                    619: 
                    620:         drive state
                    621: 
                    622:         drive ID-word           4
1.1.1.2 ! root      623:         state                   1 (bit 0: motor on, bit 1: drive disabled)
1.1       root      624:         rw-head track           1
                    625:         dskready                1
                    626:         id-mode                 1 (ID mode bit number 0-31)
                    627:         floppy information
                    628: 
                    629:         bits from               4
                    630:         beginning of track
                    631:         CRC of disk-image       4 (used during restore to check if image
                    632:                                   is correct)
                    633:         disk-image              null-terminated
                    634:         file name
                    635: 
                    636: INTERNAL FLOPPY CONTROLLER STATUS
                    637: 
                    638:         "DISK"
                    639: 
                    640:         current DMA word        2
                    641:         DMA word bit offset     1
                    642:         WORDSYNC found          1 (no=0,yes=1)
                    643:         hpos of next bit        1
                    644:         DSKLENGTH status        0=off,1=written once,2=written twice
                    645: 
                    646: RAM SPACE 
                    647: 
                    648:         "xRAM" (CRAM = chip, BRAM = bogo, FRAM = fast, ZFRAM = Z3)
                    649: 
                    650:         start address           4 ("bank"=chip/slow/fast etc..)
                    651:         of RAM "bank"
                    652:         RAM "bank" size         4
                    653:         RAM flags               4
                    654:         RAM "bank" contents
                    655: 
                    656: ROM SPACE
                    657: 
                    658:         "ROM "
                    659: 
                    660:         ROM start               4
                    661:         address
                    662:         size of ROM             4
                    663:         ROM type                4 KICK=0
                    664:         ROM flags               4
                    665:         ROM version             2
                    666:         ROM revision            2
                    667:         ROM CRC                 4 see below
                    668:         ROM-image               null terminated, see below
                    669:         ID-string
                    670:         ROM contents            (Not mandatory, use hunk size to check if
                    671:                                 this hunk contains ROM data or not)
                    672: 
                    673:         Kickstart ROM:
                    674:          ID-string is "Kickstart x.x"
                    675:          ROM version: version in high word and revision in low word
                    676:          Kickstart ROM version and revision can be found from ROM start
                    677:          + 12 (version) and +14 (revision)
                    678: 
                    679:         ROM version and CRC is only meant for emulator to automatically
                    680:         find correct image from its ROM-directory during state restore.
                    681: 
                    682:         Usually saving ROM contents is not good idea.
                    683: 
                    684: 
                    685: END
                    686:         hunk "END " ends, remember hunk size 8!
                    687: 
                    688: 
                    689: EMULATOR SPECIFIC HUNKS
                    690: 
                    691: Read only if "emulator name" in header is same as used emulator.
                    692: Maybe useful for configuration?
                    693: 
                    694: misc:
                    695: 
                    696: - save only at position 0,0 before triggering VBLANK interrupt
                    697: - all data must be saved in bigendian format
                    698: - should we strip all paths from image file names?
                    699: 
                    700: */

unix.superglobalmegacorp.com

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