|
|
1.1 root 1: /* Generator is (c) James Ponder, 1997-2001 http://www.squish.net/generator/ */
2:
3: #include <sys/stat.h>
4: #include <unistd.h>
5: #include <stdio.h>
6: #include <stdlib.h>
7: #include <errno.h>
8: #include <time.h>
9: #include <string.h>
10: #include <errno.h>
11:
12: #include "generator.h"
13: #include "snprintf.h"
14:
15: #include "state.h"
16: #include "ui.h"
17: #include "cpu68k.h"
18: #include "cpuz80.h"
19: #include "vdp.h"
20: #include "gensound.h"
21: #include "fm.h"
22:
23: /*
24: * NB:
25: * states are only loaded/saved at the end of the frame
26: * all local values are stored in network / 68k format (big endian)
27: */
28:
1.1.1.2 ! root 29: struct savestate
! 30: {
1.1 root 31: /* must ensure everything is aligned as expected */
32: char s_majorver[1];
33: char s_minorver[1];
1.1.1.2 ! root 34: char reserved1[2]; /* align */
1.1 root 35: char s_ram[0x10000];
36: char s_vram[0x10000];
37: char s_z80ram[0x2000];
38: char s_cram[0x80];
39: char s_vsram[0x50];
1.1.1.2 ! root 40: char s_68k_regs[4 * 16];
1.1 root 41: char s_68k_pc[4];
42: char s_68k_sp[4];
43: char s_68k_sr[2];
44: char s_68k_stop[1];
45: char s_68k_pending[1];
46: char s_z80_af[2];
47: char s_z80_bc[2];
48: char s_z80_de[2];
49: char s_z80_hl[2];
50: char s_z80_afprime[2];
51: char s_z80_bcprime[2];
52: char s_z80_deprime[2];
53: char s_z80_hlprime[2];
54: char s_z80_ix[2];
55: char s_z80_iy[2];
56: char s_z80_sp[2];
57: char s_z80_pc[2];
58: char s_z80_i[1];
59: char s_z80_r[1];
60: char s_z80_active[1];
1.1.1.2 ! root 61: char s_z80_halted[1]; /* was reserved in 0.31 */
1.1 root 62: char s_z80_bank[4];
63: char s_fmregs1[256];
64: char s_fmregs2[256];
65: char s_fmaddr1[1];
66: char s_fmaddr2[1];
67: char s_vdp_regs[25];
1.1.1.2 ! root 68: char s_z80_im[1]; /* was reserved in 0.31 */
1.1 root 69: char s_vdp_pal[1];
70: char s_vdp_overseas[1];
71: char s_vdp_ctrlflag[1];
72: char s_vdp_code[1];
1.1.1.2 ! root 73: char s_vdp_first[2]; /* possibly only top two bits required here */
! 74: char s_vdp_second[2]; /* used for unterminated ctrl writes */
1.1 root 75: char s_vdp_dmabytes[4];
76: char s_vdp_address[2];
1.1.1.2 ! root 77: char s_z80_iff1[1]; /* was reserved in 0.31 */
! 78: char s_z80_iff2[1]; /* was reserved in 0.31 */
1.1 root 79: };
80:
81: /*** state_date - return the modification date or 0 for non-existant ***/
82:
83: time_t state_date(const int slot)
84: {
85: char filename[256];
86: struct stat statbuf;
87:
88: snprintf(filename, sizeof(filename), "%s.gt%d", gen_leafname, slot);
89:
90: if (stat(filename, &statbuf) != 0)
91: return 0;
92: return statbuf.st_mtime;
93: }
94:
95: /*** state_load - load the given slot ***/
96:
97: int state_load(const int slot)
98: {
99: char filename[256];
100: struct savestate *ssp;
101: char *ss;
102: struct stat statbuf;
103: FILE *f, *a;
104: int i;
105:
106: snprintf(filename, sizeof(filename), "%s.gt%d", gen_leafname, slot);
107: if (stat(filename, &statbuf) != 0)
108: return -1;
109:
110: if ((ss = malloc(statbuf.st_size)) == NULL) {
1.1.1.2 ! root 111: LOG_CRITICAL(("Failed to allocate memory whilst loading '%s'", filename));
1.1 root 112: return -1;
113: }
114: if ((f = fopen(filename, "rb")) == NULL) {
115: LOG_CRITICAL(("Failed to open '%s': %s", filename, strerror(errno)));
116: return -1;
117: }
118: if (fread(ss, statbuf.st_size, 1, f) != 1) {
119: if (feof(f)) {
120: LOG_CRITICAL(("EOF whilst reading GTR file '%s'", filename));
121: return -1;
122: }
123: LOG_CRITICAL(("Error whilst reading GTR file '%s': %s", filename,
1.1.1.2 ! root 124: strerror(errno)));
1.1 root 125: return -1;
126: }
127: fclose(f);
128:
129: ssp = (struct savestate *)ss;
130:
131: if (ssp->s_majorver[0] != 1) {
132: LOG_CRITICAL(("GTR file '%s' is version %d, and we're version 1",
133: filename, ssp->s_majorver));
134: return -1;
135: }
136: if (statbuf.st_size != sizeof(struct savestate)) {
137: LOG_CRITICAL(("GTR file '%s' is corrupt - it is not %d bytes long",
138: filename, sizeof(struct savestate)));
139: return -1;
140: }
141:
142: gen_reset();
143: memcpy(cpu68k_ram, ssp->s_ram, sizeof(ssp->s_ram));
144: memcpy(vdp_vram, ssp->s_vram, sizeof(ssp->s_vram));
145: memcpy(cpuz80_ram, ssp->s_z80ram, sizeof(ssp->s_z80ram));
146: memcpy(vdp_cram, ssp->s_cram, sizeof(ssp->s_cram));
147: memcpy(vdp_vsram, ssp->s_vsram, sizeof(ssp->s_vsram));
148: for (i = 0; i < 16; i++)
149: regs.regs[i] = LOCENDIAN32(((uint32 *)ssp->s_68k_regs)[i]);
150: regs.pc = LOCENDIAN32(*(uint32 *)ssp->s_68k_pc);
151: regs.sp = LOCENDIAN32(*(uint32 *)ssp->s_68k_sp);
152: regs.sr.sr_int = LOCENDIAN16(*(uint16 *)ssp->s_68k_sr);
153: regs.stop = ssp->s_68k_stop[0];
154: regs.pending = ssp->s_68k_pending[0];
155: #ifdef RAZE
1.1.1.2 ! root 156: z80_set_reg(Z80_REG_AF, LOCENDIAN16(*(uint16 *)ssp->s_z80_af));
! 157: z80_set_reg(Z80_REG_BC, LOCENDIAN16(*(uint16 *)ssp->s_z80_bc));
! 158: z80_set_reg(Z80_REG_DE, LOCENDIAN16(*(uint16 *)ssp->s_z80_de));
! 159: z80_set_reg(Z80_REG_HL, LOCENDIAN16(*(uint16 *)ssp->s_z80_hl));
1.1 root 160: z80_set_reg(Z80_REG_AF2, LOCENDIAN16(*(uint16 *)ssp->s_z80_afprime));
161: z80_set_reg(Z80_REG_BC2, LOCENDIAN16(*(uint16 *)ssp->s_z80_bcprime));
162: z80_set_reg(Z80_REG_DE2, LOCENDIAN16(*(uint16 *)ssp->s_z80_deprime));
163: z80_set_reg(Z80_REG_HL2, LOCENDIAN16(*(uint16 *)ssp->s_z80_hlprime));
1.1.1.2 ! root 164: z80_set_reg(Z80_REG_IX, LOCENDIAN16(*(uint16 *)ssp->s_z80_ix));
! 165: z80_set_reg(Z80_REG_IY, LOCENDIAN16(*(uint16 *)ssp->s_z80_iy));
! 166: z80_set_reg(Z80_REG_SP, LOCENDIAN16(*(uint16 *)ssp->s_z80_sp));
! 167: z80_set_reg(Z80_REG_PC, LOCENDIAN16(*(uint16 *)ssp->s_z80_pc));
1.1 root 168: z80_set_reg(Z80_REG_IFF1, ssp->s_z80_iff1[0]);
169: z80_set_reg(Z80_REG_IFF2, ssp->s_z80_iff2[0]);
1.1.1.2 ! root 170: z80_set_reg(Z80_REG_IR, ssp->s_z80_i[0] << 8 | ssp->s_z80_r[0]);
1.1 root 171: z80_set_reg(Z80_REG_IM, ssp->s_z80_im[0]);
172: z80_set_reg(Z80_REG_Halted, ssp->s_z80_halted[0]);
173: /* FIX:
1.1.1.2 ! root 174: Z80_REG_IRQVector, 0x00 to 0xff
! 175: Z80_REG_IRQLine, boolean - 1 or 0
! 176: */
1.1 root 177: #else
178: cpuz80_z80.z80af = LOCENDIAN16(*(uint16 *)ssp->s_z80_af);
179: cpuz80_z80.z80bc = LOCENDIAN16(*(uint16 *)ssp->s_z80_bc);
180: cpuz80_z80.z80de = LOCENDIAN16(*(uint16 *)ssp->s_z80_de);
181: cpuz80_z80.z80hl = LOCENDIAN16(*(uint16 *)ssp->s_z80_hl);
182: cpuz80_z80.z80afprime = LOCENDIAN16(*(uint16 *)ssp->s_z80_afprime);
183: cpuz80_z80.z80bcprime = LOCENDIAN16(*(uint16 *)ssp->s_z80_bcprime);
184: cpuz80_z80.z80deprime = LOCENDIAN16(*(uint16 *)ssp->s_z80_deprime);
185: cpuz80_z80.z80hlprime = LOCENDIAN16(*(uint16 *)ssp->s_z80_hlprime);
186: cpuz80_z80.z80ix = LOCENDIAN16(*(uint16 *)ssp->s_z80_ix);
187: cpuz80_z80.z80iy = LOCENDIAN16(*(uint16 *)ssp->s_z80_iy);
188: cpuz80_z80.z80sp = LOCENDIAN16(*(uint16 *)ssp->s_z80_sp);
189: cpuz80_z80.z80pc = LOCENDIAN16(*(uint16 *)ssp->s_z80_pc);
190: cpuz80_z80.z80i = ssp->s_z80_i[0];
191: cpuz80_z80.z80r = ssp->s_z80_r[0];
192: cpuz80_z80.z80inInterrupt = ssp->s_z80_iff1[0];
193: cpuz80_z80.z80interruptState = ssp->s_z80_iff2[0];
194: cpuz80_z80.z80interruptMode = ssp->s_z80_im[0];
195: cpuz80_z80.z80halted = ssp->s_z80_halted[0];
196: /* FIX:
1.1.1.2 ! root 197: c -> z80intAddr = z80intAddr;
! 198: c -> z80nmiAddr = z80nmiAddr;
! 199: */
1.1 root 200: #endif
201: cpuz80_bank = LOCENDIAN32(*(uint32 *)ssp->s_z80_bank);
202:
203:
204: memcpy(vdp_reg, ssp->s_vdp_regs, sizeof(ssp->s_vdp_regs));
205: vdp_pal = ssp->s_vdp_pal[0];
206: vdp_overseas = ssp->s_vdp_overseas[0];
207: vdp_ctrlflag = ssp->s_vdp_ctrlflag[0];
208: vdp_code = ssp->s_vdp_code[0];
209: vdp_first = LOCENDIAN16(*(uint16 *)ssp->s_vdp_first);
210: vdp_second = LOCENDIAN16(*(uint16 *)ssp->s_vdp_second);
211: vdp_dmabytes = LOCENDIAN32(*(uint32 *)ssp->s_vdp_dmabytes);
212: vdp_address = LOCENDIAN16(*(uint16 *)ssp->s_vdp_address);
1.1.1.2 ! root 213:
1.1 root 214: /* reset some other run-time stuff that isn't important enough to save */
215: vdp_setupvideo();
216: vdp_dmabusy = vdp_dmabytes > 0 ? 1 : 0;
217:
218: for (i = 0; i < 256; i++) {
1.1.1.2 ! root 219: sound_ym2612store(0, i);
! 220: sound_ym2612store(1, ssp->s_fmregs1[i]);
! 221: sound_ym2612store(2, i);
! 222: sound_ym2612store(3, ssp->s_fmregs2[i]);
1.1 root 223: }
1.1.1.2 ! root 224: sound_ym2612store(0, ssp->s_fmaddr1[0]);
! 225: sound_ym2612store(1, ssp->s_fmaddr2[0]);
1.1 root 226: cpuz80_updatecontext();
227: return 0;
228: }
229:
230: /*** state_save - save to the given slot ***/
231:
232: int state_save(const int slot)
233: {
234: char filename[256];
235: struct savestate ss;
1.1.1.2 ! root 236: struct savestate *ssp = &ss; /* I want a pointer like the load routines */
1.1 root 237: struct stat statbuf;
238: FILE *f, *a;
239: int i;
240:
241: snprintf(filename, sizeof(filename), "%s.gt%d", gen_leafname, slot);
242: if ((f = fopen(filename, "wb")) == NULL) {
243: LOG_CRITICAL(("Failed to open '%s' for writing: %s",
244: filename, strerror(errno)));
245: return -1;
246: }
247: memset(ssp, 0, sizeof(ss));
248: ssp->s_majorver[0] = 1;
249: ssp->s_minorver[0] = 2;
250: memcpy(ssp->s_ram, cpu68k_ram, sizeof(ssp->s_ram));
251: memcpy(ssp->s_vram, vdp_vram, sizeof(ssp->s_vram));
252: memcpy(ssp->s_z80ram, cpuz80_ram, sizeof(ssp->s_z80ram));
253: memcpy(ssp->s_cram, vdp_cram, sizeof(ssp->s_cram));
254: memcpy(ssp->s_vsram, vdp_vsram, sizeof(ssp->s_vsram));
255: for (i = 0; i < 16; i++)
256: ((uint32 *)ssp->s_68k_regs)[i] = LOCENDIAN32(regs.regs[i]);
257: *(uint32 *)ssp->s_68k_pc = LOCENDIAN32(regs.pc);
258: *(uint32 *)ssp->s_68k_sp = LOCENDIAN32(regs.sp);
259: *(uint16 *)ssp->s_68k_sr = LOCENDIAN16(regs.sr.sr_int);
260: ssp->s_68k_stop[0] = regs.stop;
261: ssp->s_68k_pending[0] = regs.pending;
262: #ifdef RAZE
263: *(uint16 *)ssp->s_z80_af = LOCENDIAN16(z80_get_reg(Z80_REG_AF));
264: *(uint16 *)ssp->s_z80_bc = LOCENDIAN16(z80_get_reg(Z80_REG_BC));
265: *(uint16 *)ssp->s_z80_de = LOCENDIAN16(z80_get_reg(Z80_REG_DE));
266: *(uint16 *)ssp->s_z80_hl = LOCENDIAN16(z80_get_reg(Z80_REG_HL));
267: *(uint16 *)ssp->s_z80_afprime = LOCENDIAN16(z80_get_reg(Z80_REG_AF2));
268: *(uint16 *)ssp->s_z80_bcprime = LOCENDIAN16(z80_get_reg(Z80_REG_BC2));
269: *(uint16 *)ssp->s_z80_deprime = LOCENDIAN16(z80_get_reg(Z80_REG_DE2));
270: *(uint16 *)ssp->s_z80_hlprime = LOCENDIAN16(z80_get_reg(Z80_REG_HL2));
271: *(uint16 *)ssp->s_z80_ix = LOCENDIAN16(z80_get_reg(Z80_REG_IX));
272: *(uint16 *)ssp->s_z80_iy = LOCENDIAN16(z80_get_reg(Z80_REG_IY));
273: *(uint16 *)ssp->s_z80_sp = LOCENDIAN16(z80_get_reg(Z80_REG_SP));
274: *(uint16 *)ssp->s_z80_pc = LOCENDIAN16(z80_get_reg(Z80_REG_PC));
275: ssp->s_z80_i[0] = (z80_get_reg(Z80_REG_IR) >> 8) & 0xff;
276: ssp->s_z80_r[0] = z80_get_reg(Z80_REG_IR) & 0xff;
277: ssp->s_z80_iff1[0] = z80_get_reg(Z80_REG_IFF1);
278: ssp->s_z80_iff2[0] = z80_get_reg(Z80_REG_IFF2);
279: ssp->s_z80_im[0] = z80_get_reg(Z80_REG_IM);
280: #else
281: *(uint16 *)ssp->s_z80_af = LOCENDIAN16(cpuz80_z80.z80af);
282: *(uint16 *)ssp->s_z80_bc = LOCENDIAN16(cpuz80_z80.z80bc);
283: *(uint16 *)ssp->s_z80_de = LOCENDIAN16(cpuz80_z80.z80de);
284: *(uint16 *)ssp->s_z80_hl = LOCENDIAN16(cpuz80_z80.z80hl);
285: *(uint16 *)ssp->s_z80_afprime = LOCENDIAN16(cpuz80_z80.z80afprime);
286: *(uint16 *)ssp->s_z80_bcprime = LOCENDIAN16(cpuz80_z80.z80bcprime);
287: *(uint16 *)ssp->s_z80_deprime = LOCENDIAN16(cpuz80_z80.z80deprime);
288: *(uint16 *)ssp->s_z80_hlprime = LOCENDIAN16(cpuz80_z80.z80hlprime);
289: *(uint16 *)ssp->s_z80_ix = LOCENDIAN16(cpuz80_z80.z80ix);
290: *(uint16 *)ssp->s_z80_iy = LOCENDIAN16(cpuz80_z80.z80iy);
291: *(uint16 *)ssp->s_z80_sp = LOCENDIAN16(cpuz80_z80.z80sp);
292: *(uint16 *)ssp->s_z80_pc = LOCENDIAN16(cpuz80_z80.z80pc);
293: ssp->s_z80_i[0] = cpuz80_z80.z80i;
294: ssp->s_z80_r[0] = cpuz80_z80.z80r;
295: ssp->s_z80_iff1[0] = cpuz80_z80.z80inInterrupt;
296: ssp->s_z80_iff2[0] = cpuz80_z80.z80interruptState;
297: ssp->s_z80_im[0] = cpuz80_z80.z80interruptMode;
298: ssp->s_z80_halted[0] = cpuz80_z80.z80halted;
299: #endif
300: *(uint32 *)ssp->s_z80_bank = LOCENDIAN32(cpuz80_bank);
301: memcpy(ssp->s_vdp_regs, vdp_reg, sizeof(ssp->s_vdp_regs));
302: ssp->s_vdp_pal[0] = vdp_pal;
303: ssp->s_vdp_overseas[0] = vdp_overseas;
304: ssp->s_vdp_ctrlflag[0] = vdp_ctrlflag;
305: ssp->s_vdp_code[0] = vdp_code;
306: *(uint16 *)ssp->s_vdp_first = LOCENDIAN16(vdp_first);
307: *(uint16 *)ssp->s_vdp_second = LOCENDIAN16(vdp_second);
308: *(uint32 *)ssp->s_vdp_dmabytes = LOCENDIAN32(vdp_dmabytes);
309: *(uint16 *)ssp->s_vdp_address = LOCENDIAN16(vdp_address);
1.1.1.2 ! root 310: memcpy(ssp->s_fmregs1, sound_regs1, sizeof(ssp->s_fmregs1));
! 311: memcpy(ssp->s_fmregs2, sound_regs2, sizeof(ssp->s_fmregs2));
! 312: ssp->s_fmaddr1[0] = sound_address1;
! 313: ssp->s_fmaddr2[0] = sound_address2;
1.1 root 314: if (fwrite(ssp, sizeof(ss), 1, f) != 1) {
315: LOG_CRITICAL(("Error whilst writing GTR file '%s': %s", filename,
1.1.1.2 ! root 316: strerror(errno)));
1.1 root 317: return -1;
318: }
319: fclose(f);
320: return 0;
321: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.