int MDFNI_LoadState(const char *fname, const char *suffix) { if(!MDFNGameInfo->StateAction) return 0; MDFND_SetStateStatus(NULL); /* For network play and movies, be load the state locally, and then save the state to a temporary buffer, and send or record that. This ensures that if an older state is loaded that is missing some information expected in newer save states, desynchronization won't occur(at least not from this ;)). */ if(MDFNSS_Load(fname, suffix)) { if(MDFNnetplay) { NetplaySendState(); } if(MDFNMOV_IsRecording()) MDFNMOV_RecordState(); return 1; } return 0; }
bool MDFNI_LoadState(const char *fname, const char *suffix) noexcept { bool ret = true; try { if(!MDFNGameInfo->StateAction) { throw MDFN_Error(0, _("Module \"%s\" doesn't support save states."), MDFNGameInfo->shortname); } /* For network play and movies, be load the state locally, and then save the state to a temporary buffer, and send or record that. This ensures that if an older state is loaded that is missing some information expected in newer save states, desynchronization won't occur(at least not from this ;)). */ { GZFileStream st(fname ? std::string(fname) : MDFN_MakeFName(MDFNMKF_STATE,CurrentState,suffix), GZFileStream::MODE::READ); uint8 header[32]; uint32 st_len; st.read(header, 32); st_len = MDFN_de32lsb(header + 16 + 4) & 0x7FFFFFFF; if(st_len < 32) throw MDFN_Error(0, _("Save state header length field is bad.")); MemoryStream sm(st_len, -1); memcpy(sm.map(), header, 32); st.read(sm.map() + 32, st_len - 32); MDFNSS_LoadSM(&sm, false); } if(MDFNnetplay) { NetplaySendState(); } if(MDFNMOV_IsRecording()) MDFNMOV_RecordState(); MDFND_SetStateStatus(NULL); if(!fname && !suffix) { SaveStateStatus[CurrentState] = true; MDFN_DispMessage(_("State %d loaded."), CurrentState); } } catch(std::exception &e) { if(!fname && !suffix) MDFN_DispMessage(_("State %d load error: %s"), CurrentState, e.what()); else MDFN_PrintError("%s", e.what()); if(MDFNnetplay) MDFND_NetplayText(e.what(), false); ret = false; } return(ret); }