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