|
|
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: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.