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