X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=pico%2Fstate.c;h=f4e685fb05e3946938e88e619c554fd71ac53049;hb=e42a47e2086e6512519dd86af420363498302f49;hp=11eee6f75a23590300734a8093d25c3d79f45ec9;hpb=27e2627380215963acbf38bf899a4a864446d826;p=picodrive.git diff --git a/pico/state.c b/pico/state.c index 11eee6f..f4e685f 100644 --- a/pico/state.c +++ b/pico/state.c @@ -7,19 +7,15 @@ */ #include "pico_int.h" -#include +#include #include "../cpu/sh2/sh2.h" #include "sound/ym2612.h" +#include "state.h" // sn76496 extern int *sn76496_regs; -typedef size_t (arearw)(void *p, size_t _size, size_t _n, void *file); -typedef size_t (areaeof)(void *file); -typedef int (areaseek)(void *file, long offset, int whence); -typedef int (areaclose)(void *file); - static arearw *areaRead; static arearw *areaWrite; static areaeof *areaEof; @@ -152,10 +148,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.. @@ -177,12 +173,17 @@ typedef enum { CHUNK_32X_EVT, 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, // defined in PicoInt + CHUNK_CARTHW_ = CHUNK_CARTHW, // 64 (defined in PicoInt) } chunk_name_e; -static const char * const chunk_names[] = { +static const char * const chunk_names[CHUNK_DEFAULT_COUNT] = { "INVALID!", "M68K state", "RAM", @@ -238,20 +239,26 @@ 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) { \ + 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) { \ - if (PicoStateProgressCB && name < CHUNK_DEFAULT_COUNT) { \ + 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)) return 1; \ + if (!write_chunk(name, sizeof(buff), &buff, file)) \ + goto out; \ } static int state_save(void *file) @@ -259,7 +266,10 @@ 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); @@ -290,11 +300,16 @@ static int state_save(void *file) if (PicoAHW & 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); - Pico_mcd->m.hint_vector = *(unsigned short *)(Pico_mcd->bios + 0x72); + 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); @@ -303,11 +318,17 @@ 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_RC, Pico_mcd->rot_comp); 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(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); @@ -322,13 +343,13 @@ static int state_save(void *file) sh2_pack(&sh2s[0], cpubuff); CHECKED_WRITE_BUFF(CHUNK_MSH2, cpubuff); - CHECKED_WRITE_BUFF(CHUNK_MSH2_DATA, Pico32xMem->data_array[0]); - CHECKED_WRITE_BUFF(CHUNK_MSH2_PERI, Pico32xMem->sh2_peri_regs[0]); + 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, Pico32xMem->data_array[1]); - CHECKED_WRITE_BUFF(CHUNK_SSH2_PERI, Pico32xMem->sh2_peri_regs[1]); + 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); @@ -339,7 +360,7 @@ static int state_save(void *file) CHECKED_WRITE_BUFF(CHUNK_32XPAL, Pico32xMem->pal); memset(buff, 0, 0x40); - memcpy(buff, event_times, sizeof(event_times)); + memcpy(buff, p32x_event_times, sizeof(p32x_event_times)); CHECKED_WRITE(CHUNK_32X_EVT, 0x40, buff); } #endif @@ -353,7 +374,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; @@ -361,7 +387,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? @@ -369,7 +395,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; \ } @@ -385,14 +410,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; @@ -400,14 +435,22 @@ 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)) 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"); @@ -456,12 +499,39 @@ 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_RC: CHECKED_READ_BUFF(Pico_mcd->rot_comp); 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: @@ -474,10 +544,10 @@ static int state_load(void *file) sh2_unpack(&sh2s[1], buff_sh2); break; - case CHUNK_MSH2_DATA: CHECKED_READ_BUFF(Pico32xMem->data_array[0]); break; - case CHUNK_MSH2_PERI: CHECKED_READ_BUFF(Pico32xMem->sh2_peri_regs[0]); break; - case CHUNK_SSH2_DATA: CHECKED_READ_BUFF(Pico32xMem->data_array[1]); break; - case CHUNK_SSH2_PERI: CHECKED_READ_BUFF(Pico32xMem->sh2_peri_regs[1]); 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; @@ -487,8 +557,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(event_times, buff, sizeof(event_times)); + CHECKED_READ2(0x40, buf); + memcpy(p32x_event_times, buf, sizeof(p32x_event_times)); break; #endif default: @@ -506,24 +576,22 @@ 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) PicoStateLoadedMS(); - if (PicoAHW & PAHW_MCD) - { - PicoMemStateLoaded(); - - if (!(Pico_mcd->s68k_regs[0x36] & 1) && (Pico_mcd->scd.Status_CDC & 1)) - cdda_start_play(); - } - if (PicoAHW & PAHW_32X) Pico32xStateLoaded(1); + if (PicoLoadStateHook != NULL) + PicoLoadStateHook(); + // must unpack 68k and z80 after banks are set up if (!(PicoAHW & PAHW_SMS)) SekUnpackCpu(buff_m68k, 0); @@ -533,10 +601,20 @@ readend: z80_unpack(buff_z80); // due to dep from 68k cycles.. + SekCycleAim = SekCycleCnt; if (PicoAHW & PAHW_32X) Pico32xStateLoaded(0); + if (PicoAHW & PAHW_MCD) + { + SekCycleAimS68k = SekCycleCntS68k; + pcd_state_loaded(); + } - return 0; + retval = 0; + +out: + free(buf); + return retval; } static int state_load_gfx(void *file) @@ -590,19 +668,15 @@ static int state_load_gfx(void *file) } } +out: readend: return 0; } -int PicoState(const char *fname, int is_save) +static int pico_state_internal(void *afile, int is_save) { - void *afile = NULL; int ret; - afile = open_save_file(fname, is_save); - if (afile == NULL) - return -1; - if (is_save) ret = state_save(afile); else { @@ -612,15 +686,39 @@ int PicoState(const char *fname, int is_save) ret = state_load_legacy(afile); } - if (PicoLoadStateHook != NULL) - PicoLoadStateHook(); Pico.m.dirtyPal = 1; + Pico.video.status &= ~(SR_VB | SR_F); } + 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;