some more risky timing changes
[picodrive.git] / pico / state.c
CommitLineData
cff531af 1/*\r
2 * PicoDrive\r
3 * (C) notaz, 2010\r
4 *\r
5 * This work is licensed under the terms of MAME license.\r
6 * See COPYING file in the top-level directory.\r
7 */\r
b4db550e 8\r
9#include "pico_int.h"\r
325ee167 10#include <zlib.h>\r
b4db550e 11\r
12#include "../cpu/sh2/sh2.h"\r
13#include "sound/ym2612.h"\r
86b38dc4 14#include "state.h"\r
b4db550e 15\r
16// sn76496\r
17extern int *sn76496_regs;\r
18\r
b4db550e 19static arearw *areaRead;\r
20static arearw *areaWrite;\r
21static areaeof *areaEof;\r
22static areaseek *areaSeek;\r
23static areaclose *areaClose;\r
24\r
25carthw_state_chunk *carthw_chunks;\r
26void (*PicoStateProgressCB)(const char *str);\r
27void (*PicoLoadStateHook)(void);\r
28\r
29\r
30/* I/O functions */\r
31static size_t gzRead2(void *p, size_t _size, size_t _n, void *file)\r
32{\r
33 return gzread(file, p, _size * _n);\r
34}\r
35\r
36static size_t gzWrite2(void *p, size_t _size, size_t _n, void *file)\r
37{\r
38 return gzwrite(file, p, _size * _n);\r
39}\r
40\r
41static void set_cbs(int gz)\r
42{\r
43 if (gz) {\r
44 areaRead = gzRead2;\r
45 areaWrite = gzWrite2;\r
46 areaEof = (areaeof *) gzeof;\r
47 areaSeek = (areaseek *) gzseek;\r
48 areaClose = (areaclose *) gzclose;\r
49 } else {\r
50 areaRead = (arearw *) fread;\r
51 areaWrite = (arearw *) fwrite;\r
52 areaEof = (areaeof *) feof;\r
53 areaSeek = (areaseek *) fseek;\r
54 areaClose = (areaclose *) fclose;\r
55 }\r
56}\r
57\r
58static void *open_save_file(const char *fname, int is_save)\r
59{\r
60 int len = strlen(fname);\r
61 void *afile = NULL;\r
62\r
63 if (len > 3 && strcmp(fname + len - 3, ".gz") == 0)\r
64 {\r
65 if ( (afile = gzopen(fname, is_save ? "wb" : "rb")) ) {\r
66 set_cbs(1);\r
67 if (is_save)\r
68 gzsetparams(afile, 9, Z_DEFAULT_STRATEGY);\r
69 }\r
70 }\r
71 else\r
72 {\r
73 if ( (afile = fopen(fname, is_save ? "wb" : "rb")) ) {\r
74 set_cbs(0);\r
75 }\r
76 }\r
77\r
78 return afile;\r
79}\r
80\r
81// legacy savestate loading\r
82#define SCANP(f, x) areaRead(&Pico.x, sizeof(Pico.x), 1, f)\r
83\r
84static int state_load_legacy(void *file)\r
85{\r
86 unsigned char head[32];\r
87 unsigned char cpu[0x60];\r
88 unsigned char cpu_z80[Z80_STATE_SIZE];\r
89 void *ym2612_regs;\r
90 int ok;\r
91\r
92 memset(&cpu,0,sizeof(cpu));\r
93 memset(&cpu_z80,0,sizeof(cpu_z80));\r
94\r
95 memset(head, 0, sizeof(head));\r
96 areaRead(head, sizeof(head), 1, file);\r
97 if (strcmp((char *)head, "Pico") != 0)\r
98 return -1;\r
99\r
100 elprintf(EL_STATUS, "legacy savestate");\r
101\r
102 // Scan all the memory areas:\r
103 SCANP(file, ram);\r
104 SCANP(file, vram);\r
105 SCANP(file, zram);\r
106 SCANP(file, cram);\r
107 SCANP(file, vsram);\r
108\r
109 // Pack, scan and unpack the cpu data:\r
110 areaRead(cpu, sizeof(cpu), 1, file);\r
111 SekUnpackCpu(cpu, 0);\r
112\r
113 SCANP(file, m);\r
114 SCANP(file, video);\r
115\r
116 ok = areaRead(cpu_z80, sizeof(cpu_z80), 1, file) == sizeof(cpu_z80);\r
117 // do not unpack if we fail to load z80 state\r
118 if (!ok) z80_reset();\r
119 else z80_unpack(cpu_z80);\r
120\r
121 ym2612_regs = YM2612GetRegs();\r
122 areaRead(sn76496_regs, 28*4, 1, file);\r
123 areaRead(ym2612_regs, 0x200+4, 1, file);\r
124 ym2612_unpack_state();\r
125\r
126 return 0;\r
127}\r
128\r
129// ---------------------------------------------------------------------------\r
130\r
131typedef enum {\r
132 CHUNK_M68K = 1,\r
133 CHUNK_RAM,\r
134 CHUNK_VRAM,\r
135 CHUNK_ZRAM,\r
136 CHUNK_CRAM, // 5\r
137 CHUNK_VSRAM,\r
138 CHUNK_MISC,\r
139 CHUNK_VIDEO,\r
140 CHUNK_Z80,\r
141 CHUNK_PSG, // 10\r
142 CHUNK_FM,\r
143 // CD stuff\r
144 CHUNK_S68K,\r
145 CHUNK_PRG_RAM,\r
146 CHUNK_WORD_RAM,\r
147 CHUNK_PCM_RAM, // 15\r
148 CHUNK_BRAM,\r
149 CHUNK_GA_REGS,\r
150 CHUNK_PCM,\r
3f23709e 151 CHUNK_CDC, // old\r
274fcc35 152 CHUNK_CDD, // 20 old\r
153 CHUNK_SCD, // old\r
3f23709e 154 CHUNK_RC, // old\r
b4db550e 155 CHUNK_MISC_CD,\r
156 //\r
157 CHUNK_IOPORTS, // versions < 1.70 did not save that..\r
158 CHUNK_SMS, // 25\r
159 // 32x\r
160 CHUNK_MSH2,\r
161 CHUNK_MSH2_DATA,\r
162 CHUNK_MSH2_PERI,\r
163 CHUNK_SSH2,\r
164 CHUNK_SSH2_DATA, // 30\r
165 CHUNK_SSH2_PERI,\r
166 CHUNK_32XSYS,\r
167 CHUNK_M68K_BIOS,\r
168 CHUNK_MSH2_BIOS,\r
169 CHUNK_SSH2_BIOS, // 35\r
170 CHUNK_SDRAM,\r
171 CHUNK_DRAM,\r
172 CHUNK_32XPAL,\r
6a98f03e 173 CHUNK_32X_EVT,\r
27e26273 174 CHUNK_32X_FIRST = CHUNK_MSH2,\r
175 CHUNK_32X_LAST = CHUNK_32X_EVT,\r
ae214f1c 176 // add new stuff here\r
177 CHUNK_CD_EVT = 50,\r
a93a80de 178 CHUNK_CD_GFX,\r
3f23709e 179 CHUNK_CD_CDC,\r
274fcc35 180 CHUNK_CD_CDD,\r
b4db550e 181 //\r
182 CHUNK_DEFAULT_COUNT,\r
ae214f1c 183 CHUNK_CARTHW_ = CHUNK_CARTHW, // 64 (defined in PicoInt)\r
b4db550e 184} chunk_name_e;\r
185\r
cfae1ae1 186static const char * const chunk_names[CHUNK_DEFAULT_COUNT] = {\r
b4db550e 187 "INVALID!",\r
188 "M68K state",\r
189 "RAM",\r
190 "VRAM",\r
191 "ZRAM",\r
192 "CRAM", // 5\r
193 "VSRAM",\r
194 "emu state",\r
195 "VIDEO",\r
196 "Z80 state",\r
197 "PSG", // 10\r
198 "FM",\r
199 // CD stuff\r
200 "S68K state",\r
201 "PRG_RAM",\r
202 "WORD_RAM",\r
203 "PCM_RAM", // 15\r
204 "BRAM",\r
205 "GATE ARRAY regs",\r
206 "PCM state",\r
207 "CDC",\r
208 "CDD", // 20\r
209 "SCD",\r
210 "GFX chip",\r
211 "MCD state",\r
212 //\r
213 "IO",\r
214 "SMS state", // 25\r
215 // 32x\r
216 "MSH2",\r
217 "MSH2 data",\r
218 "MSH2 peri",\r
219 "SSH2",\r
220 "SSH2 data", // 30\r
221 "SSH2 peri",\r
222 "32X system regs",\r
223 "M68K BIOS",\r
224 "MSH2 BIOS",\r
225 "SSH2 BIOS", // 35\r
226 "SDRAM",\r
227 "DRAM",\r
228 "PAL",\r
6a98f03e 229 "events",\r
b4db550e 230};\r
231\r
232static int write_chunk(chunk_name_e name, int len, void *data, void *file)\r
233{\r
234 size_t bwritten = 0;\r
235 bwritten += areaWrite(&name, 1, 1, file);\r
236 bwritten += areaWrite(&len, 1, 4, file);\r
237 bwritten += areaWrite(data, 1, len, file);\r
238\r
239 return (bwritten == len + 4 + 1);\r
240}\r
241\r
3f23709e 242#define CHUNK_LIMIT_W 18772 // sizeof(cdc)\r
243\r
b4db550e 244#define CHECKED_WRITE(name,len,data) { \\r
cfae1ae1 245 if (PicoStateProgressCB && name < CHUNK_DEFAULT_COUNT && chunk_names[name]) { \\r
b4db550e 246 strncpy(sbuff + 9, chunk_names[name], sizeof(sbuff) - 9); \\r
247 PicoStateProgressCB(sbuff); \\r
248 } \\r
3f23709e 249 if (data == buf2 && len > CHUNK_LIMIT_W) \\r
250 goto out; \\r
251 if (!write_chunk(name, len, data, file)) \\r
252 goto out; \\r
b4db550e 253}\r
254\r
255#define CHECKED_WRITE_BUFF(name,buff) { \\r
cfae1ae1 256 if (PicoStateProgressCB && name < CHUNK_DEFAULT_COUNT && chunk_names[name]) { \\r
b4db550e 257 strncpy(sbuff + 9, chunk_names[name], sizeof(sbuff) - 9); \\r
258 PicoStateProgressCB(sbuff); \\r
259 } \\r
3f23709e 260 if (!write_chunk(name, sizeof(buff), &buff, file)) \\r
261 goto out; \\r
b4db550e 262}\r
263\r
264static int state_save(void *file)\r
265{\r
266 char sbuff[32] = "Saving.. ";\r
267 unsigned char buff[0x60], buff_z80[Z80_STATE_SIZE];\r
268 void *ym2612_regs = YM2612GetRegs();\r
3f23709e 269 void *buf2 = NULL;\r
270 int ver = 0x0191; // not really used..\r
271 int retval = -1;\r
a93a80de 272 int len;\r
b4db550e 273\r
274 areaWrite("PicoSEXT", 1, 8, file);\r
275 areaWrite(&ver, 1, 4, file);\r
276\r
277 if (!(PicoAHW & PAHW_SMS)) {\r
278 memset(buff, 0, sizeof(buff));\r
279 SekPackCpu(buff, 0);\r
280 CHECKED_WRITE_BUFF(CHUNK_M68K, buff);\r
281 CHECKED_WRITE_BUFF(CHUNK_RAM, Pico.ram);\r
282 CHECKED_WRITE_BUFF(CHUNK_VSRAM, Pico.vsram);\r
283 CHECKED_WRITE_BUFF(CHUNK_IOPORTS, Pico.ioports);\r
284 ym2612_pack_state();\r
285 CHECKED_WRITE(CHUNK_FM, 0x200+4, ym2612_regs);\r
286 }\r
287 else {\r
288 CHECKED_WRITE_BUFF(CHUNK_SMS, Pico.ms);\r
289 }\r
290\r
291 CHECKED_WRITE_BUFF(CHUNK_VRAM, Pico.vram);\r
292 CHECKED_WRITE_BUFF(CHUNK_ZRAM, Pico.zram);\r
293 CHECKED_WRITE_BUFF(CHUNK_CRAM, Pico.cram);\r
294 CHECKED_WRITE_BUFF(CHUNK_MISC, Pico.m);\r
295 CHECKED_WRITE_BUFF(CHUNK_VIDEO, Pico.video);\r
296\r
297 z80_pack(buff_z80);\r
298 CHECKED_WRITE_BUFF(CHUNK_Z80, buff_z80);\r
299 CHECKED_WRITE(CHUNK_PSG, 28*4, sn76496_regs);\r
300\r
301 if (PicoAHW & PAHW_MCD)\r
302 {\r
3f23709e 303 buf2 = malloc(CHUNK_LIMIT_W);\r
304 if (buf2 == NULL)\r
305 return -1;\r
306\r
b4db550e 307 memset(buff, 0, sizeof(buff));\r
308 SekPackCpu(buff, 1);\r
309 if (Pico_mcd->s68k_regs[3] & 4) // 1M mode?\r
310 wram_1M_to_2M(Pico_mcd->word_ram2M);\r
895d1512 311 memcpy(&Pico_mcd->m.hint_vector, Pico_mcd->bios + 0x72,\r
312 sizeof(Pico_mcd->m.hint_vector));\r
b4db550e 313\r
314 CHECKED_WRITE_BUFF(CHUNK_S68K, buff);\r
315 CHECKED_WRITE_BUFF(CHUNK_PRG_RAM, Pico_mcd->prg_ram);\r
316 CHECKED_WRITE_BUFF(CHUNK_WORD_RAM, Pico_mcd->word_ram2M); // in 2M format\r
317 CHECKED_WRITE_BUFF(CHUNK_PCM_RAM, Pico_mcd->pcm_ram);\r
318 CHECKED_WRITE_BUFF(CHUNK_BRAM, Pico_mcd->bram);\r
319 CHECKED_WRITE_BUFF(CHUNK_GA_REGS, Pico_mcd->s68k_regs); // GA regs, not CPU regs\r
320 CHECKED_WRITE_BUFF(CHUNK_PCM, Pico_mcd->pcm);\r
b4db550e 321 CHECKED_WRITE_BUFF(CHUNK_MISC_CD, Pico_mcd->m);\r
ae214f1c 322 memset(buff, 0, 0x40);\r
323 memcpy(buff, pcd_event_times, sizeof(pcd_event_times));\r
324 CHECKED_WRITE(CHUNK_CD_EVT, 0x40, buff);\r
3f23709e 325\r
326 len = gfx_context_save(buf2);\r
327 CHECKED_WRITE(CHUNK_CD_GFX, len, buf2);\r
328 len = cdc_context_save(buf2);\r
329 CHECKED_WRITE(CHUNK_CD_CDC, len, buf2);\r
274fcc35 330 len = cdd_context_save(buf2);\r
331 CHECKED_WRITE(CHUNK_CD_CDD, len, buf2);\r
b4db550e 332\r
333 if (Pico_mcd->s68k_regs[3] & 4) // convert back\r
334 wram_2M_to_1M(Pico_mcd->word_ram2M);\r
335 }\r
336\r
f3a57b2d 337#ifndef NO_32X\r
b4db550e 338 if (PicoAHW & PAHW_32X)\r
339 {\r
340 unsigned char cpubuff[SH2_STATE_SIZE];\r
341\r
342 memset(cpubuff, 0, sizeof(cpubuff));\r
343\r
344 sh2_pack(&sh2s[0], cpubuff);\r
345 CHECKED_WRITE_BUFF(CHUNK_MSH2, cpubuff);\r
f81107f5 346 CHECKED_WRITE_BUFF(CHUNK_MSH2_DATA, sh2s[0].data_array);\r
347 CHECKED_WRITE_BUFF(CHUNK_MSH2_PERI, sh2s[0].peri_regs);\r
b4db550e 348\r
349 sh2_pack(&sh2s[1], cpubuff);\r
350 CHECKED_WRITE_BUFF(CHUNK_SSH2, cpubuff);\r
f81107f5 351 CHECKED_WRITE_BUFF(CHUNK_SSH2_DATA, sh2s[1].data_array);\r
352 CHECKED_WRITE_BUFF(CHUNK_SSH2_PERI, sh2s[1].peri_regs);\r
b4db550e 353\r
354 CHECKED_WRITE_BUFF(CHUNK_32XSYS, Pico32x);\r
355 CHECKED_WRITE_BUFF(CHUNK_M68K_BIOS, Pico32xMem->m68k_rom);\r
356 CHECKED_WRITE_BUFF(CHUNK_MSH2_BIOS, Pico32xMem->sh2_rom_m);\r
357 CHECKED_WRITE_BUFF(CHUNK_SSH2_BIOS, Pico32xMem->sh2_rom_s);\r
358 CHECKED_WRITE_BUFF(CHUNK_SDRAM, Pico32xMem->sdram);\r
359 CHECKED_WRITE_BUFF(CHUNK_DRAM, Pico32xMem->dram);\r
360 CHECKED_WRITE_BUFF(CHUNK_32XPAL, Pico32xMem->pal);\r
ed4402a7 361\r
6a98f03e 362 memset(buff, 0, 0x40);\r
ae214f1c 363 memcpy(buff, p32x_event_times, sizeof(p32x_event_times));\r
6a98f03e 364 CHECKED_WRITE(CHUNK_32X_EVT, 0x40, buff);\r
b4db550e 365 }\r
f3a57b2d 366#endif\r
b4db550e 367\r
368 if (carthw_chunks != NULL)\r
369 {\r
370 carthw_state_chunk *chwc;\r
371 if (PicoStateProgressCB)\r
372 PicoStateProgressCB("Saving.. cart hw state");\r
373 for (chwc = carthw_chunks; chwc->ptr != NULL; chwc++)\r
374 CHECKED_WRITE(chwc->chunk, chwc->size, chwc->ptr);\r
375 }\r
376\r
3f23709e 377 retval = 0;\r
378\r
379out:\r
380 if (buf2 != NULL)\r
381 free(buf2);\r
382 return retval;\r
b4db550e 383}\r
384\r
385static int g_read_offs = 0;\r
386\r
387#define R_ERROR_RETURN(error) \\r
388{ \\r
389 elprintf(EL_STATUS, "load_state @ %x: " error, g_read_offs); \\r
3f23709e 390 goto out; \\r
b4db550e 391}\r
392\r
393// when is eof really set?\r
394#define CHECKED_READ(len,data) { \\r
395 if (areaRead(data, 1, len, file) != len) { \\r
396 if (len == 1 && areaEof(file)) goto readend; \\r
397 R_ERROR_RETURN("areaRead: premature EOF\n"); \\r
b4db550e 398 } \\r
399 g_read_offs += len; \\r
400}\r
401\r
402#define CHECKED_READ2(len2,data) { \\r
403 if (len2 != len) { \\r
404 elprintf(EL_STATUS, "unexpected len %i, wanted %i (%s)", len, len2, #len2); \\r
405 if (len > len2) R_ERROR_RETURN("failed."); \\r
406 /* else read anyway and hope for the best.. */ \\r
407 } \\r
408 CHECKED_READ(len, data); \\r
409}\r
410\r
411#define CHECKED_READ_BUFF(buff) CHECKED_READ2(sizeof(buff), &buff);\r
412\r
3f23709e 413#define CHUNK_LIMIT_R 0x10960 // sizeof(old_cdc)\r
414\r
415#define CHECKED_READ_LIM(data) { \\r
416 if (len > CHUNK_LIMIT_R) \\r
417 R_ERROR_RETURN("chunk size over limit."); \\r
418 CHECKED_READ(len, data); \\r
419}\r
420\r
b4db550e 421static int state_load(void *file)\r
422{\r
423 unsigned char buff_m68k[0x60], buff_s68k[0x60];\r
424 unsigned char buff_z80[Z80_STATE_SIZE];\r
425 unsigned char buff_sh2[SH2_STATE_SIZE];\r
3f23709e 426 unsigned char *buf = NULL;\r
b4db550e 427 unsigned char chunk;\r
428 void *ym2612_regs;\r
3f23709e 429 int len_check;\r
430 int retval = -1;\r
b4db550e 431 char header[8];\r
432 int ver, len;\r
433\r
03065bb6 434 memset(buff_m68k, 0, sizeof(buff_m68k));\r
435 memset(buff_s68k, 0, sizeof(buff_s68k));\r
436 memset(buff_z80, 0, sizeof(buff_z80));\r
437\r
3f23709e 438 buf = malloc(CHUNK_LIMIT_R);\r
439 if (buf == NULL)\r
440 return -1;\r
441\r
b4db550e 442 g_read_offs = 0;\r
443 CHECKED_READ(8, header);\r
444 if (strncmp(header, "PicoSMCD", 8) && strncmp(header, "PicoSEXT", 8))\r
445 R_ERROR_RETURN("bad header");\r
446 CHECKED_READ(4, &ver);\r
447\r
ae214f1c 448 memset(pcd_event_times, 0, sizeof(pcd_event_times));\r
449 memset(p32x_event_times, 0, sizeof(p32x_event_times));\r
450\r
b4db550e 451 while (!areaEof(file))\r
452 {\r
3f23709e 453 len_check = 0;\r
b4db550e 454 CHECKED_READ(1, &chunk);\r
455 CHECKED_READ(4, &len);\r
456 if (len < 0 || len > 1024*512) R_ERROR_RETURN("bad length");\r
457 if (CHUNK_S68K <= chunk && chunk <= CHUNK_MISC_CD && !(PicoAHW & PAHW_MCD))\r
458 R_ERROR_RETURN("cd chunk in non CD state?");\r
27e26273 459 if (CHUNK_32X_FIRST <= chunk && chunk <= CHUNK_32X_LAST && !(PicoAHW & PAHW_32X))\r
460 Pico32xStartup();\r
b4db550e 461\r
462 switch (chunk)\r
463 {\r
464 case CHUNK_M68K:\r
465 CHECKED_READ_BUFF(buff_m68k);\r
466 break;\r
467\r
468 case CHUNK_Z80:\r
469 CHECKED_READ_BUFF(buff_z80);\r
b4db550e 470 break;\r
471\r
472 case CHUNK_RAM: CHECKED_READ_BUFF(Pico.ram); break;\r
473 case CHUNK_VRAM: CHECKED_READ_BUFF(Pico.vram); break;\r
474 case CHUNK_ZRAM: CHECKED_READ_BUFF(Pico.zram); break;\r
475 case CHUNK_CRAM: CHECKED_READ_BUFF(Pico.cram); break;\r
476 case CHUNK_VSRAM: CHECKED_READ_BUFF(Pico.vsram); break;\r
477 case CHUNK_MISC: CHECKED_READ_BUFF(Pico.m); break;\r
478 case CHUNK_VIDEO: CHECKED_READ_BUFF(Pico.video); break;\r
479 case CHUNK_IOPORTS: CHECKED_READ_BUFF(Pico.ioports); break;\r
480 case CHUNK_PSG: CHECKED_READ2(28*4, sn76496_regs); break;\r
481 case CHUNK_FM:\r
482 ym2612_regs = YM2612GetRegs();\r
483 CHECKED_READ2(0x200+4, ym2612_regs);\r
484 ym2612_unpack_state();\r
485 break;\r
486\r
487 case CHUNK_SMS:\r
488 CHECKED_READ_BUFF(Pico.ms);\r
489 break;\r
490\r
491 // cd stuff\r
492 case CHUNK_S68K:\r
493 CHECKED_READ_BUFF(buff_s68k);\r
494 break;\r
495\r
496 case CHUNK_PRG_RAM: CHECKED_READ_BUFF(Pico_mcd->prg_ram); break;\r
497 case CHUNK_WORD_RAM: CHECKED_READ_BUFF(Pico_mcd->word_ram2M); break;\r
498 case CHUNK_PCM_RAM: CHECKED_READ_BUFF(Pico_mcd->pcm_ram); break;\r
499 case CHUNK_BRAM: CHECKED_READ_BUFF(Pico_mcd->bram); break;\r
500 case CHUNK_GA_REGS: CHECKED_READ_BUFF(Pico_mcd->s68k_regs); break;\r
501 case CHUNK_PCM: CHECKED_READ_BUFF(Pico_mcd->pcm); break;\r
b4db550e 502 case CHUNK_MISC_CD: CHECKED_READ_BUFF(Pico_mcd->m); break;\r
503\r
ae214f1c 504 case CHUNK_CD_EVT:\r
3f23709e 505 CHECKED_READ2(0x40, buf);\r
506 memcpy(pcd_event_times, buf, sizeof(pcd_event_times));\r
ae214f1c 507 break;\r
508\r
a93a80de 509 case CHUNK_CD_GFX:\r
3f23709e 510 CHECKED_READ_LIM(buf);\r
511 len_check = gfx_context_load(buf);\r
512 break;\r
513\r
514 case CHUNK_CD_CDC:\r
515 CHECKED_READ_LIM(buf);\r
516 len_check = cdc_context_load(buf);\r
517 break;\r
518\r
274fcc35 519 case CHUNK_CD_CDD:\r
520 CHECKED_READ_LIM(buf);\r
521 len_check = cdd_context_load(buf);\r
522 break;\r
523\r
3f23709e 524 // old, to be removed:\r
525 case CHUNK_CDC:\r
526 CHECKED_READ_LIM(buf);\r
527 cdc_context_load_old(buf);\r
a93a80de 528 break;\r
529\r
274fcc35 530 case CHUNK_SCD:\r
531 CHECKED_READ_LIM(buf);\r
532 cdd_context_load_old(buf);\r
533 break;\r
534\r
b4db550e 535 // 32x stuff\r
f3a57b2d 536#ifndef NO_32X\r
b4db550e 537 case CHUNK_MSH2:\r
538 CHECKED_READ_BUFF(buff_sh2);\r
539 sh2_unpack(&sh2s[0], buff_sh2);\r
540 break;\r
541\r
542 case CHUNK_SSH2:\r
543 CHECKED_READ_BUFF(buff_sh2);\r
544 sh2_unpack(&sh2s[1], buff_sh2);\r
545 break;\r
546\r
f81107f5 547 case CHUNK_MSH2_DATA: CHECKED_READ_BUFF(sh2s[0].data_array); break;\r
548 case CHUNK_MSH2_PERI: CHECKED_READ_BUFF(sh2s[0].peri_regs); break;\r
549 case CHUNK_SSH2_DATA: CHECKED_READ_BUFF(sh2s[1].data_array); break;\r
550 case CHUNK_SSH2_PERI: CHECKED_READ_BUFF(sh2s[1].peri_regs); break;\r
b4db550e 551 case CHUNK_32XSYS: CHECKED_READ_BUFF(Pico32x); break;\r
552 case CHUNK_M68K_BIOS: CHECKED_READ_BUFF(Pico32xMem->m68k_rom); break;\r
553 case CHUNK_MSH2_BIOS: CHECKED_READ_BUFF(Pico32xMem->sh2_rom_m); break;\r
554 case CHUNK_SSH2_BIOS: CHECKED_READ_BUFF(Pico32xMem->sh2_rom_s); break;\r
555 case CHUNK_SDRAM: CHECKED_READ_BUFF(Pico32xMem->sdram); break;\r
556 case CHUNK_DRAM: CHECKED_READ_BUFF(Pico32xMem->dram); break;\r
557 case CHUNK_32XPAL: CHECKED_READ_BUFF(Pico32xMem->pal); break;\r
6a98f03e 558\r
559 case CHUNK_32X_EVT:\r
3f23709e 560 CHECKED_READ2(0x40, buf);\r
561 memcpy(p32x_event_times, buf, sizeof(p32x_event_times));\r
6a98f03e 562 break;\r
f3a57b2d 563#endif\r
b4db550e 564 default:\r
565 if (carthw_chunks != NULL)\r
566 {\r
567 carthw_state_chunk *chwc;\r
568 for (chwc = carthw_chunks; chwc->ptr != NULL; chwc++) {\r
569 if (chwc->chunk == chunk) {\r
570 CHECKED_READ2(chwc->size, chwc->ptr);\r
571 goto breakswitch;\r
572 }\r
573 }\r
574 }\r
575 elprintf(EL_STATUS, "load_state: skipping unknown chunk %i of size %i", chunk, len);\r
576 areaSeek(file, len, SEEK_CUR);\r
577 break;\r
578 }\r
3f23709e 579breakswitch:\r
580 if (len_check != 0 && len_check != len)\r
581 elprintf(EL_STATUS, "load_state: chunk %d has bad len %d/%d",\r
582 len, len_check);\r
b4db550e 583 }\r
584\r
585readend:\r
586 if (PicoAHW & PAHW_SMS)\r
587 PicoStateLoadedMS();\r
588\r
27e26273 589 if (PicoAHW & PAHW_32X)\r
590 Pico32xStateLoaded(1);\r
591\r
e23f4494 592 if (PicoLoadStateHook != NULL)\r
593 PicoLoadStateHook();\r
594\r
03065bb6 595 // must unpack 68k and z80 after banks are set up\r
b4db550e 596 if (!(PicoAHW & PAHW_SMS))\r
597 SekUnpackCpu(buff_m68k, 0);\r
27e26273 598 if (PicoAHW & PAHW_MCD)\r
599 SekUnpackCpu(buff_s68k, 1);\r
b4db550e 600\r
03065bb6 601 z80_unpack(buff_z80);\r
602\r
27e26273 603 // due to dep from 68k cycles..\r
ae214f1c 604 SekCycleAim = SekCycleCnt;\r
b4db550e 605 if (PicoAHW & PAHW_32X)\r
27e26273 606 Pico32xStateLoaded(0);\r
ae214f1c 607 if (PicoAHW & PAHW_MCD)\r
608 {\r
609 SekCycleAimS68k = SekCycleCntS68k;\r
610 pcd_state_loaded();\r
ae214f1c 611 }\r
b4db550e 612\r
3f23709e 613 retval = 0;\r
614\r
615out:\r
616 free(buf);\r
617 return retval;\r
b4db550e 618}\r
619\r
620static int state_load_gfx(void *file)\r
621{\r
622 int ver, len, found = 0, to_find = 4;\r
623 char buff[8];\r
624\r
625 if (PicoAHW & PAHW_32X)\r
626 to_find += 2;\r
627\r
628 g_read_offs = 0;\r
629 CHECKED_READ(8, buff);\r
630 if (strncmp((char *)buff, "PicoSMCD", 8) && strncmp((char *)buff, "PicoSEXT", 8))\r
631 R_ERROR_RETURN("bad header");\r
632 CHECKED_READ(4, &ver);\r
633\r
634 while (!areaEof(file) && found < to_find)\r
635 {\r
636 CHECKED_READ(1, buff);\r
637 CHECKED_READ(4, &len);\r
638 if (len < 0 || len > 1024*512) R_ERROR_RETURN("bad length");\r
639 if (buff[0] > CHUNK_FM && buff[0] <= CHUNK_MISC_CD && !(PicoAHW & PAHW_MCD))\r
640 R_ERROR_RETURN("cd chunk in non CD state?");\r
641\r
642 switch (buff[0])\r
643 {\r
644 case CHUNK_VRAM: CHECKED_READ_BUFF(Pico.vram); found++; break;\r
645 case CHUNK_CRAM: CHECKED_READ_BUFF(Pico.cram); found++; break;\r
646 case CHUNK_VSRAM: CHECKED_READ_BUFF(Pico.vsram); found++; break;\r
647 case CHUNK_VIDEO: CHECKED_READ_BUFF(Pico.video); found++; break;\r
648\r
f3a57b2d 649#ifndef NO_32X\r
b4db550e 650 case CHUNK_DRAM:\r
651 if (Pico32xMem != NULL)\r
652 CHECKED_READ_BUFF(Pico32xMem->dram);\r
653 break;\r
654\r
655 case CHUNK_32XPAL:\r
656 if (Pico32xMem != NULL)\r
657 CHECKED_READ_BUFF(Pico32xMem->pal);\r
658 Pico32x.dirty_pal = 1;\r
659 break;\r
660\r
661 case CHUNK_32XSYS:\r
662 CHECKED_READ_BUFF(Pico32x);\r
663 break;\r
f3a57b2d 664#endif\r
b4db550e 665 default:\r
666 areaSeek(file, len, SEEK_CUR);\r
667 break;\r
668 }\r
669 }\r
670\r
3f23709e 671out:\r
b4db550e 672readend:\r
673 return 0;\r
674}\r
675\r
86b38dc4 676static int pico_state_internal(void *afile, int is_save)\r
b4db550e 677{\r
b4db550e 678 int ret;\r
679\r
b4db550e 680 if (is_save)\r
681 ret = state_save(afile);\r
682 else {\r
683 ret = state_load(afile);\r
684 if (ret != 0) {\r
685 areaSeek(afile, 0, SEEK_SET);\r
686 ret = state_load_legacy(afile);\r
687 }\r
688\r
b4db550e 689 Pico.m.dirtyPal = 1;\r
e42a47e2 690 Pico.video.status &= ~(SR_VB | SR_F);\r
b4db550e 691 }\r
692\r
86b38dc4 693 return ret;\r
694}\r
695\r
696int PicoState(const char *fname, int is_save)\r
697{\r
698 void *afile = NULL;\r
699 int ret;\r
700\r
701 afile = open_save_file(fname, is_save);\r
702 if (afile == NULL)\r
703 return -1;\r
704\r
705 ret = pico_state_internal(afile, is_save);\r
b4db550e 706 areaClose(afile);\r
707 return ret;\r
708}\r
709\r
86b38dc4 710int PicoStateFP(void *afile, int is_save,\r
711 arearw *read, arearw *write, areaeof *eof, areaseek *seek)\r
712{\r
713 areaRead = read;\r
714 areaWrite = write;\r
715 areaEof = eof;\r
716 areaSeek = seek;\r
717 areaClose = NULL;\r
718\r
719 return pico_state_internal(afile, is_save);\r
720}\r
721\r
b4db550e 722int PicoStateLoadGfx(const char *fname)\r
723{\r
724 void *afile;\r
725 int ret;\r
726\r
727 afile = open_save_file(fname, 0);\r
728 if (afile == NULL)\r
729 return -1;\r
730\r
731 ret = state_load_gfx(afile);\r
732 if (ret != 0) {\r
733 // assume legacy\r
734 areaSeek(afile, 0x10020, SEEK_SET); // skip header and RAM\r
735 areaRead(Pico.vram, 1, sizeof(Pico.vram), afile);\r
736 areaSeek(afile, 0x2000, SEEK_CUR);\r
737 areaRead(Pico.cram, 1, sizeof(Pico.cram), afile);\r
738 areaRead(Pico.vsram, 1, sizeof(Pico.vsram), afile);\r
739 areaSeek(afile, 0x221a0, SEEK_SET);\r
740 areaRead(&Pico.video, 1, sizeof(Pico.video), afile);\r
741 }\r
742 areaClose(afile);\r
743 return 0;\r
744}\r
745\r
746// tmp state\r
747struct PicoTmp\r
748{\r
749 unsigned short vram[0x8000];\r
750 unsigned short cram[0x40];\r
751 unsigned short vsram[0x40];\r
752\r
753 //struct PicoMisc m;\r
754 struct PicoVideo video;\r
755\r
756 struct {\r
757 struct Pico32x p32x;\r
758 unsigned short dram[2][0x20000/2];\r
759 unsigned short pal[0x100];\r
760 } t32x;\r
761};\r
762\r
763// returns data ptr to free() or PicoTmpStateRestore()\r
764void *PicoTmpStateSave(void)\r
765{\r
766 // gfx only for now\r
767 struct PicoTmp *t = malloc(sizeof(*t));\r
768 if (t == NULL)\r
769 return NULL;\r
770\r
771 memcpy(t->vram, Pico.vram, sizeof(Pico.vram));\r
772 memcpy(t->cram, Pico.cram, sizeof(Pico.cram));\r
773 memcpy(t->vsram, Pico.vsram, sizeof(Pico.vsram));\r
774 memcpy(&t->video, &Pico.video, sizeof(Pico.video));\r
775\r
f3a57b2d 776#ifndef NO_32X\r
b4db550e 777 if (PicoAHW & PAHW_32X) {\r
778 memcpy(&t->t32x.p32x, &Pico32x, sizeof(Pico32x));\r
779 memcpy(t->t32x.dram, Pico32xMem->dram, sizeof(Pico32xMem->dram));\r
780 memcpy(t->t32x.pal, Pico32xMem->pal, sizeof(Pico32xMem->pal));\r
781 }\r
f3a57b2d 782#endif\r
b4db550e 783\r
784 return t;\r
785}\r
786\r
787void PicoTmpStateRestore(void *data)\r
788{\r
789 struct PicoTmp *t = data;\r
790 if (t == NULL)\r
791 return;\r
792\r
793 memcpy(Pico.vram, t->vram, sizeof(Pico.vram));\r
794 memcpy(Pico.cram, t->cram, sizeof(Pico.cram));\r
795 memcpy(Pico.vsram, t->vsram, sizeof(Pico.vsram));\r
796 memcpy(&Pico.video, &t->video, sizeof(Pico.video));\r
797 Pico.m.dirtyPal = 1;\r
798\r
f3a57b2d 799#ifndef NO_32X\r
b4db550e 800 if (PicoAHW & PAHW_32X) {\r
801 memcpy(&Pico32x, &t->t32x.p32x, sizeof(Pico32x));\r
802 memcpy(Pico32xMem->dram, t->t32x.dram, sizeof(Pico32xMem->dram));\r
803 memcpy(Pico32xMem->pal, t->t32x.pal, sizeof(Pico32xMem->pal));\r
804 Pico32x.dirty_pal = 1;\r
805 }\r
f3a57b2d 806#endif\r
b4db550e 807}\r
808\r
ed4402a7 809// vim:shiftwidth=2:ts=2:expandtab\r