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

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
        !           623:         motor state             1 (off=0,on=1)
        !           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.