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