X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=pico%2Fstate.c;h=5092ddcbcad57d4802dc33ac6b49793a9f5d5844;hb=7e056c853a0ae81cbfc33135c3802b55eaab5b17;hp=a1ceac2c729b9c8483bea0c9dacad3342eecb98b;hpb=a93a80deda2211dc89ea543841e71cdaf6f65917;p=picodrive.git diff --git a/pico/state.c b/pico/state.c index a1ceac2..5092ddc 100644 --- a/pico/state.c +++ b/pico/state.c @@ -7,7 +7,7 @@ */ #include "pico_int.h" -#include +#include #include "../cpu/sh2/sh2.h" #include "sound/ym2612.h" @@ -78,54 +78,6 @@ static void *open_save_file(const char *fname, int is_save) return afile; } -// legacy savestate loading -#define SCANP(f, x) areaRead(&Pico.x, sizeof(Pico.x), 1, f) - -static int state_load_legacy(void *file) -{ - unsigned char head[32]; - unsigned char cpu[0x60]; - unsigned char cpu_z80[Z80_STATE_SIZE]; - void *ym2612_regs; - int ok; - - memset(&cpu,0,sizeof(cpu)); - memset(&cpu_z80,0,sizeof(cpu_z80)); - - memset(head, 0, sizeof(head)); - areaRead(head, sizeof(head), 1, file); - if (strcmp((char *)head, "Pico") != 0) - return -1; - - elprintf(EL_STATUS, "legacy savestate"); - - // Scan all the memory areas: - SCANP(file, ram); - SCANP(file, vram); - SCANP(file, zram); - SCANP(file, cram); - SCANP(file, vsram); - - // Pack, scan and unpack the cpu data: - areaRead(cpu, sizeof(cpu), 1, file); - SekUnpackCpu(cpu, 0); - - SCANP(file, m); - SCANP(file, video); - - ok = areaRead(cpu_z80, sizeof(cpu_z80), 1, file) == sizeof(cpu_z80); - // do not unpack if we fail to load z80 state - if (!ok) z80_reset(); - else z80_unpack(cpu_z80); - - ym2612_regs = YM2612GetRegs(); - areaRead(sn76496_regs, 28*4, 1, file); - areaRead(ym2612_regs, 0x200+4, 1, file); - ym2612_unpack_state(); - - return 0; -} - // --------------------------------------------------------------------------- typedef enum { @@ -148,10 +100,10 @@ typedef enum { CHUNK_BRAM, CHUNK_GA_REGS, CHUNK_PCM, - CHUNK_CDC, - CHUNK_CDD, // 20 - CHUNK_SCD, - CHUNK_RC, + 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.. @@ -176,6 +128,8 @@ typedef enum { // 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) @@ -237,12 +191,17 @@ static int write_chunk(chunk_name_e name, int len, void *data, void *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 (!write_chunk(name, len, data, file)) return 1; \ + if (data == buf2 && len > CHUNK_LIMIT_W) \ + goto out; \ + if (!write_chunk(name, len, data, file)) \ + goto out; \ } #define CHECKED_WRITE_BUFF(name,buff) { \ @@ -250,7 +209,8 @@ static int write_chunk(chunk_name_e name, int len, void *data, void *file) strncpy(sbuff + 9, chunk_names[name], sizeof(sbuff) - 9); \ PicoStateProgressCB(sbuff); \ } \ - if (!write_chunk(name, sizeof(buff), &buff, file)) return 1; \ + if (!write_chunk(name, sizeof(buff), &buff, file)) \ + goto out; \ } static int state_save(void *file) @@ -258,29 +218,37 @@ static int state_save(void *file) char sbuff[32] = "Saving.. "; unsigned char buff[0x60], buff_z80[Z80_STATE_SIZE]; void *ym2612_regs = YM2612GetRegs(); - int ver = 0x0170; // not really used.. + 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 (!(PicoAHW & PAHW_SMS)) { + 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, Pico.ram); - CHECKED_WRITE_BUFF(CHUNK_VSRAM, Pico.vsram); - CHECKED_WRITE_BUFF(CHUNK_IOPORTS, Pico.ioports); + 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, Pico.vram); - CHECKED_WRITE_BUFF(CHUNK_ZRAM, Pico.zram); - CHECKED_WRITE_BUFF(CHUNK_CRAM, Pico.cram); + 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); CHECKED_WRITE_BUFF(CHUNK_VIDEO, Pico.video); @@ -288,8 +256,12 @@ static int state_save(void *file) CHECKED_WRITE_BUFF(CHUNK_Z80, buff_z80); CHECKED_WRITE(CHUNK_PSG, 28*4, sn76496_regs); - if (PicoAHW & PAHW_MCD) + 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? @@ -304,22 +276,24 @@ static int state_save(void *file) 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_CDD, Pico_mcd->cdd); - CHECKED_WRITE_BUFF(CHUNK_CDC, Pico_mcd->cdc); - CHECKED_WRITE_BUFF(CHUNK_SCD, Pico_mcd->scd); 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); - len = gfx_context_save(buff); - CHECKED_WRITE(CHUNK_CD_GFX, len, buff); + + 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 (PicoAHW & PAHW_32X) + if (PicoIn.AHW & PAHW_32X) { unsigned char cpubuff[SH2_STATE_SIZE]; @@ -358,7 +332,12 @@ static int state_save(void *file) CHECKED_WRITE(chwc->chunk, chwc->size, chwc->ptr); } - return 0; + retval = 0; + +out: + if (buf2 != NULL) + free(buf2); + return retval; } static int g_read_offs = 0; @@ -366,7 +345,7 @@ static int g_read_offs = 0; #define R_ERROR_RETURN(error) \ { \ elprintf(EL_STATUS, "load_state @ %x: " error, g_read_offs); \ - return 1; \ + goto out; \ } // when is eof really set? @@ -374,7 +353,6 @@ static int g_read_offs = 0; if (areaRead(data, 1, len, file) != len) { \ if (len == 1 && areaEof(file)) goto readend; \ R_ERROR_RETURN("areaRead: premature EOF\n"); \ - return 1; \ } \ g_read_offs += len; \ } @@ -390,14 +368,24 @@ static int g_read_offs = 0; #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 buff[0x40]; + unsigned char *buf = NULL; unsigned char chunk; void *ym2612_regs; + int len_check; + int retval = -1; char header[8]; int ver, len; @@ -405,6 +393,10 @@ static int state_load(void *file) 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)) @@ -416,12 +408,13 @@ static int state_load(void *file) 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 && !(PicoAHW & PAHW_MCD)) + 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 && !(PicoAHW & PAHW_32X)) + if (CHUNK_32X_FIRST <= chunk && chunk <= CHUNK_32X_LAST && !(PicoIn.AHW & PAHW_32X)) Pico32xStartup(); switch (chunk) @@ -434,14 +427,14 @@ static int state_load(void *file) CHECKED_READ_BUFF(buff_z80); break; - case CHUNK_RAM: CHECKED_READ_BUFF(Pico.ram); break; - case CHUNK_VRAM: CHECKED_READ_BUFF(Pico.vram); break; - case CHUNK_ZRAM: CHECKED_READ_BUFF(Pico.zram); break; - case CHUNK_CRAM: CHECKED_READ_BUFF(Pico.cram); break; - case CHUNK_VSRAM: CHECKED_READ_BUFF(Pico.vsram); 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); break; - case CHUNK_IOPORTS: CHECKED_READ_BUFF(Pico.ioports); break; + case CHUNK_IOPORTS: CHECKED_READ_BUFF(PicoMem.ioports); break; case CHUNK_PSG: CHECKED_READ2(28*4, sn76496_regs); break; case CHUNK_FM: ym2612_regs = YM2612GetRegs(); @@ -464,19 +457,37 @@ static int state_load(void *file) 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_CDD: CHECKED_READ_BUFF(Pico_mcd->cdd); break; - case CHUNK_CDC: CHECKED_READ_BUFF(Pico_mcd->cdc); break; - case CHUNK_SCD: CHECKED_READ_BUFF(Pico_mcd->scd); break; case CHUNK_MISC_CD: CHECKED_READ_BUFF(Pico_mcd->m); break; case CHUNK_CD_EVT: - CHECKED_READ_BUFF(buff); - memcpy(pcd_event_times, buff, sizeof(pcd_event_times)); + CHECKED_READ2(0x40, buf); + memcpy(pcd_event_times, buf, sizeof(pcd_event_times)); break; case CHUNK_CD_GFX: - CHECKED_READ2(0x18, buff); - gfx_context_load(buff); + 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 @@ -504,8 +515,8 @@ static int state_load(void *file) case CHUNK_32XPAL: CHECKED_READ_BUFF(Pico32xMem->pal); break; case CHUNK_32X_EVT: - CHECKED_READ_BUFF(buff); - memcpy(p32x_event_times, buff, sizeof(p32x_event_times)); + CHECKED_READ2(0x40, buf); + memcpy(p32x_event_times, buf, sizeof(p32x_event_times)); break; #endif default: @@ -523,38 +534,50 @@ static int state_load(void *file) areaSeek(file, len, SEEK_CUR); break; } -breakswitch:; +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 (PicoAHW & PAHW_SMS) + if (PicoIn.AHW & PAHW_SMS) PicoStateLoadedMS(); - if (PicoAHW & PAHW_32X) + if (PicoIn.AHW & PAHW_32X) Pico32xStateLoaded(1); + if (PicoLoadStateHook != NULL) + PicoLoadStateHook(); + // must unpack 68k and z80 after banks are set up - if (!(PicoAHW & PAHW_SMS)) + if (!(PicoIn.AHW & PAHW_SMS)) SekUnpackCpu(buff_m68k, 0); - if (PicoAHW & PAHW_MCD) + if (PicoIn.AHW & PAHW_MCD) SekUnpackCpu(buff_s68k, 1); z80_unpack(buff_z80); // due to dep from 68k cycles.. - SekCycleAim = SekCycleCnt; - if (PicoAHW & PAHW_32X) + Pico.t.m68c_aim = Pico.t.m68c_cnt; + if (PicoIn.AHW & PAHW_32X) Pico32xStateLoaded(0); - if (PicoAHW & PAHW_MCD) + if (PicoIn.AHW & PAHW_MCD) { SekCycleAimS68k = SekCycleCntS68k; pcd_state_loaded(); - - if (!(Pico_mcd->s68k_regs[0x36] & 1) && (Pico_mcd->scd.Status_CDC & 1)) - cdda_start_play(); } - return 0; + 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) @@ -562,7 +585,7 @@ static int state_load_gfx(void *file) int ver, len, found = 0, to_find = 4; char buff[8]; - if (PicoAHW & PAHW_32X) + if (PicoIn.AHW & PAHW_32X) to_find += 2; g_read_offs = 0; @@ -576,14 +599,14 @@ static int state_load_gfx(void *file) 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 && !(PicoAHW & PAHW_MCD)) + 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(Pico.vram); found++; break; - case CHUNK_CRAM: CHECKED_READ_BUFF(Pico.cram); found++; break; - case CHUNK_VSRAM: CHECKED_READ_BUFF(Pico.vsram); found++; break; + 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 @@ -608,6 +631,7 @@ static int state_load_gfx(void *file) } } +out: readend: return 0; } @@ -618,17 +642,8 @@ static int pico_state_internal(void *afile, int is_save) if (is_save) ret = state_save(afile); - else { + else ret = state_load(afile); - if (ret != 0) { - areaSeek(afile, 0, SEEK_SET); - ret = state_load_legacy(afile); - } - - if (PicoLoadStateHook != NULL) - PicoLoadStateHook(); - Pico.m.dirtyPal = 1; - } return ret; } @@ -672,10 +687,10 @@ int PicoStateLoadGfx(const char *fname) if (ret != 0) { // assume legacy areaSeek(afile, 0x10020, SEEK_SET); // skip header and RAM - areaRead(Pico.vram, 1, sizeof(Pico.vram), afile); + areaRead(PicoMem.vram, 1, sizeof(PicoMem.vram), afile); areaSeek(afile, 0x2000, SEEK_CUR); - areaRead(Pico.cram, 1, sizeof(Pico.cram), afile); - areaRead(Pico.vsram, 1, sizeof(Pico.vsram), afile); + 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); } @@ -708,13 +723,13 @@ void *PicoTmpStateSave(void) if (t == NULL) return NULL; - memcpy(t->vram, Pico.vram, sizeof(Pico.vram)); - memcpy(t->cram, Pico.cram, sizeof(Pico.cram)); - memcpy(t->vsram, Pico.vsram, sizeof(Pico.vsram)); + 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->video, &Pico.video, sizeof(Pico.video)); #ifndef NO_32X - if (PicoAHW & PAHW_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)); @@ -730,14 +745,14 @@ void PicoTmpStateRestore(void *data) if (t == NULL) return; - memcpy(Pico.vram, t->vram, sizeof(Pico.vram)); - memcpy(Pico.cram, t->cram, sizeof(Pico.cram)); - memcpy(Pico.vsram, t->vsram, sizeof(Pico.vsram)); + 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(&Pico.video, &t->video, sizeof(Pico.video)); Pico.m.dirtyPal = 1; #ifndef NO_32X - if (PicoAHW & PAHW_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));