// Convenience function for movie.cpp int MDFNSS_SaveFP(gzFile fp, const MDFN_Surface *surface, const MDFN_Rect *DisplayRect, const MDFN_Rect *LineWidths) { StateMem st; memset(&st, 0, sizeof(StateMem)); if(!MDFNSS_SaveSM(&st, 1, 0, surface, DisplayRect, LineWidths)) { if(st.data) free(st.data); return(0); } if(gzwrite(fp, st.data, st.len) != (int32)st.len) { if(st.data) free(st.data); return(0); } if(st.data) free(st.data); return(1); }
size_t retro_serialize_size(void) { MDFNGI *curgame = (MDFNGI*)game; //if (serialize_size) // return serialize_size; if (!curgame->StateAction) { if (log_cb) log_cb(RETRO_LOG_WARN, "[mednafen]: Module %s doesn't support save states.\n", curgame->shortname); return 0; } StateMem st; memset(&st, 0, sizeof(st)); if (!MDFNSS_SaveSM(&st, 0, 0, NULL, NULL, NULL)) { if (log_cb) log_cb(RETRO_LOG_WARN, "[mednafen]: Module %s doesn't support save states.\n", curgame->shortname); return 0; } free(st.data); return serialize_size = st.len; }
// Integrity checking is experimental, and needs work to function properly(in the emulator cores). static int SendIntegrity(void) { StateMem sm; md5_context md5; uint8 digest[16]; memset(&sm, 0, sizeof(StateMem)); // Do not do a raw/data-only state for speed, due to lack of endian and bool conversion. if(!MDFNSS_SaveSM(&sm, 0, false)) { throw MDFN_Error(0, _("Error during save state generation.")); } md5.starts(); md5.update(sm.data, sm.len); md5.finish(digest); free(sm.data); //for(int i = 15; i >= 0; i--) // printf("%02x", digest[i]); //puts(""); SendCommand(MDFNNPCMD_INTEGRITY_RES, 16, digest); return(1); }
bool retro_serialize(void *data, size_t size) { StateMem st; memset(&st, 0, sizeof(st)); st.data = (uint8_t*)data; st.malloced = size; return MDFNSS_SaveSM(&st, 0, 1); }
bool MDFNI_SaveState(const char *fname, const char *suffix, const MDFN_Surface *surface, const MDFN_Rect *DisplayRect, const int32 *LineWidths) noexcept { bool ret = true; try { if(!MDFNGameInfo->StateAction) { throw MDFN_Error(0, _("Module \"%s\" doesn't support save states."), MDFNGameInfo->shortname); } if(MDFNnetplay && (MDFNGameInfo->SaveStateAltersState == true)) { throw MDFN_Error(0, _("Module %s is not compatible with manual state saving during netplay."), MDFNGameInfo->shortname); } // // { MemoryStream st(65536); MDFNSS_SaveSM(&st, false, surface, DisplayRect, LineWidths); // // // GZFileStream gp(fname ? std::string(fname) : MDFN_MakeFName(MDFNMKF_STATE,CurrentState,suffix), GZFileStream::MODE::WRITE, MDFN_GetSettingI("filesys.state_comp_level")); gp.write(st.map(), st.size()); gp.close(); } MDFND_SetStateStatus(NULL); if(!fname && !suffix) { SaveStateStatus[CurrentState] = true; RecentlySavedState = CurrentState; MDFN_DispMessage(_("State %d saved."), CurrentState); } } catch(std::exception &e) { if(!fname && !suffix) MDFN_DispMessage(_("State %d save error: %s"), CurrentState, e.what()); else MDFN_PrintError("%s", e.what()); if(MDFNnetplay) MDFND_NetplayText(e.what(), false); ret = false; } return(ret); }
int MDFNSS_Save(const char *fname, const char *suffix, const MDFN_Surface *surface, const MDFN_Rect *DisplayRect, const MDFN_Rect *LineWidths) { StateMem st; memset(&st, 0, sizeof(StateMem)); if(!MDFNGameInfo->StateAction) { MDFN_DispMessage("Module \"%s\" doesn't support save states.", MDFNGameInfo->shortname); return(0); } if(!MDFNSS_SaveSM(&st, 1, 0, surface, DisplayRect, LineWidths)) { if(st.data) free(st.data); if(!fname && !suffix) MDFN_DispMessage("State %d save error.", CurrentState); return(0); } if(!MDFN_DumpToFile(fname ? fname : MDFN_MakeFName(MDFNMKF_STATE,CurrentState,suffix).c_str(), 6, st.data, st.len)) { SaveStateStatus[CurrentState] = 0; free(st.data); if(!fname && !suffix) MDFN_DispMessage("State %d save error.",CurrentState); return(0); } std::string bleh = MDFN_MakeFName(MDFNMKF_STATE,CurrentState,suffix); SaveStateMovie(bleh); free(st.data); SaveStateStatus[CurrentState] = 1; RecentlySavedState = CurrentState; if(!fname && !suffix) MDFN_DispMessage("State %d saved.",CurrentState); return(1); }
void MDFNMOV_RecordState(void) { gzFile fp = slots[current - 1]; StateMem sm; memset(&sm, 0, sizeof(StateMem)); MDFNSS_SaveSM(&sm, 0, 0); if(MDFN_StateEvilIsRunning()) { smem_putc(&RewindBuffer, MDFNNPCMD_LOADSTATE); smem_putc(&RewindBuffer, sm.len & 0xFF); smem_putc(&RewindBuffer, (sm.len >> 8) & 0xFF); smem_putc(&RewindBuffer, (sm.len >> 16) & 0xFF); smem_putc(&RewindBuffer, (sm.len >> 24) & 0xFF); smem_write(&RewindBuffer, sm.data, sm.len); } else {
static void SendState(void) { StateMem sm; uLongf clen; std::vector<uint8> cbuf; memset(&sm, 0, sizeof(StateMem)); if(!MDFNSS_SaveSM(&sm, 0, 0)) { throw MDFN_Error(0, _("Error during save state generation.")); } clen = sm.len + sm.len / 1000 + 12; cbuf.resize(4 + clen); MDFN_en32lsb(&cbuf[0], sm.len); compress2((Bytef *)&cbuf[0] + 4, &clen, (Bytef *)sm.data, sm.len, 7); free(sm.data); SendCommand(MDFNNPCMD_LOADSTATE, clen + 4, &cbuf[0]); }
int MDFNSS_Save(const char *fname, const char *suffix, uint32 *fb, MDFN_Rect *LineWidths) { StateMem st; memset(&st, 0, sizeof(StateMem)); if(!MDFNSS_SaveSM(&st, 1, 0, fb, LineWidths)) { if(st.data) free(st.data); if(!fname && !suffix) MDFN_DispMessage(_("State %d save error."), CurrentState); return(0); } if(!MDFN_DumpToFile(fname ? fname : MDFN_MakeFName(MDFNMKF_STATE,CurrentState,suffix).c_str(), 6, st.data, st.len)) { SaveStateStatus[CurrentState] = 0; free(st.data); if(!fname && !suffix) MDFN_DispMessage(_("State %d save error."),CurrentState); return(0); } SaveStateMovie((const char*)MDFN_MakeFName(MDFNMKF_STATE,CurrentState,suffix).c_str()); free(st.data); SaveStateStatus[CurrentState] = 1; RecentlySavedState = CurrentState; if(!fname && !suffix) MDFN_DispMessage(_("State %d saved."),CurrentState); return(1); }
size_t retro_serialize_size(void) { //if (serialize_size) // return serialize_size; if (!game->StateAction) { fprintf(stderr, "[mednafen]: Module %s doesn't support save states.\n", game->shortname); return 0; } StateMem st; memset(&st, 0, sizeof(st)); if (!MDFNSS_SaveSM(&st, 0, 1)) { fprintf(stderr, "[mednafen]: Module %s doesn't support save states.\n", game->shortname); return 0; } free(st.data); return serialize_size = st.len; }
int MDFN_StateEvil(int rewind) { if(!EvilEnabled) return(0); if(rewind) { int32 next_bcspos = bcspos; bool NeedDataFlush = FALSE; bcspos--; if(bcspos < 0) bcspos += SRW_NUM; if(!bcs[bcspos].data) bcspos = (bcspos + 1) % SRW_NUM; else NeedDataFlush = TRUE; if(bcs[bcspos].compressed_len) { uint8 *tmp_buf; lzo_uint dst_len = bcs[bcspos].uncompressed_len; tmp_buf = (uint8 *)malloc(bcs[bcspos].uncompressed_len); if(SRWCompressor == SRW_COMPRESSOR_QUICKLZ) dst_len = qlz_decompress((char*)bcs[bcspos].data, tmp_buf, qlz_scratch_decompress); else if(SRWCompressor == SRW_COMPRESSOR_MINILZO) lzo1x_decompress(bcs[bcspos].data, bcs[bcspos].compressed_len, tmp_buf, &dst_len, NULL); else if(SRWCompressor == SRW_COMPRESSOR_BLZ) { dst_len = blz_unpack(bcs[bcspos].data, tmp_buf); } for(uint32 x = 0; x < bcs[bcspos].uncompressed_len && x < bcs[next_bcspos].uncompressed_len; x++) tmp_buf[x] ^= bcs[next_bcspos].data[x]; free(bcs[bcspos].data); bcs[bcspos].data = tmp_buf; bcs[bcspos].compressed_len = 0; } if(NeedDataFlush) { if(bcs[next_bcspos].MovieLove.data) { free(bcs[next_bcspos].MovieLove.data); bcs[next_bcspos].MovieLove.data = NULL; } free(bcs[next_bcspos].data); bcs[next_bcspos].data = NULL; bcs[next_bcspos].compressed_len = 0; bcs[next_bcspos].uncompressed_len = 0; } if(bcs[bcspos].uncompressed_len) { StateMem sm; sm.data = bcs[bcspos].data; sm.loc = 0; sm.initial_malloc = 0; sm.malloced = sm.len = bcs[bcspos].uncompressed_len; MDFNSS_LoadSM(&sm, 0, 1); free(MDFNMOV_GrabRewindJoy().data); return(1); } } else { StateMem sm; int32 prev_bcspos = bcspos; bcspos = (bcspos + 1) % SRW_NUM; if(MDFNMOV_IsRecording()) { if(bcs[bcspos].data && bcs[bcspos].MovieLove.data) { //printf("Force: %d\n", bcspos); MDFNMOV_ForceRecord(&bcs[bcspos].MovieLove); free(bcs[bcspos].MovieLove.data); bcs[bcspos].MovieLove.data = NULL; } } if(bcs[bcspos].data) { free(bcs[bcspos].data); bcs[bcspos].data = NULL; } if(bcs[bcspos].MovieLove.data) { free(bcs[bcspos].MovieLove.data); bcs[bcspos].MovieLove.data = NULL; } memset(&sm, 0, sizeof(sm)); MDFNSS_SaveSM(&sm, 0, 1); bcs[bcspos].data = sm.data; bcs[bcspos].compressed_len = 0; bcs[bcspos].uncompressed_len = sm.len; // Compress the previous save state. if(bcs[prev_bcspos].data) { for(uint32 x = 0; x < bcs[prev_bcspos].uncompressed_len && x < sm.len; x++) bcs[prev_bcspos].data[x] ^= sm.data[x]; if(SRWCompressor == SRW_COMPRESSOR_QUICKLZ) { uint32 dst_len; uint8 *tmp_buf = (uint8 *)malloc(bcs[prev_bcspos].uncompressed_len + 400); dst_len = qlz_compress(bcs[prev_bcspos].data, (char*)tmp_buf, bcs[prev_bcspos].uncompressed_len, qlz_scratch_compress); free(bcs[prev_bcspos].data); bcs[prev_bcspos].data = (uint8 *)realloc(tmp_buf, dst_len); bcs[prev_bcspos].compressed_len = dst_len; } else if(SRWCompressor == SRW_COMPRESSOR_MINILZO) { uint8 workmem[LZO1X_1_MEM_COMPRESS]; uint8 * tmp_buf = (uint8 *)malloc((size_t)(1.10 * bcs[prev_bcspos].uncompressed_len)); lzo_uint dst_len = (lzo_uint)(1.10 * bcs[prev_bcspos].uncompressed_len); lzo1x_1_compress(bcs[prev_bcspos].data, bcs[prev_bcspos].uncompressed_len, tmp_buf, &dst_len, workmem); free(bcs[prev_bcspos].data); bcs[prev_bcspos].data = (uint8 *)realloc(tmp_buf, dst_len); bcs[prev_bcspos].compressed_len = dst_len; } else if(SRWCompressor == SRW_COMPRESSOR_BLZ) { blz_pack_t workmem; uint8 * tmp_buf = (uint8 *)malloc((size_t)(bcs[prev_bcspos].uncompressed_len + blz_pack_extra)); uint32 dst_len = bcs[prev_bcspos].uncompressed_len + blz_pack_extra; dst_len = blz_pack(bcs[prev_bcspos].data, bcs[prev_bcspos].uncompressed_len, tmp_buf, &workmem); free(bcs[prev_bcspos].data); bcs[prev_bcspos].data = (uint8 *)realloc(tmp_buf, dst_len); bcs[prev_bcspos].compressed_len = dst_len; } } if(MDFNMOV_IsRecording()) bcs[bcspos].MovieLove = MDFNMOV_GrabRewindJoy(); } return(0); }