5 * This work is licensed under the terms of MAME license.
\r
6 * See COPYING file in the top-level directory.
\r
9 #include "pico_int.h"
\r
12 #include <cpu/sh2/sh2.h>
\r
13 #include "sound/ym2612.h"
\r
14 #include "sound/ym2413.h"
\r
15 #include "sound/sn76496.h"
\r
16 #include "cd/megasd.h"
\r
19 static arearw *areaRead;
\r
20 static arearw *areaWrite;
\r
21 static areaeof *areaEof;
\r
22 static areaseek *areaSeek;
\r
23 static areaclose *areaClose;
\r
25 carthw_state_chunk *carthw_chunks;
\r
26 void (*PicoStateProgressCB)(const char *str);
\r
27 void (*PicoLoadStateHook)(void);
\r
31 static size_t gzRead2(void *p, size_t _size, size_t _n, void *file)
\r
33 return gzread(file, p, _size * _n);
\r
36 static size_t gzWrite2(void *p, size_t _size, size_t _n, void *file)
\r
38 return gzwrite(file, p, _size * _n);
\r
41 static void set_cbs(int gz)
\r
45 areaWrite = gzWrite2;
\r
46 areaEof = (areaeof *) gzeof;
\r
47 areaSeek = (areaseek *) gzseek;
\r
48 areaClose = (areaclose *) gzclose;
\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
58 static void *open_save_file(const char *fname, int is_save)
\r
60 int len = strlen(fname);
\r
63 if (len > 3 && strcasecmp(fname + len - 3, ".gz") == 0)
\r
65 if ( (afile = gzopen(fname, is_save ? "wb" : "rb")) ) {
\r
68 gzsetparams(afile, 9, Z_DEFAULT_STRATEGY);
\r
73 if ( (afile = fopen(fname, is_save ? "wb" : "rb")) ) {
\r
81 // ---------------------------------------------------------------------------
\r
99 CHUNK_PCM_RAM, // 15
\r
104 CHUNK_CDD, // 20 old
\r
109 CHUNK_IOPORTS, // old
\r
116 CHUNK_SSH2_DATA, // 30
\r
121 CHUNK_SSH2_BIOS, // 35
\r
127 CHUNK_32X_FIRST = CHUNK_MSH2,
\r
128 CHUNK_32X_LAST = CHUNK_32X_EVT,
\r
129 // add new stuff here
\r
143 CHUNK_DEFAULT_COUNT,
\r
144 CHUNK_CARTHW_ = CHUNK_CARTHW, // 64 (defined in PicoInt)
\r
148 static const char * const chunk_names[CHUNK_DEFAULT_COUNT] = {
\r
194 static int write_chunk(unsigned char name, int len, void *data, void *file)
\r
196 size_t bwritten = 0;
\r
197 bwritten += areaWrite(&name, 1, 1, file);
\r
198 bwritten += areaWrite(&len, 1, 4, file);
\r
199 bwritten += areaWrite(data, 1, len, file);
\r
201 return (bwritten == len + 4 + 1);
\r
204 #define CHUNK_LIMIT_W 18772 // sizeof(cdc)
\r
206 #define CHECKED_WRITE(name,len,data) { \
\r
207 if (PicoStateProgressCB && name < CHUNK_DEFAULT_COUNT && chunk_names[name]) { \
\r
208 strncpy(sbuff + 9, chunk_names[name], sizeof(sbuff)-1 - 9); \
\r
209 sbuff[sizeof(sbuff)-1] = '\0'; \
\r
210 PicoStateProgressCB(sbuff); \
\r
212 if (data == buf2 && len > CHUNK_LIMIT_W) \
\r
214 if (!write_chunk(name, len, data, file)) \
\r
218 #define CHECKED_WRITE_BUFF(name,buff) { \
\r
219 if (PicoStateProgressCB && name < CHUNK_DEFAULT_COUNT && chunk_names[name]) { \
\r
220 strncpy(sbuff + 9, chunk_names[name], sizeof(sbuff)-1 - 9); \
\r
221 sbuff[sizeof(sbuff)-1] = '\0'; \
\r
222 PicoStateProgressCB(sbuff); \
\r
224 if (!write_chunk(name, sizeof(buff), &buff, file)) \
\r
228 static int state_save(void *file)
\r
230 char sbuff[32] = "Saving.. ";
\r
231 unsigned char buff[0x60], buff_z80[Z80_STATE_SIZE];
\r
233 int ver = 0x0191; // not really used..
\r
237 buf2 = malloc(CHUNK_LIMIT_W);
\r
241 areaWrite("PicoSEXT", 1, 8, file);
\r
242 areaWrite(&ver, 1, 4, file);
\r
244 if (!(PicoIn.AHW & PAHW_SMS)) {
\r
245 // the patches can cause incompatible saves with no-idle
\r
246 SekFinishIdleDet();
\r
248 memset(buff, 0, sizeof(buff));
\r
249 SekPackCpu(buff, 0);
\r
250 CHECKED_WRITE_BUFF(CHUNK_M68K, buff);
\r
251 CHECKED_WRITE_BUFF(CHUNK_RAM, PicoMem.ram);
\r
252 CHECKED_WRITE_BUFF(CHUNK_VSRAM, PicoMem.vsram);
\r
253 CHECKED_WRITE_BUFF(CHUNK_IOPORTS, PicoMem.ioports);
\r
254 len = io_ports_pack(buf2, CHUNK_LIMIT_W);
\r
255 CHECKED_WRITE(CHUNK_IOPORTSv2, len, buf2);
\r
256 if (PicoIn.AHW & PAHW_PICO) {
\r
257 len = PicoPicoPCMSave(buf2, CHUNK_LIMIT_W);
\r
258 CHECKED_WRITE(CHUNK_PICO_PCM, len, buf2);
\r
259 CHECKED_WRITE(CHUNK_PICO, sizeof(PicoPicohw), &PicoPicohw);
\r
262 void *ym_regs = YM2612GetRegs();
\r
263 ym2612_pack_state_old();
\r
264 CHECKED_WRITE(CHUNK_FM, 0x200+4, ym_regs);
\r
266 // write fm state first since timer load needs OPN.ST.mode
\r
267 len = YM2612PicoStateSave3(buf2, CHUNK_LIMIT_W);
\r
268 CHECKED_WRITE(CHUNK_FMv3, len, buf2);
\r
269 len = ym2612_pack_timers(buf2, CHUNK_LIMIT_W);
\r
270 CHECKED_WRITE(CHUNK_FM_TIMERS, len, buf2);
\r
274 if (!(PicoIn.opt & POPT_DIS_IDLE_DET))
\r
278 CHECKED_WRITE_BUFF(CHUNK_SMS, Pico.ms);
\r
279 // only store the FM unit state if it was really used
\r
280 if (Pico.m.hardware & PMS_HW_FMUSED) {
\r
281 len = ym2413_pack_state(buf2, CHUNK_LIMIT_W);
\r
282 CHECKED_WRITE(CHUNK_YM2413, len, buf2);
\r
285 CHECKED_WRITE(CHUNK_PSG, 28*4, sn76496_regs);
\r
287 if (!(PicoIn.AHW & PAHW_PICO)) {
\r
288 z80_pack(buff_z80);
\r
289 CHECKED_WRITE_BUFF(CHUNK_Z80, buff_z80);
\r
290 CHECKED_WRITE_BUFF(CHUNK_ZRAM, PicoMem.zram);
\r
293 CHECKED_WRITE_BUFF(CHUNK_VRAM, PicoMem.vram);
\r
294 CHECKED_WRITE_BUFF(CHUNK_CRAM, PicoMem.cram);
\r
296 CHECKED_WRITE_BUFF(CHUNK_MISC, Pico.m);
\r
297 len = PicoVideoSave(buf2);
\r
298 CHECKED_WRITE(CHUNK_VDP, len, buf2);
\r
299 CHECKED_WRITE_BUFF(CHUNK_VIDEO, Pico.video);
\r
301 if (PicoIn.AHW & PAHW_MCD)
\r
303 memset(buff, 0, sizeof(buff));
\r
304 SekPackCpu(buff, 1);
\r
305 if (Pico_mcd->s68k_regs[3] & 4) // 1M mode?
\r
306 wram_1M_to_2M(Pico_mcd->word_ram2M);
\r
307 memcpy(&Pico_mcd->m.hint_vector, Pico_mcd->bios + 0x72,
\r
308 sizeof(Pico_mcd->m.hint_vector));
\r
310 CHECKED_WRITE_BUFF(CHUNK_S68K, buff);
\r
311 CHECKED_WRITE_BUFF(CHUNK_PRG_RAM, Pico_mcd->prg_ram);
\r
312 CHECKED_WRITE_BUFF(CHUNK_WORD_RAM, Pico_mcd->word_ram2M); // in 2M format
\r
313 CHECKED_WRITE_BUFF(CHUNK_PCM_RAM, Pico_mcd->pcm_ram);
\r
314 CHECKED_WRITE_BUFF(CHUNK_BRAM, Pico_mcd->bram);
\r
315 CHECKED_WRITE_BUFF(CHUNK_GA_REGS, Pico_mcd->s68k_regs); // GA regs, not CPU regs
\r
316 CHECKED_WRITE_BUFF(CHUNK_PCM, Pico_mcd->pcm);
\r
317 CHECKED_WRITE_BUFF(CHUNK_MISC_CD, Pico_mcd->m);
\r
318 memset(buff, 0, 0x40);
\r
319 memcpy(buff, pcd_event_times, sizeof(pcd_event_times));
\r
320 CHECKED_WRITE(CHUNK_CD_EVT, 0x40, buff);
\r
322 len = gfx_context_save(buf2);
\r
323 CHECKED_WRITE(CHUNK_CD_GFX, len, buf2);
\r
324 len = cdc_context_save(buf2);
\r
325 CHECKED_WRITE(CHUNK_CD_CDC, len, buf2);
\r
326 len = cdd_context_save(buf2);
\r
327 CHECKED_WRITE(CHUNK_CD_CDD, len, buf2);
\r
329 CHECKED_WRITE_BUFF(CHUNK_CD_MSD, Pico_msd);
\r
331 if (Pico_mcd->s68k_regs[3] & 4) // convert back
\r
332 wram_2M_to_1M(Pico_mcd->word_ram2M);
\r
336 if (PicoIn.AHW & PAHW_32X)
\r
338 unsigned char cpubuff[SH2_STATE_SIZE];
\r
340 memset(cpubuff, 0, sizeof(cpubuff));
\r
342 sh2_pack(&sh2s[0], cpubuff);
\r
343 CHECKED_WRITE_BUFF(CHUNK_MSH2, cpubuff);
\r
344 CHECKED_WRITE_BUFF(CHUNK_MSH2_DATA, sh2s[0].data_array);
\r
345 CHECKED_WRITE_BUFF(CHUNK_MSH2_PERI, sh2s[0].peri_regs);
\r
347 sh2_pack(&sh2s[1], cpubuff);
\r
348 CHECKED_WRITE_BUFF(CHUNK_SSH2, cpubuff);
\r
349 CHECKED_WRITE_BUFF(CHUNK_SSH2_DATA, sh2s[1].data_array);
\r
350 CHECKED_WRITE_BUFF(CHUNK_SSH2_PERI, sh2s[1].peri_regs);
\r
352 CHECKED_WRITE_BUFF(CHUNK_32XSYS, Pico32x);
\r
353 CHECKED_WRITE_BUFF(CHUNK_M68K_BIOS, Pico32xMem->m68k_rom);
\r
354 CHECKED_WRITE_BUFF(CHUNK_MSH2_BIOS, Pico32xMem->sh2_rom_m);
\r
355 CHECKED_WRITE_BUFF(CHUNK_SSH2_BIOS, Pico32xMem->sh2_rom_s);
\r
356 CHECKED_WRITE_BUFF(CHUNK_SDRAM, Pico32xMem->sdram);
\r
357 CHECKED_WRITE_BUFF(CHUNK_DRAM, Pico32xMem->dram);
\r
358 CHECKED_WRITE_BUFF(CHUNK_32XPAL, Pico32xMem->pal);
\r
360 memset(buff, 0, 0x40);
\r
361 memcpy(buff, p32x_event_times, sizeof(p32x_event_times));
\r
362 CHECKED_WRITE(CHUNK_32X_EVT, 0x40, buff);
\r
366 if (carthw_chunks != NULL)
\r
368 carthw_state_chunk *chwc;
\r
369 if (PicoStateProgressCB)
\r
370 PicoStateProgressCB("Saving.. cart hw state");
\r
371 for (chwc = carthw_chunks; chwc->ptr != NULL; chwc++)
\r
372 CHECKED_WRITE(chwc->chunk, chwc->size, chwc->ptr);
\r
375 CHECKED_WRITE(0, 0, NULL);
\r
384 static int g_read_offs = 0;
\r
386 #define R_ERROR_RETURN(error) \
\r
388 elprintf(EL_STATUS, "load_state @ %x: " error, g_read_offs); \
\r
392 // when is eof really set?
\r
393 #define CHECKED_READ(len,data) { \
\r
394 if (areaRead(data, 1, len, file) != len) { \
\r
395 if (len == 1 && areaEof(file)) goto readend; \
\r
396 R_ERROR_RETURN("areaRead: premature EOF\n"); \
\r
398 g_read_offs += len; \
\r
401 #define CHECKED_READ2(len2,data) { \
\r
402 if (len2 != len) { \
\r
403 elprintf(EL_STATUS, "unexpected len %i, wanted %i (%s)", len, len2, #len2); \
\r
404 if (len > len2) R_ERROR_RETURN("failed."); \
\r
405 /* else read anyway and hope for the best.. */ \
\r
407 CHECKED_READ(len, data); \
\r
410 #define CHECKED_READ_BUFF(buff) CHECKED_READ2(sizeof(buff), &buff);
\r
412 #define CHUNK_LIMIT_R 0x10960 // sizeof(old_cdc)
\r
414 #define CHECKED_READ_LIM(data) { \
\r
415 if (len > CHUNK_LIMIT_R) \
\r
416 R_ERROR_RETURN("chunk size over limit."); \
\r
417 CHECKED_READ(len, data); \
\r
420 static int state_load(void *file)
\r
422 unsigned char buff_m68k[0x60], buff_s68k[0x60];
\r
423 unsigned char buff_z80[Z80_STATE_SIZE];
\r
424 unsigned char buff_sh2[SH2_STATE_SIZE];
\r
425 unsigned char buff_vdp[0x200];
\r
426 unsigned char *buf = NULL;
\r
427 unsigned char chunk;
\r
432 int ver, has_32x = 0;
\r
433 int len, len_vdp = 0;
\r
435 memset(buff_m68k, 0, sizeof(buff_m68k));
\r
436 memset(buff_s68k, 0, sizeof(buff_s68k));
\r
437 memset(buff_z80, 0, sizeof(buff_z80));
\r
439 buf = malloc(CHUNK_LIMIT_R);
\r
444 CHECKED_READ(8, header);
\r
445 if (strncmp(header, "PicoSMCD", 8) && strncmp(header, "PicoSEXT", 8))
\r
446 R_ERROR_RETURN("bad header");
\r
447 CHECKED_READ(4, &ver);
\r
449 memset(pcd_event_times, 0, sizeof(pcd_event_times));
\r
450 memset(p32x_event_times, 0, sizeof(p32x_event_times));
\r
452 while (!areaEof(file))
\r
455 CHECKED_READ(1, &chunk);
\r
456 CHECKED_READ(4, &len);
\r
457 if (len < 0 || len > 1024*512) R_ERROR_RETURN("bad length");
\r
458 if (CHUNK_S68K <= chunk && chunk <= CHUNK_MISC_CD && !(PicoIn.AHW & PAHW_MCD))
\r
459 R_ERROR_RETURN("cd chunk in non CD state?");
\r
461 // 32X only appears in PicoDrive after it has been enabled, so track this
\r
462 has_32x |= CHUNK_32X_FIRST <= chunk && chunk <= CHUNK_32X_LAST;
\r
463 if (has_32x && !(PicoIn.AHW & PAHW_32X))
\r
469 CHECKED_READ_BUFF(buff_m68k);
\r
473 CHECKED_READ_BUFF(buff_z80);
\r
476 case CHUNK_RAM: CHECKED_READ_BUFF(PicoMem.ram); break;
\r
477 case CHUNK_VRAM: CHECKED_READ_BUFF(PicoMem.vram); break;
\r
478 case CHUNK_ZRAM: CHECKED_READ_BUFF(PicoMem.zram); break;
\r
479 case CHUNK_CRAM: CHECKED_READ_BUFF(PicoMem.cram); break;
\r
480 case CHUNK_VSRAM: CHECKED_READ_BUFF(PicoMem.vsram); break;
\r
481 case CHUNK_MISC: CHECKED_READ_BUFF(Pico.m); break;
\r
482 case CHUNK_VIDEO: CHECKED_READ_BUFF(Pico.video); break;
\r
483 case CHUNK_VDP: CHECKED_READ2((len_vdp = len), buff_vdp); break;
\r
485 case CHUNK_IOPORTS: CHECKED_READ_BUFF(PicoMem.ioports); break;
\r
486 case CHUNK_PSG: CHECKED_READ2(28*4, sn76496_regs); break;
\r
488 CHECKED_READ(len, buf);
\r
489 ym2413_unpack_state(buf, len);
\r
490 Pico.m.hardware |= PMS_HW_FMUSED;
\r
493 ym_regs = YM2612GetRegs();
\r
494 CHECKED_READ2(0x200+4, ym_regs);
\r
495 ym2612_unpack_state_old();
\r
497 case CHUNK_FM_TIMERS: CHECKED_READ(len, buf); ym2612_unpack_timers(buf, len); break;
\r
498 case CHUNK_FMv3: CHECKED_READ(len, buf); YM2612PicoStateLoad3(buf, len); break;
\r
499 case CHUNK_IOPORTSv2: CHECKED_READ(len, buf); io_ports_unpack(buf, len); break;
\r
501 case CHUNK_PICO_PCM:
\r
502 CHECKED_READ(len, buf);
\r
503 PicoPicoPCMLoad(buf, len);
\r
506 CHECKED_READ_BUFF(PicoPicohw);
\r
510 CHECKED_READ_BUFF(Pico.ms);
\r
515 CHECKED_READ_BUFF(buff_s68k);
\r
518 case CHUNK_PRG_RAM: CHECKED_READ_BUFF(Pico_mcd->prg_ram); break;
\r
519 case CHUNK_WORD_RAM: CHECKED_READ_BUFF(Pico_mcd->word_ram2M); break;
\r
520 case CHUNK_PCM_RAM: CHECKED_READ_BUFF(Pico_mcd->pcm_ram); break;
\r
521 case CHUNK_BRAM: CHECKED_READ_BUFF(Pico_mcd->bram); break;
\r
522 case CHUNK_GA_REGS: CHECKED_READ_BUFF(Pico_mcd->s68k_regs); break;
\r
523 case CHUNK_PCM: CHECKED_READ_BUFF(Pico_mcd->pcm); break;
\r
524 case CHUNK_MISC_CD: CHECKED_READ_BUFF(Pico_mcd->m); break;
\r
525 case CHUNK_CD_MSD: CHECKED_READ_BUFF(Pico_msd); break;
\r
528 CHECKED_READ2(0x40, buf);
\r
529 memcpy(pcd_event_times, buf, sizeof(pcd_event_times));
\r
533 CHECKED_READ_LIM(buf);
\r
534 len_check = gfx_context_load(buf);
\r
538 CHECKED_READ_LIM(buf);
\r
539 len_check = cdc_context_load(buf);
\r
543 CHECKED_READ_LIM(buf);
\r
544 len_check = cdd_context_load(buf);
\r
547 // old, to be removed:
\r
549 CHECKED_READ_LIM(buf);
\r
550 cdc_context_load_old(buf);
\r
554 CHECKED_READ_LIM(buf);
\r
555 cdd_context_load_old(buf);
\r
561 CHECKED_READ_BUFF(buff_sh2);
\r
562 sh2_unpack(&sh2s[0], buff_sh2);
\r
566 CHECKED_READ_BUFF(buff_sh2);
\r
567 sh2_unpack(&sh2s[1], buff_sh2);
\r
570 case CHUNK_MSH2_DATA: CHECKED_READ_BUFF(sh2s[0].data_array); break;
\r
571 case CHUNK_MSH2_PERI: CHECKED_READ_BUFF(sh2s[0].peri_regs); break;
\r
572 case CHUNK_SSH2_DATA: CHECKED_READ_BUFF(sh2s[1].data_array); break;
\r
573 case CHUNK_SSH2_PERI: CHECKED_READ_BUFF(sh2s[1].peri_regs); break;
\r
574 case CHUNK_32XSYS: CHECKED_READ_BUFF(Pico32x); break;
\r
575 case CHUNK_M68K_BIOS: CHECKED_READ_BUFF(Pico32xMem->m68k_rom); break;
\r
576 case CHUNK_MSH2_BIOS: CHECKED_READ_BUFF(Pico32xMem->sh2_rom_m); break;
\r
577 case CHUNK_SSH2_BIOS: CHECKED_READ_BUFF(Pico32xMem->sh2_rom_s); break;
\r
578 case CHUNK_SDRAM: CHECKED_READ_BUFF(Pico32xMem->sdram); break;
\r
579 case CHUNK_DRAM: CHECKED_READ_BUFF(Pico32xMem->dram); break;
\r
580 case CHUNK_32XPAL: CHECKED_READ_BUFF(Pico32xMem->pal); break;
\r
582 case CHUNK_32X_EVT:
\r
583 CHECKED_READ2(0x40, buf);
\r
584 memcpy(p32x_event_times, buf, sizeof(p32x_event_times));
\r
588 if (!len && !chunk)
\r
590 if (carthw_chunks != NULL)
\r
592 carthw_state_chunk *chwc;
\r
593 for (chwc = carthw_chunks; chwc->ptr != NULL; chwc++) {
\r
594 if (chwc->chunk == chunk) {
\r
595 CHECKED_READ2(chwc->size, chwc->ptr);
\r
600 elprintf(EL_STATUS, "load_state: skipping unknown chunk %i of size %i", chunk, len);
\r
601 areaSeek(file, len, SEEK_CUR);
\r
605 if (len_check != 0 && len_check != len)
\r
606 elprintf(EL_STATUS, "load_state: chunk %d has bad len %d/%d",
\r
611 PicoVideoLoad(buff_vdp, len_vdp);
\r
613 if (PicoIn.AHW & PAHW_32X)
\r
615 Pico32xShutdown(); // in case of loading a state with 32X disabled
\r
617 if (PicoIn.AHW & PAHW_SMS)
\r
618 PicoStateLoadedMS();
\r
620 if (PicoIn.AHW & PAHW_32X)
\r
621 Pico32xStateLoaded(1);
\r
623 if (PicoLoadStateHook != NULL)
\r
624 PicoLoadStateHook();
\r
626 // must unpack 68k and z80 after banks are set up
\r
627 if (!(PicoIn.AHW & PAHW_SMS))
\r
628 SekUnpackCpu(buff_m68k, 0);
\r
629 if (PicoIn.AHW & PAHW_MCD)
\r
630 SekUnpackCpu(buff_s68k, 1);
\r
632 z80_unpack(buff_z80);
\r
634 if (PicoIn.AHW & PAHW_32X)
\r
635 Pico32xStateLoaded(0);
\r
636 if (PicoIn.AHW & PAHW_MCD)
\r
637 pcd_state_loaded();
\r
638 if (!(PicoIn.AHW & PAHW_SMS)) {
\r
639 Pico.video.status &= ~(SR_VB | SR_F);
\r
640 Pico.video.status |= ((Pico.video.reg[1] >> 3) ^ SR_VB) & SR_VB;
\r
641 Pico.video.status |= (Pico.video.pending_ints << 2) & SR_F;
\r
644 Pico.m.dirtyPal = 1;
\r
652 static int state_load_gfx(void *file)
\r
654 int ver, len, found = 0, to_find = 4;
\r
655 u8 buff_vdp[0x200];
\r
659 if (PicoIn.AHW & PAHW_32X)
\r
663 CHECKED_READ(8, buff);
\r
664 if (strncmp((char *)buff, "PicoSMCD", 8) && strncmp((char *)buff, "PicoSEXT", 8))
\r
665 R_ERROR_RETURN("bad header");
\r
666 CHECKED_READ(4, &ver);
\r
668 while (!areaEof(file) && found < to_find)
\r
670 CHECKED_READ(1, buff);
\r
671 CHECKED_READ(4, &len);
\r
672 if (len < 0 || len > 1024*512) R_ERROR_RETURN("bad length");
\r
673 if (buff[0] > CHUNK_FM && buff[0] <= CHUNK_MISC_CD && !(PicoIn.AHW & PAHW_MCD))
\r
674 R_ERROR_RETURN("cd chunk in non CD state?");
\r
678 case CHUNK_VRAM: CHECKED_READ_BUFF(PicoMem.vram); found++; break;
\r
679 case CHUNK_CRAM: CHECKED_READ_BUFF(PicoMem.cram); found++; break;
\r
680 case CHUNK_VSRAM: CHECKED_READ_BUFF(PicoMem.vsram); found++; break;
\r
681 case CHUNK_VIDEO: CHECKED_READ_BUFF(Pico.video); found++; break;
\r
682 case CHUNK_VDP: CHECKED_READ2((len_vdp = len), buff_vdp); break;
\r
686 if (Pico32xMem != NULL)
\r
687 CHECKED_READ_BUFF(Pico32xMem->dram);
\r
692 if (Pico32xMem != NULL)
\r
693 CHECKED_READ_BUFF(Pico32xMem->pal);
\r
695 Pico32x.dirty_pal = 1;
\r
699 CHECKED_READ_BUFF(Pico32x);
\r
704 areaSeek(file, len, SEEK_CUR);
\r
708 PicoVideoLoad(buff_vdp, len_vdp);
\r
715 static int pico_state_internal(void *afile, int is_save)
\r
720 ret = state_save(afile);
\r
722 ret = state_load(afile);
\r
727 int PicoState(const char *fname, int is_save)
\r
729 void *afile = NULL;
\r
732 afile = open_save_file(fname, is_save);
\r
736 ret = pico_state_internal(afile, is_save);
\r
741 int PicoStateFP(void *afile, int is_save,
\r
742 arearw *read, arearw *write, areaeof *eof, areaseek *seek)
\r
750 return pico_state_internal(afile, is_save);
\r
753 int PicoStateLoadGfx(const char *fname)
\r
758 afile = open_save_file(fname, 0);
\r
762 ret = state_load_gfx(afile);
\r
765 areaSeek(afile, 0x10020, SEEK_SET); // skip header and RAM
\r
766 areaRead(PicoMem.vram, 1, sizeof(PicoMem.vram), afile);
\r
767 areaSeek(afile, 0x2000, SEEK_CUR);
\r
768 areaRead(PicoMem.cram, 1, sizeof(PicoMem.cram), afile);
\r
769 areaRead(PicoMem.vsram, 1, sizeof(PicoMem.vsram), afile);
\r
770 areaSeek(afile, 0x221a0, SEEK_SET);
\r
771 areaRead(&Pico.video, 1, sizeof(Pico.video), afile);
\r
772 PicoVideoCacheSAT(1);
\r
776 Pico.est.rendstatus = -1;
\r
783 unsigned short vram[0x8000];
\r
784 unsigned short cram[0x40];
\r
785 unsigned short vsram[0x40];
\r
786 unsigned int satcache[2*0x80];
\r
788 //struct PicoMisc m;
\r
789 struct PicoVideo video;
\r
794 struct Pico32x p32x;
\r
795 unsigned short dram[2][0x20000/2];
\r
796 unsigned short pal[0x100];
\r
800 // returns data ptr to free() or PicoTmpStateRestore()
\r
801 void *PicoTmpStateSave(void)
\r
803 // gfx only for now
\r
804 struct PicoTmp *t = malloc(sizeof(*t));
\r
808 memcpy(t->vram, PicoMem.vram, sizeof(PicoMem.vram));
\r
809 memcpy(t->cram, PicoMem.cram, sizeof(PicoMem.cram));
\r
810 memcpy(t->vsram, PicoMem.vsram, sizeof(PicoMem.vsram));
\r
811 memcpy(t->satcache, VdpSATCache, sizeof(VdpSATCache));
\r
812 memcpy(&t->video, &Pico.video, sizeof(Pico.video));
\r
813 t->vdp_len = PicoVideoSave(t->vdp);
\r
816 if (PicoIn.AHW & PAHW_32X) {
\r
817 memcpy(&t->t32x.p32x, &Pico32x, sizeof(Pico32x));
\r
818 memcpy(t->t32x.dram, Pico32xMem->dram, sizeof(Pico32xMem->dram));
\r
819 memcpy(t->t32x.pal, Pico32xMem->pal, sizeof(Pico32xMem->pal));
\r
826 void PicoTmpStateRestore(void *data)
\r
828 struct PicoTmp *t = data;
\r
832 memcpy(PicoMem.vram, t->vram, sizeof(PicoMem.vram));
\r
833 memcpy(PicoMem.cram, t->cram, sizeof(PicoMem.cram));
\r
834 memcpy(PicoMem.vsram, t->vsram, sizeof(PicoMem.vsram));
\r
835 memcpy(VdpSATCache, t->satcache, sizeof(VdpSATCache));
\r
836 memcpy(&Pico.video, &t->video, sizeof(Pico.video));
\r
837 Pico.m.dirtyPal = 1;
\r
838 PicoVideoLoad(t->vdp, t->vdp_len);
\r
841 if (PicoIn.AHW & PAHW_32X) {
\r
842 memcpy(&Pico32x, &t->t32x.p32x, sizeof(Pico32x));
\r
843 memcpy(Pico32xMem->dram, t->t32x.dram, sizeof(Pico32xMem->dram));
\r
844 memcpy(Pico32xMem->pal, t->t32x.pal, sizeof(Pico32xMem->pal));
\r
845 Pico32x.dirty_pal = 1;
\r
851 // vim:shiftwidth=2:ts=2:expandtab
\r