Patches no longer seem to be needed
[debian-dgen.git] / save.cpp
blobc3391ae238df28f763ea438ce392884c4acbacfb
1 // DGen v1.10+
2 // Megadrive C++ module saving and loading
4 #include <stdio.h>
5 #include <string.h>
6 #include <stdlib.h>
7 #include <stdint.h>
8 #include "md.h"
9 #include "system.h"
11 void md::m68k_state_dump()
14 32 and 16-bit values must be stored LSB first even though M68K is
15 big-endian for compatibility with other emulators.
17 switch (cpu_emu) {
18 #ifdef WITH_MUSA
19 case CPU_EMU_MUSA:
20 if (md_set_musa(true))
21 md_set_musa_sync(false);
22 md_set_musa(false);
23 break;
24 #endif
25 #ifdef WITH_STAR
26 case CPU_EMU_STAR:
27 if (md_set_star(true))
28 md_set_star_sync(false);
29 md_set_star(false);
30 break;
31 #endif
32 #ifdef WITH_CYCLONE
33 case CPU_EMU_CYCLONE:
34 if (md_set_cyclone(true))
35 md_set_cyclone_sync(false);
36 md_set_cyclone(false);
37 break;
38 #endif
39 default:
40 break;
44 void md::m68k_state_restore()
46 /* 32 and 16-bit values are stored LSB first. */
47 switch (cpu_emu) {
48 #ifdef WITH_MUSA
49 case CPU_EMU_MUSA:
50 if (md_set_musa(true))
51 md_set_musa_sync(true);
52 md_set_musa(false);
53 break;
54 #endif
55 #ifdef WITH_STAR
56 case CPU_EMU_STAR:
57 if (md_set_star(true))
58 md_set_star_sync(true);
59 md_set_star(false);
60 break;
61 #endif
62 #ifdef WITH_CYCLONE
63 case CPU_EMU_CYCLONE:
64 if (md_set_cyclone(true))
65 md_set_cyclone_sync(true);
66 md_set_cyclone(false);
67 break;
68 #endif
69 default:
70 break;
74 void md::z80_state_dump()
76 /* 16-bit values must be stored LSB first. */
77 z80_state.irq_asserted = z80_st_irq;
78 z80_state.irq_vector = z80_irq_vector;
79 switch (z80_core) {
80 #ifdef WITH_CZ80
81 case Z80_CORE_CZ80:
82 if (md_set_cz80(true))
83 md_set_cz80_sync(false);
84 md_set_cz80(false);
85 break;
86 #endif
87 #ifdef WITH_MZ80
88 case Z80_CORE_MZ80:
89 if (md_set_mz80(true))
90 md_set_mz80_sync(false);
91 md_set_mz80(false);
92 break;
93 #endif
94 #ifdef WITH_DRZ80
95 case Z80_CORE_DRZ80:
96 if (md_set_drz80(true))
97 md_set_drz80_sync(false);
98 md_set_drz80(false);
99 break;
100 #endif
101 default:
102 break;
106 void md::z80_state_restore()
108 /* 16-bit values are stored LSB first. */
109 switch (z80_core) {
110 #ifdef WITH_CZ80
111 case Z80_CORE_CZ80:
112 if (md_set_cz80(true))
113 md_set_cz80_sync(true);
114 md_set_cz80(false);
115 break;
116 #endif
117 #ifdef WITH_MZ80
118 case Z80_CORE_MZ80:
119 if (md_set_mz80(true))
120 md_set_mz80_sync(true);
121 md_set_mz80(false);
122 break;
123 #endif
124 #ifdef WITH_DRZ80
125 case Z80_CORE_DRZ80:
126 if (md_set_drz80(true))
127 md_set_drz80_sync(true);
128 md_set_drz80(false);
129 break;
130 #endif
131 default:
132 break;
134 if (z80_state.irq_asserted)
135 z80_irq(z80_state.irq_vector);
136 else
137 z80_irq_clear();
141 gs0 genecyst save file INfo
143 GST\0 to start with
145 80-9f = d0-d7 almost certain
146 a0-bf = a0-a7 almost certain
147 c8 = pc fairly certain
148 d0 = sr fairly certain
151 112 Start of cram len 0x80
152 192 Start of vsram len 0x50
153 1e2-474 UNKNOWN sound info?
154 Start of z80 ram at 474 (they store 2000)
155 Start of RAM at 2478 almost certain (BYTE SWAPPED)
156 Start of VRAM at 12478
157 end of VRAM
161 2011-11-05 - Adapted from Gens' genecyst_save_file_format.txt:
163 Range Size Description
164 ----------- ----- -----------
165 00000-00002 3 "GST"
166 00003-00004 2 "\x40\xe0" (Gens and new DGen format)
167 00006-00007 2 "\xe0\x40" (old DGen format)
168 00040-00043 4 Last VDP control data written
169 00044-00044 1 Second write flag
170 00045-00045 1 DMA fill flag
171 00048-0004B 4 VDP write address
172 00050-00050 1 Version
173 00051-00051 1 Emulator ID
174 00052-00052 1 System ID
175 00060-0006F 16 PSG registers
176 00080-000D9 90 M68K registers
177 000FA-00111 24 VDP registers
178 00112-00191 128 Color RAM
179 00192-001E1 80 Vertical scroll RAM
180 001E2-001E2 1 YM2612 part I address register (DGen)
181 001E3-001E3 1 YM2612 part II address register (DGen)
182 001E4-003E3 512 YM2612 registers
183 00404-00437 52 Z80 registers
184 00438-0043F 8 Z80 state
185 00474-02473 8192 Z80 RAM
186 02478-12477 65536 68K RAM
187 12478-22477 65536 Video RAM
189 M68K registers (stored little-endian for compatibility)
190 --------------
191 00080-0009F : D0-D7
192 000A0-000BF : A0-A7
193 000C8 : PC
194 000D0 : SR
195 000D2 : USP
196 000D6 : SSP
198 Z80 registers (little-endian)
199 -------------
200 00404 : AF
201 00408 : BC
202 0040C : DE
203 00410 : HL
204 00414 : IX
205 00418 : IY
206 0041C : PC
207 00420 : SP
208 00424 : AF'
209 00428 : BC'
210 0042C : DE'
211 00430 : HL'
213 00434 : I
214 00435 : R (DGen)
215 00436 : x x x x x IFF1 x IFF2 (Gens v5)
216 00437 : IM (DGen)
218 Z80 State
219 ---------
220 00438 : Z80 RESET
221 00439 : Z80 BUSREQ
222 0043A : Unknown
223 0043B : Unknown
224 0043C : Z80 BANK (DWORD)
226 Gens and Kega ADD
227 -----------------
228 00040 : last VDP Control data written (DWORD)
229 00044 : second write flag (1 for second write)
230 00045 : DMA Fill flag (1 mean next data write will cause a DMA fill)
231 00048 : VDP write address (DWORD)
233 00050 : Version (Genecyst=0; Kega=5; Gens=5; DGen=5)
234 00051 : Emulator ID (Genecyst=0; Kega=0; Gens=1; DGen=9)
235 00052 : System ID (Genesis=0; SegaCD=1; 32X=2; SegaCD32X=3)
237 00060-0007F : PSG registers (DWORDs, little endian).
240 static void *swap16cpy(void *dest, const void *src, size_t n)
242 size_t i;
244 for (i = 0; (i != (n & ~1)); ++i)
245 ((uint8_t *)dest)[(i ^ 1)] = ((uint8_t *)src)[i];
246 ((uint8_t *)dest)[i] = ((uint8_t *)src)[i];
247 return dest;
250 int md::import_gst(FILE *hand)
252 uint8_t (*buf)[0x22478] =
253 (uint8_t (*)[sizeof(*buf)])malloc(sizeof(*buf));
254 uint8_t *p;
255 uint8_t *q;
256 size_t i;
257 uint32_t tmp;
259 if ((buf == NULL) ||
260 (fread((*buf), sizeof(*buf), 1, hand) != 1) ||
261 /* GST header */
262 ((memcmp((*buf), "GST\x0\x0\0\xe0\x40", 8) != 0) &&
263 (memcmp((*buf), "GST\x40\xe0", 5) != 0))) {
264 fprintf(stderr,
265 "%s: error: invalid save file header.\n",
266 __func__);
267 free(buf);
268 return -1;
270 p = &(*buf)[0x50];
271 if (p[2] != 0) {
272 fprintf(stderr,
273 "%s: error: this is not a Genesis/Mega Drive"
274 " save file.\n",
275 __func__);
276 free(buf);
277 return -1;
279 if (p[1] != 9) {
280 fprintf(stderr,
281 "%s: warning: save file was probably not generated by"
282 " DGen/SDL.\n",
283 __func__);
285 else if (p[0] != 5)
286 fprintf(stderr,
287 "%s: warning: unknown save file version.\n",
288 __func__);
289 /* Reset console first. */
290 reset();
291 /* FIXME: VDP stuff */
292 /* PSG registers (8x16-bit, 16 bytes) */
293 SN76496_restore(0, &(*buf)[0x60]);
294 /* M68K registers (19x32-bit, 1x16-bit, 90 bytes (padding: 12)) */
295 p = &(*buf)[0x80];
296 q = &(*buf)[0xa0];
297 for (i = 0; (i != 8); ++i, p += 4, q += 4) {
298 memcpy(&m68k_state.d[i], p, 4);
299 memcpy(&m68k_state.a[i], q, 4);
301 memcpy(&m68k_state.pc, &(*buf)[0xc8], 4);
302 memcpy(&m68k_state.sr, &(*buf)[0xd0], 2);
304 FIXME?
305 memcpy(&m68k_state.usp, &(*buf)[0xd2], 4);
306 memcpy(&m68k_state.ssp, &(*buf)[0xd6], 4);
308 m68k_state_restore();
309 /* VDP registers (24x8-bit VDP registers, not sizeof(vdp.reg)) */
310 memcpy(vdp.reg, &(*buf)[0xfa], 0x18);
311 memset(&vdp.reg[0x18], 0, (sizeof(vdp.reg) - 0x18));
312 /* CRAM (64x16-bit registers, 128 bytes), swapped */
313 swap16cpy(vdp.cram, &(*buf)[0x112], 0x80);
314 /* VSRAM (40x16-bit words, 80 bytes), swapped */
315 swap16cpy(vdp.vsram, &(*buf)[0x192], 0x50);
316 /* YM2612 registers */
317 p = &(*buf)[0x1e2];
318 fm_sel[0] = p[0];
319 fm_sel[1] = p[1];
320 p = &(*buf)[0x1e4];
321 YM2612_restore(0, p);
322 fm_reg[0][0x24] = p[0x24];
323 fm_reg[0][0x25] = p[0x25];
324 fm_reg[0][0x26] = p[0x26];
325 fm_reg[0][0x27] = p[0x27];
326 dac_data[0] = p[0x2a];
327 dac_enabled = (p[0x2b] >> 7);
328 memset(fm_ticker, 0, sizeof(fm_ticker));
329 /* Z80 registers (12x16-bit and 4x8-bit, 52 bytes (padding: 24)) */
330 p = &(*buf)[0x404];
331 for (i = 0; (i != 2); ++i, p = &(*buf)[0x424]) {
332 memcpy(&z80_state.alt[i].fa, &p[0x0], 2);
333 memcpy(&z80_state.alt[i].cb, &p[0x4], 2);
334 memcpy(&z80_state.alt[i].ed, &p[0x8], 2);
335 memcpy(&z80_state.alt[i].lh, &p[0xc], 2);
337 p = &(*buf)[0x414];
338 memcpy(&z80_state.ix, &p[0x0], 2);
339 memcpy(&z80_state.iy, &p[0x4], 2);
340 memcpy(&z80_state.pc, &p[0x8], 2);
341 memcpy(&z80_state.sp, &p[0xc], 2);
342 p = &(*buf)[0x434];
343 z80_state.i = p[0];
344 z80_state.r = p[1];
345 z80_state.iff = ((p[2] << 1) | p[2]); /* IFF2 = IFF1 */
346 z80_state.im = ((p[3] == 0) ? 1 : p[3]);
347 z80_state_restore();
348 /* Z80 state (8 bytes) */
349 p = &(*buf)[0x438];
350 z80_st_reset = !p[0]; /* BUS RESET state */
351 if (z80_st_reset) {
352 z80_reset();
353 fm_reset();
355 z80_st_busreq = (p[1] & 1); /* BUSREQ state */
356 memcpy(&tmp, &(*buf)[0x43c], 4);
357 z80_bank68k = le2h32(tmp);
358 /* Z80 RAM (8192 bytes) */
359 memcpy(z80ram, &(*buf)[0x474], 0x2000);
360 /* RAM (65536 bytes), swapped */
361 swap16cpy(ram, &(*buf)[0x2478], 0x10000);
362 /* VRAM (65536 bytes) */
363 memcpy(vdp.vram, &(*buf)[0x12478], 0x10000);
364 /* Mark everything as changed */
365 memset(vdp.dirt, 0xff, 0x35);
366 free(buf);
367 return 0;
370 int md::export_gst(FILE *hand)
372 uint8_t (*buf)[0x22478] =
373 (uint8_t (*)[sizeof(*buf)])calloc(1, sizeof(*buf));
374 uint8_t *p;
375 uint8_t *q;
376 size_t i;
377 uint32_t tmp;
379 if (buf == NULL)
380 return -1;
381 /* GST header */
382 memcpy((*buf), "GST\x40\xe0", 5);
383 /* FIXME: VDP stuff */
384 /* Version */
385 (*buf)[0x50] = 5;
386 /* Emulator ID */
387 (*buf)[0x51] = 9;
388 /* System ID */
389 (*buf)[0x52] = 0;
390 /* PSG registers (8x16-bit, 16 bytes) */
391 SN76496_dump(0, &(*buf)[0x60]);
392 /* M68K registers (19x32-bit, 1x16-bit, 90 bytes (padding: 12)) */
393 m68k_state_dump();
394 p = &(*buf)[0x80];
395 q = &(*buf)[0xa0];
396 for (i = 0; (i != 8); ++i, p += 4, q += 4) {
397 memcpy(p, &m68k_state.d[i], 4);
398 memcpy(q, &m68k_state.a[i], 4);
400 memcpy(&(*buf)[0xc8], &m68k_state.pc, 4);
401 memcpy(&(*buf)[0xd0], &m68k_state.sr, 2);
403 FIXME?
404 memcpy(&(*buf)[0xd2], &m68k_state.usp, 4);
405 memcpy(&(*buf)[0xd6], &m68k_state.ssp, 4);
407 /* VDP registers (24x8-bit VDP registers, not sizeof(vdp.reg)) */
408 memcpy(&(*buf)[0xfa], vdp.reg, 0x18);
409 /* CRAM (64x16-bit registers, 128 bytes), swapped */
410 swap16cpy(&(*buf)[0x112], vdp.cram, 0x80);
411 /* VSRAM (40x16-bit words, 80 bytes), swapped */
412 swap16cpy(&(*buf)[0x192], vdp.vsram, 0x50);
413 /* YM2612 registers */
414 p = &(*buf)[0x1e2];
415 p[0] = fm_sel[0];
416 p[1] = fm_sel[1];
417 p = &(*buf)[0x1e4];
418 YM2612_dump(0, p);
419 p[0x24] = fm_reg[0][0x24];
420 p[0x25] = fm_reg[0][0x25];
421 p[0x26] = fm_reg[0][0x26];
422 p[0x27] = fm_reg[0][0x27];
423 p[0x2a] = 0xff;
424 p[0x2b] = (dac_enabled << 7);
425 /* Z80 registers (12x16-bit and 4x8-bit, 52 bytes (padding: 24)) */
426 z80_state_dump();
427 p = &(*buf)[0x404];
428 for (i = 0; (i != 2); ++i, p = &(*buf)[0x424]) {
429 memcpy(&p[0x0], &z80_state.alt[i].fa, 2);
430 memcpy(&p[0x4], &z80_state.alt[i].cb, 2);
431 memcpy(&p[0x8], &z80_state.alt[i].ed, 2);
432 memcpy(&p[0xc], &z80_state.alt[i].lh, 2);
434 p = &(*buf)[0x414];
435 memcpy(&p[0x0], &z80_state.ix, 2);
436 memcpy(&p[0x4], &z80_state.iy, 2);
437 memcpy(&p[0x8], &z80_state.pc, 2);
438 memcpy(&p[0xc], &z80_state.sp, 2);
439 p = &(*buf)[0x434];
440 p[0] = z80_state.i;
441 p[1] = z80_state.r;
442 p[2] = ((z80_state.iff >> 1) | z80_state.iff);
443 p[3] = z80_state.im;
444 /* Z80 state (8 bytes) */
445 p = &(*buf)[0x438];
446 p[0] = !z80_st_reset;
447 p[1] = z80_st_busreq;
448 tmp = h2le32(z80_bank68k);
449 memcpy(&(*buf)[0x43c], &tmp, 4);
450 /* Z80 RAM (8192 bytes) */
451 memcpy(&(*buf)[0x474], z80ram, 0x2000);
452 /* RAM (65536 bytes), swapped */
453 swap16cpy(&(*buf)[0x2478], ram, 0x10000);
454 /* VRAM (65536 bytes) */
455 memcpy(&(*buf)[0x12478], vdp.vram, 0x10000);
456 /* Output */
457 i = fwrite((*buf), sizeof(*buf), 1, hand);
458 free(buf);
459 if (i != 1)
460 return -1;
461 return 0;