123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788 |
- /*
- * PicoDrive
- * (C) notaz, 2010
- *
- * This work is licensed under the terms of MAME license.
- * See COPYING file in the top-level directory.
- */
- #include "pico_int.h"
- #include <zlib.h>
- #include "../cpu/sh2/sh2.h"
- #include "sound/ym2612.h"
- #include "sound/emu2413/emu2413.h"
- #include "state.h"
- #ifdef USE_LIBRETRO_VFS
- #include "file_stream_transforms.h"
- #endif
- // sn76496 & ym2413
- extern int *sn76496_regs;
- extern OPLL old_opll;
- static arearw *areaRead;
- static arearw *areaWrite;
- static areaeof *areaEof;
- static areaseek *areaSeek;
- static areaclose *areaClose;
- carthw_state_chunk *carthw_chunks;
- void (*PicoStateProgressCB)(const char *str);
- void (*PicoLoadStateHook)(void);
- /* I/O functions */
- static size_t gzRead2(void *p, size_t _size, size_t _n, void *file)
- {
- return gzread(file, p, _size * _n);
- }
- static size_t gzWrite2(void *p, size_t _size, size_t _n, void *file)
- {
- return gzwrite(file, p, _size * _n);
- }
- static void set_cbs(int gz)
- {
- if (gz) {
- areaRead = gzRead2;
- areaWrite = gzWrite2;
- areaEof = (areaeof *) gzeof;
- areaSeek = (areaseek *) gzseek;
- areaClose = (areaclose *) gzclose;
- } else {
- areaRead = (arearw *) fread;
- areaWrite = (arearw *) fwrite;
- areaEof = (areaeof *) feof;
- areaSeek = (areaseek *) fseek;
- areaClose = (areaclose *) fclose;
- }
- }
- static void *open_save_file(const char *fname, int is_save)
- {
- int len = strlen(fname);
- void *afile = NULL;
- if (len > 3 && strcmp(fname + len - 3, ".gz") == 0)
- {
- if ( (afile = gzopen(fname, is_save ? "wb" : "rb")) ) {
- set_cbs(1);
- if (is_save)
- gzsetparams(afile, 9, Z_DEFAULT_STRATEGY);
- }
- }
- else
- {
- if ( (afile = fopen(fname, is_save ? "wb" : "rb")) ) {
- set_cbs(0);
- }
- }
- return afile;
- }
- // ---------------------------------------------------------------------------
- typedef enum {
- CHUNK_M68K = 1,
- CHUNK_RAM,
- CHUNK_VRAM,
- CHUNK_ZRAM,
- CHUNK_CRAM, // 5
- CHUNK_VSRAM,
- CHUNK_MISC,
- CHUNK_VIDEO,
- CHUNK_Z80,
- CHUNK_PSG, // 10
- CHUNK_FM,
- // CD stuff
- CHUNK_S68K,
- CHUNK_PRG_RAM,
- CHUNK_WORD_RAM,
- CHUNK_PCM_RAM, // 15
- CHUNK_BRAM,
- CHUNK_GA_REGS,
- CHUNK_PCM,
- CHUNK_CDC, // old
- CHUNK_CDD, // 20 old
- CHUNK_SCD, // old
- CHUNK_RC, // old
- CHUNK_MISC_CD,
- //
- CHUNK_IOPORTS, // versions < 1.70 did not save that..
- CHUNK_SMS, // 25
- // 32x
- CHUNK_MSH2,
- CHUNK_MSH2_DATA,
- CHUNK_MSH2_PERI,
- CHUNK_SSH2,
- CHUNK_SSH2_DATA, // 30
- CHUNK_SSH2_PERI,
- CHUNK_32XSYS,
- CHUNK_M68K_BIOS,
- CHUNK_MSH2_BIOS,
- CHUNK_SSH2_BIOS, // 35
- CHUNK_SDRAM,
- CHUNK_DRAM,
- CHUNK_32XPAL,
- CHUNK_32X_EVT,
- CHUNK_YM2413, //40
- //rename
- CHUNK_32X_FIRST = CHUNK_MSH2,
- CHUNK_32X_LAST = CHUNK_32X_EVT,
- // add new stuff here
- CHUNK_CD_EVT = 50,
- CHUNK_CD_GFX,
- CHUNK_CD_CDC,
- CHUNK_CD_CDD,
- //
- CHUNK_DEFAULT_COUNT,
- CHUNK_CARTHW_ = CHUNK_CARTHW, // 64 (defined in PicoInt)
- } chunk_name_e;
- static const char * const chunk_names[CHUNK_DEFAULT_COUNT] = {
- "INVALID!",
- "M68K state",
- "RAM",
- "VRAM",
- "ZRAM",
- "CRAM", // 5
- "VSRAM",
- "emu state",
- "VIDEO",
- "Z80 state",
- "PSG", // 10
- "FM",
- // CD stuff
- "S68K state",
- "PRG_RAM",
- "WORD_RAM",
- "PCM_RAM", // 15
- "BRAM",
- "GATE ARRAY regs",
- "PCM state",
- "CDC",
- "CDD", // 20
- "SCD",
- "GFX chip",
- "MCD state",
- //
- "IO",
- "SMS state", // 25
- // 32x
- "MSH2",
- "MSH2 data",
- "MSH2 peri",
- "SSH2",
- "SSH2 data", // 30
- "SSH2 peri",
- "32X system regs",
- "M68K BIOS",
- "MSH2 BIOS",
- "SSH2 BIOS", // 35
- "SDRAM",
- "DRAM",
- "PAL",
- "events",
- "YM2413", //40
- };
- static int write_chunk(chunk_name_e name, int len, void *data, void *file)
- {
- size_t bwritten = 0;
- bwritten += areaWrite(&name, 1, 1, file);
- bwritten += areaWrite(&len, 1, 4, file);
- bwritten += areaWrite(data, 1, len, file);
- return (bwritten == len + 4 + 1);
- }
- #define CHUNK_LIMIT_W 18772 // sizeof(cdc)
- #define CHECKED_WRITE(name,len,data) { \
- if (PicoStateProgressCB && name < CHUNK_DEFAULT_COUNT && chunk_names[name]) { \
- strncpy(sbuff + 9, chunk_names[name], sizeof(sbuff) - 9); \
- PicoStateProgressCB(sbuff); \
- } \
- if (data == buf2 && len > CHUNK_LIMIT_W) \
- goto out; \
- if (!write_chunk(name, len, data, file)) \
- goto out; \
- }
- #define CHECKED_WRITE_BUFF(name,buff) { \
- if (PicoStateProgressCB && name < CHUNK_DEFAULT_COUNT && chunk_names[name]) { \
- strncpy(sbuff + 9, chunk_names[name], sizeof(sbuff) - 9); \
- PicoStateProgressCB(sbuff); \
- } \
- if (!write_chunk(name, sizeof(buff), &buff, file)) \
- goto out; \
- }
- static int state_save(void *file)
- {
- char sbuff[32] = "Saving.. ";
- unsigned char buff[0x60], buff_z80[Z80_STATE_SIZE];
- void *ym2612_regs = YM2612GetRegs();
- void *buf2 = NULL;
- int ver = 0x0191; // not really used..
- int retval = -1;
- int len;
- areaWrite("PicoSEXT", 1, 8, file);
- areaWrite(&ver, 1, 4, file);
- if (!(PicoIn.AHW & PAHW_SMS)) {
- // the patches can cause incompatible saves with no-idle
- SekFinishIdleDet();
- memset(buff, 0, sizeof(buff));
- SekPackCpu(buff, 0);
- CHECKED_WRITE_BUFF(CHUNK_M68K, buff);
- CHECKED_WRITE_BUFF(CHUNK_RAM, PicoMem.ram);
- CHECKED_WRITE_BUFF(CHUNK_VSRAM, PicoMem.vsram);
- CHECKED_WRITE_BUFF(CHUNK_IOPORTS, PicoMem.ioports);
- ym2612_pack_state();
- CHECKED_WRITE(CHUNK_FM, 0x200+4, ym2612_regs);
- if (!(PicoIn.opt & POPT_DIS_IDLE_DET))
- SekInitIdleDet();
- }
- else {
- CHECKED_WRITE_BUFF(CHUNK_SMS, Pico.ms);
- }
- CHECKED_WRITE_BUFF(CHUNK_VRAM, PicoMem.vram);
- CHECKED_WRITE_BUFF(CHUNK_ZRAM, PicoMem.zram);
- CHECKED_WRITE_BUFF(CHUNK_CRAM, PicoMem.cram);
- CHECKED_WRITE_BUFF(CHUNK_MISC, Pico.m);
- PicoVideoSave();
- CHECKED_WRITE_BUFF(CHUNK_VIDEO, Pico.video);
- z80_pack(buff_z80);
- CHECKED_WRITE_BUFF(CHUNK_Z80, buff_z80);
- CHECKED_WRITE(CHUNK_PSG, 28*4, sn76496_regs);
- if (PicoIn.AHW & PAHW_MCD)
- {
- buf2 = malloc(CHUNK_LIMIT_W);
- if (buf2 == NULL)
- return -1;
- memset(buff, 0, sizeof(buff));
- SekPackCpu(buff, 1);
- if (Pico_mcd->s68k_regs[3] & 4) // 1M mode?
- wram_1M_to_2M(Pico_mcd->word_ram2M);
- memcpy(&Pico_mcd->m.hint_vector, Pico_mcd->bios + 0x72,
- sizeof(Pico_mcd->m.hint_vector));
- CHECKED_WRITE_BUFF(CHUNK_S68K, buff);
- CHECKED_WRITE_BUFF(CHUNK_PRG_RAM, Pico_mcd->prg_ram);
- CHECKED_WRITE_BUFF(CHUNK_WORD_RAM, Pico_mcd->word_ram2M); // in 2M format
- CHECKED_WRITE_BUFF(CHUNK_PCM_RAM, Pico_mcd->pcm_ram);
- CHECKED_WRITE_BUFF(CHUNK_BRAM, Pico_mcd->bram);
- CHECKED_WRITE_BUFF(CHUNK_GA_REGS, Pico_mcd->s68k_regs); // GA regs, not CPU regs
- CHECKED_WRITE_BUFF(CHUNK_PCM, Pico_mcd->pcm);
- CHECKED_WRITE_BUFF(CHUNK_MISC_CD, Pico_mcd->m);
- memset(buff, 0, 0x40);
- memcpy(buff, pcd_event_times, sizeof(pcd_event_times));
- CHECKED_WRITE(CHUNK_CD_EVT, 0x40, buff);
- CHECKED_WRITE(CHUNK_YM2413, sizeof(OPLL), &old_opll);
- len = gfx_context_save(buf2);
- CHECKED_WRITE(CHUNK_CD_GFX, len, buf2);
- len = cdc_context_save(buf2);
- CHECKED_WRITE(CHUNK_CD_CDC, len, buf2);
- len = cdd_context_save(buf2);
- CHECKED_WRITE(CHUNK_CD_CDD, len, buf2);
- if (Pico_mcd->s68k_regs[3] & 4) // convert back
- wram_2M_to_1M(Pico_mcd->word_ram2M);
- }
- #ifndef NO_32X
- if (PicoIn.AHW & PAHW_32X)
- {
- unsigned char cpubuff[SH2_STATE_SIZE];
- memset(cpubuff, 0, sizeof(cpubuff));
- sh2_pack(&sh2s[0], cpubuff);
- CHECKED_WRITE_BUFF(CHUNK_MSH2, cpubuff);
- CHECKED_WRITE_BUFF(CHUNK_MSH2_DATA, sh2s[0].data_array);
- CHECKED_WRITE_BUFF(CHUNK_MSH2_PERI, sh2s[0].peri_regs);
- sh2_pack(&sh2s[1], cpubuff);
- CHECKED_WRITE_BUFF(CHUNK_SSH2, cpubuff);
- CHECKED_WRITE_BUFF(CHUNK_SSH2_DATA, sh2s[1].data_array);
- CHECKED_WRITE_BUFF(CHUNK_SSH2_PERI, sh2s[1].peri_regs);
- CHECKED_WRITE_BUFF(CHUNK_32XSYS, Pico32x);
- CHECKED_WRITE_BUFF(CHUNK_M68K_BIOS, Pico32xMem->m68k_rom);
- CHECKED_WRITE_BUFF(CHUNK_MSH2_BIOS, Pico32xMem->sh2_rom_m);
- CHECKED_WRITE_BUFF(CHUNK_SSH2_BIOS, Pico32xMem->sh2_rom_s);
- CHECKED_WRITE_BUFF(CHUNK_SDRAM, Pico32xMem->sdram);
- CHECKED_WRITE_BUFF(CHUNK_DRAM, Pico32xMem->dram);
- CHECKED_WRITE_BUFF(CHUNK_32XPAL, Pico32xMem->pal);
- memset(buff, 0, 0x40);
- memcpy(buff, p32x_event_times, sizeof(p32x_event_times));
- CHECKED_WRITE(CHUNK_32X_EVT, 0x40, buff);
- }
- #endif
- if (carthw_chunks != NULL)
- {
- carthw_state_chunk *chwc;
- if (PicoStateProgressCB)
- PicoStateProgressCB("Saving.. cart hw state");
- for (chwc = carthw_chunks; chwc->ptr != NULL; chwc++)
- CHECKED_WRITE(chwc->chunk, chwc->size, chwc->ptr);
- }
- retval = 0;
- out:
- if (buf2 != NULL)
- free(buf2);
- return retval;
- }
- static int g_read_offs = 0;
- #define R_ERROR_RETURN(error) \
- { \
- elprintf(EL_STATUS, "load_state @ %x: " error, g_read_offs); \
- goto out; \
- }
- // when is eof really set?
- #define CHECKED_READ(len,data) { \
- if (areaRead(data, 1, len, file) != len) { \
- if (len == 1 && areaEof(file)) goto readend; \
- R_ERROR_RETURN("areaRead: premature EOF\n"); \
- } \
- g_read_offs += len; \
- }
- #define CHECKED_READ2(len2,data) { \
- if (len2 != len) { \
- elprintf(EL_STATUS, "unexpected len %i, wanted %i (%s)", len, len2, #len2); \
- if (len > len2) R_ERROR_RETURN("failed."); \
- /* else read anyway and hope for the best.. */ \
- } \
- CHECKED_READ(len, data); \
- }
- #define CHECKED_READ_BUFF(buff) CHECKED_READ2(sizeof(buff), &buff);
- #define CHUNK_LIMIT_R 0x10960 // sizeof(old_cdc)
- #define CHECKED_READ_LIM(data) { \
- if (len > CHUNK_LIMIT_R) \
- R_ERROR_RETURN("chunk size over limit."); \
- CHECKED_READ(len, data); \
- }
- static int state_load(void *file)
- {
- unsigned char buff_m68k[0x60], buff_s68k[0x60];
- unsigned char buff_z80[Z80_STATE_SIZE];
- unsigned char buff_sh2[SH2_STATE_SIZE];
- unsigned char *buf = NULL;
- unsigned char chunk;
- void *ym2612_regs;
- int len_check;
- int retval = -1;
- char header[8];
- int ver, len;
- memset(buff_m68k, 0, sizeof(buff_m68k));
- memset(buff_s68k, 0, sizeof(buff_s68k));
- memset(buff_z80, 0, sizeof(buff_z80));
- buf = malloc(CHUNK_LIMIT_R);
- if (buf == NULL)
- return -1;
- g_read_offs = 0;
- CHECKED_READ(8, header);
- if (strncmp(header, "PicoSMCD", 8) && strncmp(header, "PicoSEXT", 8))
- R_ERROR_RETURN("bad header");
- CHECKED_READ(4, &ver);
- memset(pcd_event_times, 0, sizeof(pcd_event_times));
- memset(p32x_event_times, 0, sizeof(p32x_event_times));
- while (!areaEof(file))
- {
- len_check = 0;
- CHECKED_READ(1, &chunk);
- CHECKED_READ(4, &len);
- if (len < 0 || len > 1024*512) R_ERROR_RETURN("bad length");
- if (CHUNK_S68K <= chunk && chunk <= CHUNK_MISC_CD && !(PicoIn.AHW & PAHW_MCD))
- R_ERROR_RETURN("cd chunk in non CD state?");
- if (CHUNK_32X_FIRST <= chunk && chunk <= CHUNK_32X_LAST && !(PicoIn.AHW & PAHW_32X))
- Pico32xStartup();
- switch (chunk)
- {
- case CHUNK_M68K:
- CHECKED_READ_BUFF(buff_m68k);
- break;
- case CHUNK_Z80:
- CHECKED_READ_BUFF(buff_z80);
- break;
- case CHUNK_RAM: CHECKED_READ_BUFF(PicoMem.ram); break;
- case CHUNK_VRAM: CHECKED_READ_BUFF(PicoMem.vram); break;
- case CHUNK_ZRAM: CHECKED_READ_BUFF(PicoMem.zram); break;
- case CHUNK_CRAM: CHECKED_READ_BUFF(PicoMem.cram); break;
- case CHUNK_VSRAM: CHECKED_READ_BUFF(PicoMem.vsram); break;
- case CHUNK_MISC: CHECKED_READ_BUFF(Pico.m); break;
- case CHUNK_VIDEO:
- CHECKED_READ_BUFF(Pico.video);
- PicoVideoLoad();
- break;
- case CHUNK_IOPORTS: CHECKED_READ_BUFF(PicoMem.ioports); break;
- case CHUNK_PSG: CHECKED_READ2(28*4, sn76496_regs); break;
- case CHUNK_YM2413: CHECKED_READ2(sizeof(OPLL), &old_opll); break;
- case CHUNK_FM:
- ym2612_regs = YM2612GetRegs();
- CHECKED_READ2(0x200+4, ym2612_regs);
- ym2612_unpack_state();
- break;
- case CHUNK_SMS:
- CHECKED_READ_BUFF(Pico.ms);
- break;
- // cd stuff
- case CHUNK_S68K:
- CHECKED_READ_BUFF(buff_s68k);
- break;
- case CHUNK_PRG_RAM: CHECKED_READ_BUFF(Pico_mcd->prg_ram); break;
- case CHUNK_WORD_RAM: CHECKED_READ_BUFF(Pico_mcd->word_ram2M); break;
- case CHUNK_PCM_RAM: CHECKED_READ_BUFF(Pico_mcd->pcm_ram); break;
- case CHUNK_BRAM: CHECKED_READ_BUFF(Pico_mcd->bram); break;
- case CHUNK_GA_REGS: CHECKED_READ_BUFF(Pico_mcd->s68k_regs); break;
- case CHUNK_PCM: CHECKED_READ_BUFF(Pico_mcd->pcm); break;
- case CHUNK_MISC_CD: CHECKED_READ_BUFF(Pico_mcd->m); break;
- case CHUNK_CD_EVT:
- CHECKED_READ2(0x40, buf);
- memcpy(pcd_event_times, buf, sizeof(pcd_event_times));
- break;
- case CHUNK_CD_GFX:
- CHECKED_READ_LIM(buf);
- len_check = gfx_context_load(buf);
- break;
- case CHUNK_CD_CDC:
- CHECKED_READ_LIM(buf);
- len_check = cdc_context_load(buf);
- break;
- case CHUNK_CD_CDD:
- CHECKED_READ_LIM(buf);
- len_check = cdd_context_load(buf);
- break;
- // old, to be removed:
- case CHUNK_CDC:
- CHECKED_READ_LIM(buf);
- cdc_context_load_old(buf);
- break;
- case CHUNK_SCD:
- CHECKED_READ_LIM(buf);
- cdd_context_load_old(buf);
- break;
- // 32x stuff
- #ifndef NO_32X
- case CHUNK_MSH2:
- CHECKED_READ_BUFF(buff_sh2);
- sh2_unpack(&sh2s[0], buff_sh2);
- break;
- case CHUNK_SSH2:
- CHECKED_READ_BUFF(buff_sh2);
- sh2_unpack(&sh2s[1], buff_sh2);
- break;
- case CHUNK_MSH2_DATA: CHECKED_READ_BUFF(sh2s[0].data_array); break;
- case CHUNK_MSH2_PERI: CHECKED_READ_BUFF(sh2s[0].peri_regs); break;
- case CHUNK_SSH2_DATA: CHECKED_READ_BUFF(sh2s[1].data_array); break;
- case CHUNK_SSH2_PERI: CHECKED_READ_BUFF(sh2s[1].peri_regs); break;
- case CHUNK_32XSYS: CHECKED_READ_BUFF(Pico32x); break;
- case CHUNK_M68K_BIOS: CHECKED_READ_BUFF(Pico32xMem->m68k_rom); break;
- case CHUNK_MSH2_BIOS: CHECKED_READ_BUFF(Pico32xMem->sh2_rom_m); break;
- case CHUNK_SSH2_BIOS: CHECKED_READ_BUFF(Pico32xMem->sh2_rom_s); break;
- case CHUNK_SDRAM: CHECKED_READ_BUFF(Pico32xMem->sdram); break;
- case CHUNK_DRAM: CHECKED_READ_BUFF(Pico32xMem->dram); break;
- case CHUNK_32XPAL: CHECKED_READ_BUFF(Pico32xMem->pal); break;
- case CHUNK_32X_EVT:
- CHECKED_READ2(0x40, buf);
- memcpy(p32x_event_times, buf, sizeof(p32x_event_times));
- break;
- #endif
- default:
- if (carthw_chunks != NULL)
- {
- carthw_state_chunk *chwc;
- for (chwc = carthw_chunks; chwc->ptr != NULL; chwc++) {
- if (chwc->chunk == chunk) {
- CHECKED_READ2(chwc->size, chwc->ptr);
- goto breakswitch;
- }
- }
- }
- elprintf(EL_STATUS, "load_state: skipping unknown chunk %i of size %i", chunk, len);
- areaSeek(file, len, SEEK_CUR);
- break;
- }
- breakswitch:
- if (len_check != 0 && len_check != len)
- elprintf(EL_STATUS, "load_state: chunk %d has bad len %d/%d",
- len, len_check);
- }
- readend:
- if (PicoIn.AHW & PAHW_SMS)
- PicoStateLoadedMS();
- if (PicoIn.AHW & PAHW_32X)
- Pico32xStateLoaded(1);
- if (PicoLoadStateHook != NULL)
- PicoLoadStateHook();
- // must unpack 68k and z80 after banks are set up
- if (!(PicoIn.AHW & PAHW_SMS))
- SekUnpackCpu(buff_m68k, 0);
- if (PicoIn.AHW & PAHW_MCD)
- SekUnpackCpu(buff_s68k, 1);
- z80_unpack(buff_z80);
- // due to dep from 68k cycles..
- Pico.t.m68c_frame_start = Pico.t.m68c_aim = Pico.t.m68c_cnt;
- if (PicoIn.AHW & PAHW_32X)
- Pico32xStateLoaded(0);
- if (PicoIn.AHW & PAHW_MCD)
- {
- SekCycleAimS68k = SekCycleCntS68k;
- pcd_state_loaded();
- }
- Pico.m.dirtyPal = 1;
- Pico.video.status &= ~(SR_VB | SR_F);
- Pico.video.status |= ((Pico.video.reg[1] >> 3) ^ SR_VB) & SR_VB;
- Pico.video.status |= (Pico.video.pending_ints << 2) & SR_F;
- retval = 0;
- out:
- free(buf);
- return retval;
- }
- static int state_load_gfx(void *file)
- {
- int ver, len, found = 0, to_find = 4;
- char buff[8];
- if (PicoIn.AHW & PAHW_32X)
- to_find += 2;
- g_read_offs = 0;
- CHECKED_READ(8, buff);
- if (strncmp((char *)buff, "PicoSMCD", 8) && strncmp((char *)buff, "PicoSEXT", 8))
- R_ERROR_RETURN("bad header");
- CHECKED_READ(4, &ver);
- while (!areaEof(file) && found < to_find)
- {
- CHECKED_READ(1, buff);
- CHECKED_READ(4, &len);
- if (len < 0 || len > 1024*512) R_ERROR_RETURN("bad length");
- if (buff[0] > CHUNK_FM && buff[0] <= CHUNK_MISC_CD && !(PicoIn.AHW & PAHW_MCD))
- R_ERROR_RETURN("cd chunk in non CD state?");
- switch (buff[0])
- {
- case CHUNK_VRAM: CHECKED_READ_BUFF(PicoMem.vram); found++; break;
- case CHUNK_CRAM: CHECKED_READ_BUFF(PicoMem.cram); found++; break;
- case CHUNK_VSRAM: CHECKED_READ_BUFF(PicoMem.vsram); found++; break;
- case CHUNK_VIDEO: CHECKED_READ_BUFF(Pico.video); found++; break;
- #ifndef NO_32X
- case CHUNK_DRAM:
- if (Pico32xMem != NULL)
- CHECKED_READ_BUFF(Pico32xMem->dram);
- break;
- case CHUNK_32XPAL:
- if (Pico32xMem != NULL)
- CHECKED_READ_BUFF(Pico32xMem->pal);
- Pico32x.dirty_pal = 1;
- break;
- case CHUNK_32XSYS:
- CHECKED_READ_BUFF(Pico32x);
- break;
- #endif
- default:
- areaSeek(file, len, SEEK_CUR);
- break;
- }
- }
- out:
- readend:
- return 0;
- }
- static int pico_state_internal(void *afile, int is_save)
- {
- int ret;
- if (is_save)
- ret = state_save(afile);
- else
- ret = state_load(afile);
- return ret;
- }
- int PicoState(const char *fname, int is_save)
- {
- void *afile = NULL;
- int ret;
- afile = open_save_file(fname, is_save);
- if (afile == NULL)
- return -1;
- ret = pico_state_internal(afile, is_save);
- areaClose(afile);
- return ret;
- }
- int PicoStateFP(void *afile, int is_save,
- arearw *read, arearw *write, areaeof *eof, areaseek *seek)
- {
- areaRead = read;
- areaWrite = write;
- areaEof = eof;
- areaSeek = seek;
- areaClose = NULL;
- return pico_state_internal(afile, is_save);
- }
- int PicoStateLoadGfx(const char *fname)
- {
- void *afile;
- int ret;
- afile = open_save_file(fname, 0);
- if (afile == NULL)
- return -1;
- ret = state_load_gfx(afile);
- if (ret != 0) {
- // assume legacy
- areaSeek(afile, 0x10020, SEEK_SET); // skip header and RAM
- areaRead(PicoMem.vram, 1, sizeof(PicoMem.vram), afile);
- areaSeek(afile, 0x2000, SEEK_CUR);
- areaRead(PicoMem.cram, 1, sizeof(PicoMem.cram), afile);
- areaRead(PicoMem.vsram, 1, sizeof(PicoMem.vsram), afile);
- areaSeek(afile, 0x221a0, SEEK_SET);
- areaRead(&Pico.video, 1, sizeof(Pico.video), afile);
- }
- areaClose(afile);
- PicoVideoCacheSAT();
- return 0;
- }
- // tmp state
- struct PicoTmp
- {
- unsigned short vram[0x8000];
- unsigned short cram[0x40];
- unsigned short vsram[0x40];
- unsigned int satcache[0x80];
- //struct PicoMisc m;
- struct PicoVideo video;
- struct {
- struct Pico32x p32x;
- unsigned short dram[2][0x20000/2];
- unsigned short pal[0x100];
- } t32x;
- };
- // returns data ptr to free() or PicoTmpStateRestore()
- void *PicoTmpStateSave(void)
- {
- // gfx only for now
- struct PicoTmp *t = malloc(sizeof(*t));
- if (t == NULL)
- return NULL;
- memcpy(t->vram, PicoMem.vram, sizeof(PicoMem.vram));
- memcpy(t->cram, PicoMem.cram, sizeof(PicoMem.cram));
- memcpy(t->vsram, PicoMem.vsram, sizeof(PicoMem.vsram));
- memcpy(t->satcache, VdpSATCache, sizeof(VdpSATCache));
- memcpy(&t->video, &Pico.video, sizeof(Pico.video));
- #ifndef NO_32X
- if (PicoIn.AHW & PAHW_32X) {
- memcpy(&t->t32x.p32x, &Pico32x, sizeof(Pico32x));
- memcpy(t->t32x.dram, Pico32xMem->dram, sizeof(Pico32xMem->dram));
- memcpy(t->t32x.pal, Pico32xMem->pal, sizeof(Pico32xMem->pal));
- }
- #endif
- return t;
- }
- void PicoTmpStateRestore(void *data)
- {
- struct PicoTmp *t = data;
- if (t == NULL)
- return;
- memcpy(PicoMem.vram, t->vram, sizeof(PicoMem.vram));
- memcpy(PicoMem.cram, t->cram, sizeof(PicoMem.cram));
- memcpy(PicoMem.vsram, t->vsram, sizeof(PicoMem.vsram));
- memcpy(VdpSATCache, t->satcache, sizeof(VdpSATCache));
- memcpy(&Pico.video, &t->video, sizeof(Pico.video));
- Pico.m.dirtyPal = 1;
- #ifndef NO_32X
- if (PicoIn.AHW & PAHW_32X) {
- memcpy(&Pico32x, &t->t32x.p32x, sizeof(Pico32x));
- memcpy(Pico32xMem->dram, t->t32x.dram, sizeof(Pico32xMem->dram));
- memcpy(Pico32xMem->pal, t->t32x.pal, sizeof(Pico32xMem->pal));
- Pico32x.dirty_pal = 1;
- }
- #endif
- }
- // vim:shiftwidth=2:ts=2:expandtab
|