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