From 491ee6275466236bdf29e5d0ab26cbff6d8933a1 Mon Sep 17 00:00:00 2001 From: SuuperW Date: Fri, 31 Aug 2018 16:18:21 -0500 Subject: [PATCH 01/13] Clean up movie.cpp LoadFM2. --- desmume/src/movie.cpp | 160 +++++++++++++++++++++++------------------- 1 file changed, 88 insertions(+), 72 deletions(-) diff --git a/desmume/src/movie.cpp b/desmume/src/movie.cpp index 2fab4dd7b..e4b32b43d 100644 --- a/desmume/src/movie.cpp +++ b/desmume/src/movie.cpp @@ -343,9 +343,73 @@ int MovieData::dump(EMUFILE &fp, bool binary) return end-start; } +std::string readUntilWhitespace(EMUFILE &fp) +{ + std::string ret = ""; + while (true) + { + int c = fp.fgetc(); + switch (c) + { + case -1: + case ' ': + case '\t': + case '\r': + case '\n': + return ret; + default: + ret += c; + break; + } + } +} +std::string readUntilNewline(EMUFILE &fp) +{ + std::string ret = ""; + while (true) + { + int c = fp.fgetc(); + switch (c) + { + case -1: + case '\r': + case '\n': + return ret; + default: + ret += c; + break; + } + } +} +void readUntilNotWhitespace(EMUFILE &fp) +{ + while (true) + { + int c = fp.fgetc(); + switch (c) + { + case -1: + return; + case ' ': + case '\t': + case '\r': + case '\n': + break; + default: + fp.unget(); + return; + } + } +} //yuck... another custom text parser. bool LoadFM2(MovieData &movieData, EMUFILE &fp, int size, bool stopAfterHeader) { + int endOfMovie; + if (size == INT_MAX) + endOfMovie = fp.size(); + else + endOfMovie = fp.ftell() + size; + //TODO - start with something different. like 'desmume movie version 1" int curr = fp.ftell(); @@ -360,85 +424,37 @@ bool LoadFM2(MovieData &movieData, EMUFILE &fp, int size, bool stopAfterHeader) std::string key,value; enum { - NEWLINE, KEY, SEPARATOR, VALUE, RECORD, COMMENT + NEWLINE, KEY, SEPARATOR, VALUE, RECORD } state = NEWLINE; - bool bail = false; - for(;;) + while (fp.ftell() < endOfMovie) { - bool iswhitespace, isrecchar, isnewline; - int c; - if(size--<=0) goto bail; - c = fp.fgetc(); - if(c == -1) - goto bail; - iswhitespace = (c==' '||c=='\t'); - isrecchar = (c=='|'); - isnewline = (c==10||c==13); - if(isrecchar && movieData.binaryFlag && !stopAfterHeader) + readUntilNotWhitespace(fp); + int c = fp.fgetc(); + if (c == -1) + break; + + bool isRecord = c == '|'; + if(isRecord && movieData.binaryFlag && !stopAfterHeader) { - LoadFM2_binarychunk(movieData, fp, size); + LoadFM2_binarychunk(movieData, fp, endOfMovie - fp.ftell()); return true; } - switch(state) + + if (isRecord) { - case NEWLINE: - if(isnewline) goto done; - if(iswhitespace) goto done; - if(isrecchar) - goto dorecord; - //must be a key - key = ""; - value = ""; - goto dokey; - break; - case RECORD: - { - dorecord: - if (stopAfterHeader) return true; - int currcount = movieData.records.size(); - movieData.records.resize(currcount+1); - int preparse = fp.ftell(); - movieData.records[currcount].parse(fp); - int postparse = fp.ftell(); - size -= (postparse-preparse); - state = NEWLINE; - break; - } - - case KEY: - dokey: //dookie - state = KEY; - if(iswhitespace) goto doseparator; - if(isnewline) goto commit; - key += c; - break; - case SEPARATOR: - doseparator: - state = SEPARATOR; - if(isnewline) goto commit; - if(!iswhitespace) goto dovalue; - break; - case VALUE: - dovalue: - state = VALUE; - if(isnewline) goto commit; - value += c; - break; - case COMMENT: - default: - break; + if (stopAfterHeader) return true; + int currcount = movieData.records.size(); + movieData.records.resize(currcount + 1); + movieData.records[currcount].parse(fp); + } + else // key value + { + fp.unget(); + key = readUntilWhitespace(fp); + readUntilNotWhitespace(fp); + value = readUntilNewline(fp); + movieData.installValue(key, value); } - goto done; - - bail: - bail = true; - if(state == VALUE) goto commit; - goto done; - commit: - movieData.installValue(key,value); - state = NEWLINE; - done: ; - if(bail) break; } return true; From a5d843e3617b3d2587ccedeb4dda2f3e905f4f23 Mon Sep 17 00:00:00 2001 From: SuuperW Date: Fri, 31 Aug 2018 21:13:16 -0500 Subject: [PATCH 02/13] Rework MovieData::installValue to separate code for each key/value and to avoid using a long if else if chain. --- desmume/src/movie.cpp | 101 +++++++++++++++++------------------------- desmume/src/movie.h | 38 ++++++++++++---- 2 files changed, 71 insertions(+), 68 deletions(-) diff --git a/desmume/src/movie.cpp b/desmume/src/movie.cpp index e4b32b43d..d02a072e2 100644 --- a/desmume/src/movie.cpp +++ b/desmume/src/movie.cpp @@ -211,68 +211,49 @@ void MovieData::truncateAt(int frame) records.resize(frame); } +void MovieData::installRomChecksum(std::string& val) +{ + // TODO: The current implementation of reading the checksum doesn't work correctly, and can + // cause crashes when the MovieData object is deallocated. (This is caused by StringToBytes() + // overrunning romChecksum into romSerial, making romSerial undefined.) Set romChecksum to + // some dummy value for now to prevent crashing. This is okay, since romChecksum isn't actually + // used in practice at this time. - rogerman, 2012/08/24 + //StringToBytes(val,&romChecksum,MD5DATA::size); + + romChecksum = 0; +} +void MovieData::installRtcStart(std::string& val) +{ + // sloppy format check and parse + const char *validFormatStr = "####-##-##T##:##:##Z"; + bool validFormat = true; + for (int i = 0; validFormatStr[i] != '\0'; i++) { + if (validFormatStr[i] != val[i] && + !(validFormatStr[i] == '#' && isdigit(val[i]))) { + validFormat = false; + break; + } + } + if (validFormat) { + const char *s = val.data(); + int year = atoi(&s[0]); + int mon = atoi(&s[5]); + int day = atoi(&s[8]); + int hour = atoi(&s[11]); + int min = atoi(&s[14]); + int sec = atoi(&s[17]); + rtcStart = DateTime(year, mon, day, hour, min, sec); + } +} +void MovieData::installComment(std::string& val) { comments.push_back(mbstowcs(val)); } +void MovieData::installSavestate(std::string& val) { BinaryDataFromString(val, &this->savestate); } +void MovieData::installSram(std::string& val) { BinaryDataFromString(val, &this->sram); } + void MovieData::installValue(std::string& key, std::string& val) { - //todo - use another config system, or drive this from a little data structure. because this is gross - if(key == "version") - installInt(val,version); - else if(key == "emuVersion") - installInt(val,emuVersion); - else if(key == "rerecordCount") - installInt(val,rerecordCount); - else if(key == "romFilename") - romFilename = val; - else if(key == "romChecksum") { - // TODO: The current implementation of reading the checksum doesn't work correctly, and can - // cause crashes when the MovieData object is deallocated. (This is caused by StringToBytes() - // overrunning romChecksum into romSerial, making romSerial undefined.) Set romChecksum to - // some dummy value for now to prevent crashing. This is okay, since romChecksum isn't actually - // used in practice at this time. - rogerman, 2012/08/24 - //StringToBytes(val,&romChecksum,MD5DATA::size); - - romChecksum = 0; - } - else if(key == "romSerial") - romSerial = val; - else if(key == "guid") - guid = Desmume_Guid::fromString(val); - else if(key == "rtcStart") { - // sloppy format check and parse - const char *validFormatStr = "####-##-##T##:##:##Z"; - bool validFormat = true; - for (int i = 0; validFormatStr[i] != '\0'; i++) { - if (validFormatStr[i] != val[i] && - !(validFormatStr[i] == '#' && isdigit(val[i]))) { - validFormat = false; - break; - } - } - if (validFormat) { - const char *s = val.data(); - int year = atoi(&s[0]); - int mon = atoi(&s[5]); - int day = atoi(&s[8]); - int hour = atoi(&s[11]); - int min = atoi(&s[14]); - int sec = atoi(&s[17]); - rtcStart = DateTime(year,mon,day,hour,min,sec); - } - } - else if(key == "rtcStartNew") { - DateTime::TryParse(val.c_str(),rtcStart); - } - else if(key == "comment") - comments.push_back(mbstowcs(val)); - else if(key == "binary") - installBool(val,binaryFlag); - else if(key == "savestate") - { - BinaryDataFromString(val, &this->savestate); - } - else if(key == "sram") - { - BinaryDataFromString(val, &this->sram); - } + ivm method = installValueMap[key]; + if (method != NULL) + (this->*method)(val); } diff --git a/desmume/src/movie.h b/desmume/src/movie.h index 67ede7ba3..eae959ea7 100644 --- a/desmume/src/movie.h +++ b/desmume/src/movie.h @@ -198,15 +198,37 @@ public: //void TryDumpIncremental(); private: - void installInt(std::string& val, int& var) - { - var = atoi(val.c_str()); - } + void installVersion(std::string& val) { version = atoi(val.c_str()); } + void installEmuVersion(std::string& val) { emuVersion = atoi(val.c_str()); } + void installRerecordCount(std::string& val) { rerecordCount = atoi(val.c_str()); } + void installRomFilename(std::string& val) { romFilename = val; } + void installRomSerial(std::string& val) { romSerial = val; } + void installGuid(std::string& val) { guid = Desmume_Guid::fromString(val); } + void installRtcStartNew(std::string& val) { DateTime::TryParse(val.c_str(), rtcStart); } + void installBinary(std::string& val) { binaryFlag = atoi(val.c_str()) != 0; } + + void installRomChecksum(std::string& val); + void installRtcStart(std::string& val); + void installComment(std::string& val); + void installSavestate(std::string& val); + void installSram(std::string& val); - void installBool(std::string& val, bool& var) - { - var = atoi(val.c_str())!=0; - } + typedef void(MovieData::* ivm)(std::string&); + std::map installValueMap = { + {"version", &MovieData::installVersion}, + {"emuVersion", &MovieData::installEmuVersion}, + {"rerecordCount", &MovieData::installRerecordCount}, + {"romFilename", &MovieData::installRomFilename}, + {"romChecksum", &MovieData::installRomChecksum}, + {"romSerial", &MovieData::installRomSerial}, + {"guid", &MovieData::installGuid}, + {"rtcStart", &MovieData::installRtcStart}, + {"rtcStartNew", &MovieData::installRtcStartNew}, + {"comment", &MovieData::installComment}, + {"binary", &MovieData::installBinary}, + {"savestate", &MovieData::installSavestate}, + {"sram", &MovieData::installSram} + }; }; extern int currFrameCounter; From 10dc63abcaff85791a8eccf593ade252614677ee Mon Sep 17 00:00:00 2001 From: SuuperW Date: Fri, 31 Aug 2018 21:29:37 -0500 Subject: [PATCH 03/13] Some more cleanup of movie.cpp LoadFM2 --- desmume/src/movie.cpp | 52 ++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/desmume/src/movie.cpp b/desmume/src/movie.cpp index d02a072e2..710d63fa2 100644 --- a/desmume/src/movie.cpp +++ b/desmume/src/movie.cpp @@ -391,53 +391,49 @@ bool LoadFM2(MovieData &movieData, EMUFILE &fp, int size, bool stopAfterHeader) else endOfMovie = fp.ftell() + size; - //TODO - start with something different. like 'desmume movie version 1" - int curr = fp.ftell(); - //movie must start with "version 1" + //TODO - start with something different. like 'desmume movie version 1" char buf[9]; - curr = fp.ftell(); - fp.fread(buf,9); - fp.fseek(curr, SEEK_SET); + fp.fread(buf, 9); + fp.fseek(-9, SEEK_CUR); // if(fp->fail()) return false; - if (memcmp(buf,"version 1",9)) + if (memcmp(buf, "version 1", 9)) return false; - std::string key,value; - enum { - NEWLINE, KEY, SEPARATOR, VALUE, RECORD - } state = NEWLINE; while (fp.ftell() < endOfMovie) { readUntilNotWhitespace(fp); int c = fp.fgetc(); - if (c == -1) - break; - - bool isRecord = c == '|'; - if(isRecord && movieData.binaryFlag && !stopAfterHeader) + // This will be the case if there is a newline at the end of the file. + if (c == -1) break; + else if (c == '|') { - LoadFM2_binarychunk(movieData, fp, endOfMovie - fp.ftell()); - return true; - } - - if (isRecord) - { - if (stopAfterHeader) return true; - int currcount = movieData.records.size(); - movieData.records.resize(currcount + 1); - movieData.records[currcount].parse(fp); + if (stopAfterHeader) break; + else if (movieData.binaryFlag) + { + LoadFM2_binarychunk(movieData, fp, endOfMovie - fp.ftell()); + break; + } + else + { + int currcount = movieData.records.size(); + movieData.records.resize(currcount + 1); + movieData.records[currcount].parse(fp); + } } else // key value { fp.unget(); - key = readUntilWhitespace(fp); + std::string key = readUntilWhitespace(fp); readUntilNotWhitespace(fp); - value = readUntilNewline(fp); + std::string value = readUntilNewline(fp); movieData.installValue(key, value); } } + // just in case readUntilNotWhitespace read past the limit set by size parameter + fp.fseek(endOfMovie, SEEK_SET); + return true; } From bd299672a1f3fa11c7b9d1170eecb00e632ee712 Mon Sep 17 00:00:00 2001 From: SuuperW Date: Fri, 31 Aug 2018 23:02:47 -0500 Subject: [PATCH 04/13] Save jitBlockSize to movie files --- desmume/src/movie.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/desmume/src/movie.cpp b/desmume/src/movie.cpp index 710d63fa2..e340d1f87 100644 --- a/desmume/src/movie.cpp +++ b/desmume/src/movie.cpp @@ -268,13 +268,12 @@ int MovieData::dump(EMUFILE &fp, bool binary) fp.fprintf("romChecksum %s\n", u32ToHexString(gameInfo.crc).c_str()); fp.fprintf("romSerial %s\n", romSerial.c_str()); fp.fprintf("guid %s\n", guid.toString().c_str()); - fp.fprintf("useExtBios %d\n", CommonSettings.UseExtBIOS?1:0); - fp.fprintf("advancedTiming %d\n", CommonSettings.advanced_timing?1:0); + fp.fprintf("useExtBios %d\n", CommonSettings.UseExtBIOS?1:0); // TODO: include bios file data, not just a flag saying something was used if (CommonSettings.UseExtBIOS) fp.fprintf("swiFromBios %d\n", CommonSettings.SWIFromBIOS?1:0); - fp.fprintf("useExtFirmware %d\n", CommonSettings.UseExtFirmware?1:0); + fp.fprintf("useExtFirmware %d\n", CommonSettings.UseExtFirmware?1:0); // TODO: include firmware file data, not just a flag saying something was used if (CommonSettings.UseExtFirmware) { @@ -296,6 +295,9 @@ int MovieData::dump(EMUFILE &fp, bool binary) fp.fprintf("firmLanguage %d\n", CommonSettings.fw_config.language); } + fp.fprintf("advancedTiming %d\n", CommonSettings.advanced_timing?1:0); + fp.fprintf("jitBlockSize %d\n", CommonSettings.use_jit ? CommonSettings.jit_max_block_size : 0); + fp.fprintf("rtcStartNew %s\n", rtcStart.ToString().c_str()); for (u32 i = 0; i < comments.size(); i++) From e83ec89578e03cc72cc4728ad37a5a5583ffbcaf Mon Sep 17 00:00:00 2001 From: SuuperW Date: Sat, 1 Sep 2018 11:09:04 -0500 Subject: [PATCH 05/13] Loading a movie now sets emulation/firmware settings. --- desmume/src/movie.cpp | 47 ++++++++++++++++++++++++++++++++++++++----- desmume/src/movie.h | 35 +++++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 6 deletions(-) diff --git a/desmume/src/movie.cpp b/desmume/src/movie.cpp index e340d1f87..b5cc5f1e3 100644 --- a/desmume/src/movie.cpp +++ b/desmume/src/movie.cpp @@ -486,7 +486,47 @@ void FCEUI_StopMovie() freshMovie = false; } +static void LoadSettingsFromMovie(MovieData movieData) +{ + if (currMovieData.useExtBios != -1) + CommonSettings.UseExtBIOS = currMovieData.useExtBios; + if (currMovieData.useExtFirmware != -1) + CommonSettings.UseExtFirmware = currMovieData.useExtFirmware; + if (!CommonSettings.UseExtFirmware) + { + if (currMovieData.firmNickname != "") + { + CommonSettings.fw_config.nickname_len = currMovieData.firmNickname.length() > MAX_FW_NICKNAME_LENGTH ? MAX_FW_NICKNAME_LENGTH : currMovieData.firmNickname.length(); + for (int i = 0; i < CommonSettings.fw_config.nickname_len; i++) + CommonSettings.fw_config.nickname[i] = currMovieData.firmNickname[i]; + } + if (currMovieData.firmMessage != "") + { + CommonSettings.fw_config.message_len = currMovieData.firmMessage.length() > MAX_FW_MESSAGE_LENGTH ? MAX_FW_MESSAGE_LENGTH : currMovieData.firmMessage.length(); + for (int i = 0; i < CommonSettings.fw_config.message_len; i++) + CommonSettings.fw_config.message[i] = currMovieData.firmMessage[i]; + } + if (currMovieData.firmFavColour != -1) + CommonSettings.fw_config.fav_colour = currMovieData.firmFavColour; + if (currMovieData.firmBirthMonth != -1) + CommonSettings.fw_config.birth_month = currMovieData.firmBirthMonth; + if (currMovieData.firmBirthDay != -1) + CommonSettings.fw_config.birth_day = currMovieData.firmBirthDay; + if (currMovieData.firmLanguage != -1) + CommonSettings.fw_config.language = currMovieData.firmLanguage; + + // reset firmware (some games can write to it) + NDS_CreateDummyFirmware(&CommonSettings.fw_config); + } + if (currMovieData.advancedTiming != -1) + CommonSettings.advanced_timing = currMovieData.advancedTiming; + if (currMovieData.jitBlockSize != -1) + { + CommonSettings.use_jit = currMovieData.jitBlockSize != 0; + CommonSettings.jit_max_block_size = currMovieData.jitBlockSize; + } +} //begin playing an existing movie const char* _CDECL_ FCEUI_LoadMovie(const char *fname, bool _read_only, bool tasedit, int _pauseframe) { @@ -547,11 +587,8 @@ const char* _CDECL_ FCEUI_LoadMovie(const char *fname, bool _read_only, bool tas //fully reload the game to reinitialize everything before playing any movie //poweron(true); - // reset firmware (some games can write to it) - if (!CommonSettings.UseExtFirmware) - { - NDS_CreateDummyFirmware(&CommonSettings.fw_config); - } + // set emulation/firmware settings + LoadSettingsFromMovie(currMovieData); NDS_Reset(); diff --git a/desmume/src/movie.h b/desmume/src/movie.h index eae959ea7..08acc376b 100644 --- a/desmume/src/movie.h +++ b/desmume/src/movie.h @@ -155,6 +155,19 @@ public: //was the frame data stored in binary? bool binaryFlag; + int useExtBios = -1; + int useExtFirmware = -1; + + std::string firmNickname = ""; + std::string firmMessage = ""; + int firmFavColour = -1; + int firmBirthMonth = -1; + int firmBirthDay = -1; + int firmLanguage = -1; + + int advancedTiming = -1; + int jitBlockSize = -1; + int getNumRecords() { return records.size(); } class TDictionary : public std::map @@ -206,7 +219,17 @@ private: void installGuid(std::string& val) { guid = Desmume_Guid::fromString(val); } void installRtcStartNew(std::string& val) { DateTime::TryParse(val.c_str(), rtcStart); } void installBinary(std::string& val) { binaryFlag = atoi(val.c_str()) != 0; } - + void installUseExtBios(std::string& val) { useExtBios = atoi(val.c_str()) != 0; } + void installUseExtFirmware(std::string& val) { useExtFirmware = atoi(val.c_str()) != 0; } + void installFirmNickname(std::string& val) { firmNickname = val; } + void installFirmMessage(std::string& val) { firmMessage = val; } + void installFirmFavColour(std::string& val) { firmFavColour = atoi(val.c_str()); } + void installFirmBirthMonth(std::string& val) { firmBirthMonth = atoi(val.c_str()); } + void installFirmBirthDay(std::string& val) { firmBirthDay = atoi(val.c_str()); } + void installFirmLanguage(std::string& val) { firmLanguage = atoi(val.c_str()); } + void installAdvancedTiming(std::string& val) { advancedTiming = atoi(val.c_str()) != 0; } + void installJitBlockSize(std::string& val) { jitBlockSize = atoi(val.c_str()); } + void installRomChecksum(std::string& val); void installRtcStart(std::string& val); void installComment(std::string& val); @@ -226,6 +249,16 @@ private: {"rtcStartNew", &MovieData::installRtcStartNew}, {"comment", &MovieData::installComment}, {"binary", &MovieData::installBinary}, + {"useExtBios", &MovieData::installUseExtBios}, + {"useExtFirmware", &MovieData::installUseExtBios}, + {"firmNickname", &MovieData::installFirmNickname}, + {"firmMessage", &MovieData::installFirmMessage}, + {"firmFavColour", &MovieData::installFirmFavColour}, + {"firmBirthMonth", &MovieData::installFirmBirthMonth}, + {"firmBirthDay", &MovieData::installFirmBirthDay}, + {"firmLanguage", &MovieData::installFirmLanguage}, + {"advancedTiming", &MovieData::installAdvancedTiming}, + {"jitBlockSize", &MovieData::installJitBlockSize}, {"savestate", &MovieData::installSavestate}, {"sram", &MovieData::installSram} }; From 4a844b2394f6c830b64e18e03fb3e11049197a31 Mon Sep 17 00:00:00 2001 From: SuuperW Date: Sat, 1 Sep 2018 12:03:31 -0500 Subject: [PATCH 06/13] bugfix from last commit --- desmume/src/movie.cpp | 54 +++++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/desmume/src/movie.cpp b/desmume/src/movie.cpp index b5cc5f1e3..d0d812881 100644 --- a/desmume/src/movie.cpp +++ b/desmume/src/movie.cpp @@ -488,43 +488,51 @@ void FCEUI_StopMovie() static void LoadSettingsFromMovie(MovieData movieData) { - if (currMovieData.useExtBios != -1) - CommonSettings.UseExtBIOS = currMovieData.useExtBios; - if (currMovieData.useExtFirmware != -1) - CommonSettings.UseExtFirmware = currMovieData.useExtFirmware; + if (movieData.useExtBios != -1) + CommonSettings.UseExtBIOS = movieData.useExtBios; + if (movieData.useExtFirmware != -1) + CommonSettings.UseExtFirmware = movieData.useExtFirmware; if (!CommonSettings.UseExtFirmware) { - if (currMovieData.firmNickname != "") + if (movieData.firmNickname != "") { - CommonSettings.fw_config.nickname_len = currMovieData.firmNickname.length() > MAX_FW_NICKNAME_LENGTH ? MAX_FW_NICKNAME_LENGTH : currMovieData.firmNickname.length(); + CommonSettings.fw_config.nickname_len = movieData.firmNickname.length() > MAX_FW_NICKNAME_LENGTH ? MAX_FW_NICKNAME_LENGTH : movieData.firmNickname.length(); for (int i = 0; i < CommonSettings.fw_config.nickname_len; i++) - CommonSettings.fw_config.nickname[i] = currMovieData.firmNickname[i]; + CommonSettings.fw_config.nickname[i] = movieData.firmNickname[i]; } - if (currMovieData.firmMessage != "") + if (movieData.firmMessage != "") { - CommonSettings.fw_config.message_len = currMovieData.firmMessage.length() > MAX_FW_MESSAGE_LENGTH ? MAX_FW_MESSAGE_LENGTH : currMovieData.firmMessage.length(); + CommonSettings.fw_config.message_len = movieData.firmMessage.length() > MAX_FW_MESSAGE_LENGTH ? MAX_FW_MESSAGE_LENGTH : movieData.firmMessage.length(); for (int i = 0; i < CommonSettings.fw_config.message_len; i++) - CommonSettings.fw_config.message[i] = currMovieData.firmMessage[i]; + CommonSettings.fw_config.message[i] = movieData.firmMessage[i]; } - if (currMovieData.firmFavColour != -1) - CommonSettings.fw_config.fav_colour = currMovieData.firmFavColour; - if (currMovieData.firmBirthMonth != -1) - CommonSettings.fw_config.birth_month = currMovieData.firmBirthMonth; - if (currMovieData.firmBirthDay != -1) - CommonSettings.fw_config.birth_day = currMovieData.firmBirthDay; - if (currMovieData.firmLanguage != -1) - CommonSettings.fw_config.language = currMovieData.firmLanguage; + if (movieData.firmFavColour != -1) + CommonSettings.fw_config.fav_colour = movieData.firmFavColour; + if (movieData.firmBirthMonth != -1) + CommonSettings.fw_config.birth_month = movieData.firmBirthMonth; + if (movieData.firmBirthDay != -1) + CommonSettings.fw_config.birth_day = movieData.firmBirthDay; + if (movieData.firmLanguage != -1) + CommonSettings.fw_config.language = movieData.firmLanguage; // reset firmware (some games can write to it) NDS_CreateDummyFirmware(&CommonSettings.fw_config); } - if (currMovieData.advancedTiming != -1) - CommonSettings.advanced_timing = currMovieData.advancedTiming; - if (currMovieData.jitBlockSize != -1) + if (movieData.advancedTiming != -1) + CommonSettings.advanced_timing = movieData.advancedTiming; + if (movieData.jitBlockSize != -1) { - CommonSettings.use_jit = currMovieData.jitBlockSize != 0; - CommonSettings.jit_max_block_size = currMovieData.jitBlockSize; + CommonSettings.use_jit = movieData.jitBlockSize != 0; + CommonSettings.jit_max_block_size = movieData.jitBlockSize; + } +} +void UnloadMovieEmulationSettings() +{ + if (&oldSettings) + { + LoadSettingsFromMovie(oldSettings); + oldSettings = NULL; } } //begin playing an existing movie From 80047bff9155beadcf1e739c00e225f8272403b2 Mon Sep 17 00:00:00 2001 From: SuuperW Date: Sat, 1 Sep 2018 12:05:21 -0500 Subject: [PATCH 07/13] When closing or rebooting a ROM, reset emulation settings that were set by a movie. --- desmume/src/NDSSystem.cpp | 4 ++++ desmume/src/movie.cpp | 33 +++++++++++++++++++++++++++++++-- desmume/src/movie.h | 4 ++-- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/desmume/src/NDSSystem.cpp b/desmume/src/NDSSystem.cpp index f3dc0254b..b20e89994 100755 --- a/desmume/src/NDSSystem.cpp +++ b/desmume/src/NDSSystem.cpp @@ -781,6 +781,7 @@ int NDS_LoadROM(const char *filename, const char *physicalName, const char *logi cheats->init(buf); } + //UnloadMovieEmulationSettings(); called in NDS_Reset() NDS_Reset(); return ret; @@ -790,6 +791,7 @@ void NDS_FreeROM(void) { FCEUI_StopMovie(); gameInfo.closeROM(); + UnloadMovieEmulationSettings(); } void NDS_Sleep() { nds.sleeping = TRUE; } @@ -2567,6 +2569,8 @@ bool NDS_FakeBoot() bool _HACK_DONT_STOPMOVIE = false; void NDS_Reset() { + UnloadMovieEmulationSettings(); + //reload last paths if needed if(!gameInfo.reader) { diff --git a/desmume/src/movie.cpp b/desmume/src/movie.cpp index d0d812881..bf14bd107 100644 --- a/desmume/src/movie.cpp +++ b/desmume/src/movie.cpp @@ -66,6 +66,10 @@ bool movie_readonly = true; char curMovieFilename[512] = {0}; MovieData currMovieData; +MovieData oldSettings = NULL; +// Loading a movie calls NDS_Reset, which calls UnloadMovieEmulationSettings. Don't unload settings on that call. +bool firstReset = false; + int currRerecordCount; bool movie_reset_command = false; //-------------- @@ -195,7 +199,7 @@ DateTime FCEUI_MovieGetRTCDefault() return DateTime(2009,1,1,0,0,0); } -MovieData::MovieData() +MovieData::MovieData(bool fromCurrentSettings) : version(MOVIE_VERSION) , emuVersion(EMU_DESMUME_VERSION_NUMERIC()) , romChecksum(0) @@ -203,6 +207,28 @@ MovieData::MovieData() , binaryFlag(false) , rtcStart(FCEUI_MovieGetRTCDefault()) { + if (fromCurrentSettings) + { + useExtBios = CommonSettings.UseExtBIOS; + if (useExtFirmware != -1) + useExtFirmware = CommonSettings.UseExtFirmware; + if (!CommonSettings.UseExtFirmware) + { + firmNickname.resize(CommonSettings.fw_config.nickname_len); + for (int i = 0; i < CommonSettings.fw_config.nickname_len; i++) + firmNickname[i] = CommonSettings.fw_config.nickname[i]; + firmMessage.resize(CommonSettings.fw_config.message_len); + for (int i = 0; i < CommonSettings.fw_config.message_len; i++) + firmMessage[i] = CommonSettings.fw_config.message[i]; + + firmFavColour = CommonSettings.fw_config.fav_colour; + firmBirthMonth = CommonSettings.fw_config.birth_month; + firmBirthDay = CommonSettings.fw_config.birth_day; + firmLanguage = CommonSettings.fw_config.language; + } + advancedTiming = CommonSettings.advanced_timing; + jitBlockSize = CommonSettings.use_jit ? CommonSettings.jit_max_block_size : 0; + } } void MovieData::truncateAt(int frame) @@ -529,7 +555,7 @@ static void LoadSettingsFromMovie(MovieData movieData) } void UnloadMovieEmulationSettings() { - if (&oldSettings) + if (&oldSettings && !firstReset) { LoadSettingsFromMovie(oldSettings); oldSettings = NULL; @@ -596,9 +622,12 @@ const char* _CDECL_ FCEUI_LoadMovie(const char *fname, bool _read_only, bool tas //poweron(true); // set emulation/firmware settings + oldSettings = MovieData(true); LoadSettingsFromMovie(currMovieData); + firstReset = true; NDS_Reset(); + firstReset = false; ////WE NEED TO LOAD A SAVESTATE //if(currMovieData.savestate.size() != 0) diff --git a/desmume/src/movie.h b/desmume/src/movie.h index 08acc376b..84d9b1e40 100644 --- a/desmume/src/movie.h +++ b/desmume/src/movie.h @@ -132,8 +132,7 @@ private: class MovieData { public: - MovieData(); - + MovieData(bool fromCurrentSettings = false); int version; int emuVersion; @@ -273,6 +272,7 @@ extern bool movie_reset_command; bool FCEUI_MovieGetInfo(EMUFILE &fp, MOVIE_INFO &info, bool skipFrameCount); void FCEUI_SaveMovie(const char *fname, std::wstring author, int flag, std::string sramfname, const DateTime &rtcstart); const char* _CDECL_ FCEUI_LoadMovie(const char *fname, bool _read_only, bool tasedit, int _pauseframe); // returns NULL on success, errmsg on failure +void UnloadMovieEmulationSettings(); void FCEUI_StopMovie(); void FCEUMOV_AddInputState(); void FCEUMOV_HandlePlayback(); From 3645ff4e77eef79f24e4eecbb353e1e901acb31b Mon Sep 17 00:00:00 2001 From: SuuperW Date: Sat, 1 Sep 2018 12:34:17 -0500 Subject: [PATCH 08/13] Alert the user when opening emulation/firmware settings while they are set by a movie. --- desmume/src/frontend/windows/main.cpp | 12 +++++++++++- desmume/src/movie.cpp | 13 +++++++++---- desmume/src/movie.h | 1 + 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/desmume/src/frontend/windows/main.cpp b/desmume/src/frontend/windows/main.cpp index e96a9358e..f709e07c0 100755 --- a/desmume/src/frontend/windows/main.cpp +++ b/desmume/src/frontend/windows/main.cpp @@ -4817,6 +4817,11 @@ DOKEYDOWN: RunConfig(CONFIGSCREEN_HOTKEY); return 0; case IDM_FIRMSETTINGS: + if (AreMovieEmulationSettingsActive()) + { + MessageBox(hwnd, "The current settings have been set by a movie. Reset or unload the current game if you want to restore your saved settings.\n\n" + "If you make changes here, the new settings will overwrite your currently saved settings.", "Movie Settings Active", MB_OK); + } RunConfig(CONFIGSCREEN_FIRMWARE); return 0; case IDM_SOUNDSETTINGS: @@ -4826,6 +4831,11 @@ DOKEYDOWN: RunConfig(CONFIGSCREEN_WIFI); return 0; case IDM_EMULATIONSETTINGS: + if (AreMovieEmulationSettingsActive()) + { + MessageBox(hwnd, "The current settings have been set by a movie. Reset or unload the current game if you want to restore your saved settings.\n\n" + "If you make changes here (whether you reset now or not), the new settings will overwrite your currently saved settings.", "Movie Settings Active", MB_OK); + } RunConfig(CONFIGSCREEN_EMULATION); return 0; case IDM_MICROPHONESETTINGS: @@ -5874,7 +5884,7 @@ LRESULT CALLBACK EmulationSettingsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, L if(romloaded) val = MessageBox(hDlg, "The current ROM needs to be reset to apply changes.\nReset now ?", "DeSmuME", (MB_YESNO | MB_ICONQUESTION)); - + UnloadMovieEmulationSettings(); CommonSettings.UseExtBIOS = IsDlgCheckboxChecked(hDlg, IDC_USEEXTBIOS); cur = GetDlgItem(hDlg, IDC_ARM9BIOS); diff --git a/desmume/src/movie.cpp b/desmume/src/movie.cpp index bf14bd107..1d005c295 100644 --- a/desmume/src/movie.cpp +++ b/desmume/src/movie.cpp @@ -66,7 +66,7 @@ bool movie_readonly = true; char curMovieFilename[512] = {0}; MovieData currMovieData; -MovieData oldSettings = NULL; +MovieData* oldSettings = NULL; // Loading a movie calls NDS_Reset, which calls UnloadMovieEmulationSettings. Don't unload settings on that call. bool firstReset = false; @@ -555,12 +555,17 @@ static void LoadSettingsFromMovie(MovieData movieData) } void UnloadMovieEmulationSettings() { - if (&oldSettings && !firstReset) + if (oldSettings && !firstReset) { - LoadSettingsFromMovie(oldSettings); + LoadSettingsFromMovie(*oldSettings); + delete oldSettings; oldSettings = NULL; } } +bool AreMovieEmulationSettingsActive() +{ + return (bool)oldSettings; +} //begin playing an existing movie const char* _CDECL_ FCEUI_LoadMovie(const char *fname, bool _read_only, bool tasedit, int _pauseframe) { @@ -622,7 +627,7 @@ const char* _CDECL_ FCEUI_LoadMovie(const char *fname, bool _read_only, bool tas //poweron(true); // set emulation/firmware settings - oldSettings = MovieData(true); + oldSettings = new MovieData(true); LoadSettingsFromMovie(currMovieData); firstReset = true; diff --git a/desmume/src/movie.h b/desmume/src/movie.h index 84d9b1e40..e7b1ea398 100644 --- a/desmume/src/movie.h +++ b/desmume/src/movie.h @@ -273,6 +273,7 @@ bool FCEUI_MovieGetInfo(EMUFILE &fp, MOVIE_INFO &info, bool skipFrameCount); void FCEUI_SaveMovie(const char *fname, std::wstring author, int flag, std::string sramfname, const DateTime &rtcstart); const char* _CDECL_ FCEUI_LoadMovie(const char *fname, bool _read_only, bool tasedit, int _pauseframe); // returns NULL on success, errmsg on failure void UnloadMovieEmulationSettings(); +bool AreMovieEmulationSettingsActive(); void FCEUI_StopMovie(); void FCEUMOV_AddInputState(); void FCEUMOV_HandlePlayback(); From 11e2448d1c66d25b45bb9fb1310afe24f174ee71 Mon Sep 17 00:00:00 2001 From: SuuperW Date: Sat, 1 Sep 2018 12:38:39 -0500 Subject: [PATCH 09/13] Better loading of JIT settings from a movie. --- desmume/src/movie.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/desmume/src/movie.cpp b/desmume/src/movie.cpp index 1d005c295..32eccd52b 100644 --- a/desmume/src/movie.cpp +++ b/desmume/src/movie.cpp @@ -547,11 +547,13 @@ static void LoadSettingsFromMovie(MovieData movieData) } if (movieData.advancedTiming != -1) CommonSettings.advanced_timing = movieData.advancedTiming; - if (movieData.jitBlockSize != -1) + if (movieData.jitBlockSize > 0 && movieData.jitBlockSize <= 100) { - CommonSettings.use_jit = movieData.jitBlockSize != 0; + CommonSettings.use_jit = true; CommonSettings.jit_max_block_size = movieData.jitBlockSize; } + else + CommonSettings.use_jit = false; } void UnloadMovieEmulationSettings() { From 484b062bf5d87728434e8ae915531d47d7b239f8 Mon Sep 17 00:00:00 2001 From: SuuperW Date: Sun, 2 Sep 2018 10:52:35 -0500 Subject: [PATCH 10/13] Add swiFromBios and bootFromFirmware to MovieData. --- desmume/src/movie.cpp | 11 +++++++++-- desmume/src/movie.h | 8 +++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/desmume/src/movie.cpp b/desmume/src/movie.cpp index 32eccd52b..2bda75014 100644 --- a/desmume/src/movie.cpp +++ b/desmume/src/movie.cpp @@ -210,8 +210,11 @@ MovieData::MovieData(bool fromCurrentSettings) if (fromCurrentSettings) { useExtBios = CommonSettings.UseExtBIOS; - if (useExtFirmware != -1) - useExtFirmware = CommonSettings.UseExtFirmware; + if (useExtBios) + swiFromBios = CommonSettings.SWIFromBIOS; + useExtFirmware = CommonSettings.UseExtFirmware; + if (useExtFirmware) + bootFromFirmware = CommonSettings.BootFromFirmware; if (!CommonSettings.UseExtFirmware) { firmNickname.resize(CommonSettings.fw_config.nickname_len); @@ -516,8 +519,12 @@ static void LoadSettingsFromMovie(MovieData movieData) { if (movieData.useExtBios != -1) CommonSettings.UseExtBIOS = movieData.useExtBios; + if (movieData.swiFromBios != -1) + CommonSettings.SWIFromBIOS = movieData.swiFromBios; if (movieData.useExtFirmware != -1) CommonSettings.UseExtFirmware = movieData.useExtFirmware; + if (movieData.bootFromFirmware != -1) + CommonSettings.BootFromFirmware = movieData.bootFromFirmware; if (!CommonSettings.UseExtFirmware) { if (movieData.firmNickname != "") diff --git a/desmume/src/movie.h b/desmume/src/movie.h index e7b1ea398..498a62916 100644 --- a/desmume/src/movie.h +++ b/desmume/src/movie.h @@ -155,7 +155,9 @@ public: bool binaryFlag; int useExtBios = -1; + int swiFromBios = -1; int useExtFirmware = -1; + int bootFromFirmware = -1; std::string firmNickname = ""; std::string firmMessage = ""; @@ -219,7 +221,9 @@ private: void installRtcStartNew(std::string& val) { DateTime::TryParse(val.c_str(), rtcStart); } void installBinary(std::string& val) { binaryFlag = atoi(val.c_str()) != 0; } void installUseExtBios(std::string& val) { useExtBios = atoi(val.c_str()) != 0; } + void installSwiFromBios(std::string& val) { swiFromBios = atoi(val.c_str()) != 0; } void installUseExtFirmware(std::string& val) { useExtFirmware = atoi(val.c_str()) != 0; } + void installBootFromFirmware(std::string& val) { bootFromFirmware = atoi(val.c_str()) != 0; } void installFirmNickname(std::string& val) { firmNickname = val; } void installFirmMessage(std::string& val) { firmMessage = val; } void installFirmFavColour(std::string& val) { firmFavColour = atoi(val.c_str()); } @@ -249,7 +253,9 @@ private: {"comment", &MovieData::installComment}, {"binary", &MovieData::installBinary}, {"useExtBios", &MovieData::installUseExtBios}, - {"useExtFirmware", &MovieData::installUseExtBios}, + {"swiFromBios", &MovieData::installSwiFromBios}, + {"useExtFirmware", &MovieData::installUseExtFirmware}, + {"bootFromFirmware", &MovieData::installBootFromFirmware}, {"firmNickname", &MovieData::installFirmNickname}, {"firmMessage", &MovieData::installFirmMessage}, {"firmFavColour", &MovieData::installFirmFavColour}, From e697391dfd31ee599d4248d4090bfb3853b05f1e Mon Sep 17 00:00:00 2001 From: SuuperW Date: Mon, 3 Sep 2018 01:05:41 -0500 Subject: [PATCH 11/13] Support recording/playing movies starting from a savestate. --- desmume/src/commandline.cpp | 2 +- desmume/src/frontend/windows/replay.cpp | 44 ++++++--- desmume/src/frontend/windows/replay.h | 2 + desmume/src/frontend/windows/resource.h | 1 + desmume/src/frontend/windows/resources.rc | 109 ++++++++++++++-------- desmume/src/movie.cpp | 43 ++++++--- desmume/src/movie.h | 4 +- desmume/src/saves.cpp | 7 +- desmume/src/saves.h | 3 +- 9 files changed, 146 insertions(+), 69 deletions(-) diff --git a/desmume/src/commandline.cpp b/desmume/src/commandline.cpp index d3979e3c6..1c5612ed3 100644 --- a/desmume/src/commandline.cpp +++ b/desmume/src/commandline.cpp @@ -559,7 +559,7 @@ void CommandLine::process_movieCommands() } else if(record_movie_file != "") { - FCEUI_SaveMovie(record_movie_file.c_str(), L"", 0, NULL, FCEUI_MovieGetRTCDefault()); + FCEUI_SaveMovie(record_movie_file.c_str(), L"", START_BLANK, NULL, FCEUI_MovieGetRTCDefault()); } } diff --git a/desmume/src/frontend/windows/replay.cpp b/desmume/src/frontend/windows/replay.cpp index 332068cc8..e9ea2cac5 100644 --- a/desmume/src/frontend/windows/replay.cpp +++ b/desmume/src/frontend/windows/replay.cpp @@ -243,8 +243,7 @@ INT_PTR CALLBACK ReplayDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM return false; } - -int flag=0; +START_FROM startFrom; //Record movie dialog static INT_PTR CALLBACK RecordDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) @@ -256,7 +255,11 @@ static INT_PTR CALLBACK RecordDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, switch(uMsg) { case WM_INITDIALOG: { - CheckDlgButton(hwndDlg, IDC_START_FROM_SRAM, ((flag == 1) ? BST_CHECKED : BST_UNCHECKED)); + CheckDlgButton(hwndDlg, IDC_START_FROM_SRAM, startFrom == START_SRAM ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_START_FROM_POWER_ON, startFrom == START_SAVESTATE ? BST_UNCHECKED : BST_CHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_START_FROM_SRAM), startFrom != START_SAVESTATE); + EnableWindow(GetDlgItem(hwndDlg, IDC_EDIT_SRAMFILENAME), startFrom == START_SRAM); + EnableWindow(GetDlgItem(hwndDlg, IDC_BUTTON_BROWSESRAM), startFrom == START_SRAM); SetFocus(GetDlgItem(hwndDlg, IDC_EDIT_FILENAME)); DateTime t = FCEUI_MovieGetRTCDefault(); @@ -313,7 +316,7 @@ static INT_PTR CALLBACK RecordDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, t.tm_sec = systime.wSecond; DateTime rtcstart(t.tm_year,t.tm_mon,t.tm_mday,t.tm_hour,t.tm_min,t.tm_sec); - FCEUI_SaveMovie(fname.c_str(), author, flag, sramfname, rtcstart); + FCEUI_SaveMovie(fname.c_str(), author, startFrom, sramfname, rtcstart); EndDialog(hwndDlg, 0); } return true; @@ -402,17 +405,34 @@ static INT_PTR CALLBACK RecordDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, break; } break; + + case IDC_START_FROM_SRAM: + { + bool checked = IsDlgButtonChecked(hwndDlg, IDC_START_FROM_SRAM); + startFrom = checked ? START_SRAM : START_BLANK; + EnableWindow(GetDlgItem(hwndDlg, IDC_EDIT_SRAMFILENAME), checked); + EnableWindow(GetDlgItem(hwndDlg, IDC_BUTTON_BROWSESRAM), checked); + + break; + } + + case IDC_START_FROM_POWER_ON: // TODO: test movies starting form savestate + { + bool powerOn = IsDlgButtonChecked(hwndDlg, IDC_START_FROM_POWER_ON); + startFrom = powerOn ? START_BLANK : START_SAVESTATE; + EnableWindow(GetDlgItem(hwndDlg, IDC_START_FROM_SRAM), powerOn); + if (!powerOn) + { + CheckDlgButton(hwndDlg, IDC_START_FROM_SRAM, false); + // CheckDlgButton does not send a WM_COMMAND message, so also disable SRAM stuff here + EnableWindow(GetDlgItem(hwndDlg, IDC_EDIT_SRAMFILENAME), false); + EnableWindow(GetDlgItem(hwndDlg, IDC_BUTTON_BROWSESRAM), false); + } + break; + } } } - HWND cur = GetDlgItem(hwndDlg, IDC_EDIT_SRAMFILENAME); - - IsDlgButtonChecked(hwndDlg, IDC_START_FROM_SRAM) ? flag=1 : flag=0; - IsDlgButtonChecked(hwndDlg, IDC_START_FROM_SRAM) ? EnableWindow(cur, TRUE) : EnableWindow(cur, FALSE); - - cur = GetDlgItem(hwndDlg, IDC_BUTTON_BROWSESRAM); - IsDlgButtonChecked(hwndDlg, IDC_START_FROM_SRAM) ? EnableWindow(cur, TRUE) : EnableWindow(cur, FALSE); - return false; } diff --git a/desmume/src/frontend/windows/replay.h b/desmume/src/frontend/windows/replay.h index 279d6a2e5..3f1b42ad0 100644 --- a/desmume/src/frontend/windows/replay.h +++ b/desmume/src/frontend/windows/replay.h @@ -18,6 +18,8 @@ #ifndef _WIN_REPLAY_H_ #define _WIN_REPLAY_H_ +enum START_FROM { START_BLANK, START_SRAM, START_SAVESTATE }; + void Replay_LoadMovie(); void MovieRecordTo(); diff --git a/desmume/src/frontend/windows/resource.h b/desmume/src/frontend/windows/resource.h index e7d0b1eec..593de50ef 100644 --- a/desmume/src/frontend/windows/resource.h +++ b/desmume/src/frontend/windows/resource.h @@ -273,6 +273,7 @@ #define IDC_BUTTON_BROWSESRAM 980 #define IDC_C_WATCH_UP 980 #define IDD_EDITWATCH 980 +#define IDC_START_FROM_POWER_ON 981 #define IDC_C_WATCH_DOWN 981 #define RAMMENU_FILE_AUTOLOAD 982 #define RAMMENU_FILE_SAVEWINDOW 983 diff --git a/desmume/src/frontend/windows/resources.rc b/desmume/src/frontend/windows/resources.rc index 69677ecc1..895440ed6 100644 --- a/desmume/src/frontend/windows/resources.rc +++ b/desmume/src/frontend/windows/resources.rc @@ -963,27 +963,28 @@ BEGIN PUSHBUTTON "Separator",IDC_C_WATCH_SEPARATE,225,136,36,14 END -IDD_RECORDMOVIE DIALOGEX 0, 0, 301, 124 +IDD_RECORDMOVIE DIALOGEX 0, 0, 301, 118 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Record movie" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - DEFPUSHBUTTON "OK",IDOK,177,106,50,14 - PUSHBUTTON "Cancel",IDCANCEL,231,106,50,14 - GROUPBOX "",65501,11,9,269,64 - LTEXT "File:",IDC_STATIC,31,22,14,8 - EDITTEXT IDC_EDIT_FILENAME,49,20,189,12,ES_AUTOHSCROLL - PUSHBUTTON "...",IDC_BUTTON_BROWSEFILE,249,20,18,14 - LTEXT "Author:",IDC_STATIC,21,38,25,8 - EDITTEXT IDC_EDIT_AUTHOR,49,36,189,14,ES_AUTOHSCROLL - LTEXT "Date:",IDC_STATIC,28,56,18,8 - CONTROL "",IDC_DTP_DATE,"SysDateTimePick32",DTS_RIGHTALIGN | DTS_LONGDATEFORMAT | WS_TABSTOP,49,54,123,12 - CONTROL "",IDC_DTP_TIME,"SysDateTimePick32",DTS_RIGHTALIGN | DTS_UPDOWN | WS_TABSTOP | 0x8,176,54,62,12 - GROUPBOX "",IDC_STATIC,11,73,269,29 - LTEXT "SRAM:",IDC_STATIC,19,85,25,8 - EDITTEXT IDC_EDIT_SRAMFILENAME,48,83,189,12,ES_AUTOHSCROLL - PUSHBUTTON "...",IDC_BUTTON_BROWSESRAM,248,83,18,14 - CONTROL "Start from SRAM",IDC_START_FROM_SRAM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,108,93,10 + DEFPUSHBUTTON "OK",IDOK,177,99,50,14 + PUSHBUTTON "Cancel",IDCANCEL,231,99,50,14 + GROUPBOX "",65501,11,2,269,64 + LTEXT "File:",IDC_STATIC,31,15,14,8 + EDITTEXT IDC_EDIT_FILENAME,49,13,189,12,ES_AUTOHSCROLL + PUSHBUTTON "...",IDC_BUTTON_BROWSEFILE,249,13,18,14 + LTEXT "Author:",IDC_STATIC,21,31,25,8 + EDITTEXT IDC_EDIT_AUTHOR,49,29,189,14,ES_AUTOHSCROLL + LTEXT "Date:",IDC_STATIC,28,49,18,8 + CONTROL "",IDC_DTP_DATE,"SysDateTimePick32",DTS_RIGHTALIGN | DTS_LONGDATEFORMAT | WS_TABSTOP,49,47,123,12 + CONTROL "",IDC_DTP_TIME,"SysDateTimePick32",DTS_RIGHTALIGN | DTS_UPDOWN | WS_TABSTOP | 0x8,176,47,62,12 + GROUPBOX "",IDC_STATIC,11,66,269,29 + LTEXT "SRAM:",IDC_STATIC,19,78,25,8 + EDITTEXT IDC_EDIT_SRAMFILENAME,48,76,189,12,ES_AUTOHSCROLL + PUSHBUTTON "...",IDC_BUTTON_BROWSESRAM,248,76,18,14 + CONTROL "Start from SRAM",IDC_START_FROM_SRAM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,101,73,10 + CONTROL "Start from power on",IDC_START_FROM_POWER_ON,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,85,101,81,10 END IDD_REPLAY_METADATA DIALOGEX 0, 0, 325, 250 @@ -1904,7 +1905,7 @@ BEGIN IDD_RECORDMOVIE, DIALOG BEGIN - BOTTOMMARGIN, 113 + BOTTOMMARGIN, 107 END IDD_SOUNDSETTINGS, DIALOG @@ -2120,6 +2121,10 @@ BEGIN IDM_FILE_STOPAVI "Stop AVI" IDM_FILE_STOPWAV "Stop WAV" IDM_FILE_RECORDAVI "Record AVI" +END + +STRINGTABLE +BEGIN IDM_FILE_RECORDWAV "Record WAV" END @@ -2133,23 +2138,58 @@ BEGIN ID_LABEL_HK1 "Open ROM" ID_LABEL_HK2 "Reset" ID_LABEL_HK3 "Pause" - ID_LABEL_HK3b "CPU mode" - ID_LABEL_HK3c "Increase JIT block size" - ID_LABEL_HK3d "Decrease JIT block size" ID_LABEL_HK4 "Frame Advance" ID_LABEL_HK5 "Fast Forward" ID_LABEL_HK6 "Fast Forward Toggle" ID_LABEL_HK7 "Increase Speed" ID_LABEL_HK8 "Decrease Speed" - ID_LABEL_HK8b "Limit Framerate Toggle" ID_LABEL_HK9 "Microphone" ID_LABEL_HK10 "Auto-Hold" ID_LABEL_HK11 "Auto-Hold Clear" ID_LABEL_HK12 "Toggle Rasterizer" ID_LABEL_HK13 "Save Screenshot as" - ID_LABEL_HK13b "Quick Screenshot" ID_LABEL_HK14 "Record WAV" ID_LABEL_HK15 "Record AVI" +END + +STRINGTABLE +BEGIN + ID_LABEL_HK3b "CPU mode" + ID_LABEL_HK3c "Increase JIT block size" +END + +STRINGTABLE +BEGIN + ID_LABEL_HK3d "Decrease JIT block size" +END + +STRINGTABLE +BEGIN + ID_LABEL_HK8b "Limit Framerate Toggle" +END + +STRINGTABLE +BEGIN + ID_LABEL_HK48 "Turbo A" + ID_LABEL_HK49 "Turbo Y" + ID_LABEL_HK50 "Turbo X" + ID_LABEL_HK51 "Turbo R" + ID_LABEL_HK52 "Turbo L" + ID_LABEL_HK53 "Reload ROM" + ID_LABEL_HK13b "Quick Screenshot" + ID_LABEL_HK54 "Search Cheats" + ID_LABEL_HK55 "Increase Pressure" + ID_LABEL_HK56 "Decrease Pressure" + ID_LABEL_HK57 "Rotation 0" + ID_LABEL_HK58 "Rotation 90" + ID_LABEL_HK59 "Rotation 180" + ID_LABEL_HK60 "Rotation 270" + ID_LABEL_HK61 "Toggle Stylus Jitter" + ID_LABEL_HK62 "Toggle Cursor" +END + +STRINGTABLE +BEGIN ID_LABEL_HK16 "Toggle Frame Display" ID_LABEL_HK17 "Toggle FPS Display" ID_LABEL_HK18 "Toggle Input Display" @@ -2166,6 +2206,10 @@ BEGIN ID_LABEL_HK29 "Stylus Auto-Hold" ID_LABEL_HK30 "LCDs layout mode" ID_LABEL_HK31 "LCDs swap" +END + +STRINGTABLE +BEGIN ID_LABEL_HK32 "Increase Volume" ID_LABEL_HK33 "Decrease Volume" ID_LABEL_HK34 "Save to Slot " @@ -2182,21 +2226,10 @@ BEGIN ID_LABEL_HK45 "Turbo Select" ID_LABEL_HK46 "Turbo Start" ID_LABEL_HK47 "Turbo B" - ID_LABEL_HK48 "Turbo A" - ID_LABEL_HK49 "Turbo Y" - ID_LABEL_HK50 "Turbo X" - ID_LABEL_HK51 "Turbo R" - ID_LABEL_HK52 "Turbo L" - ID_LABEL_HK53 "Reload ROM" - ID_LABEL_HK54 "Search Cheats" - ID_LABEL_HK55 "Increase Pressure" - ID_LABEL_HK56 "Decrease Pressure" - ID_LABEL_HK57 "Rotation 0" - ID_LABEL_HK58 "Rotation 90" - ID_LABEL_HK59 "Rotation 180" - ID_LABEL_HK60 "Rotation 270" - ID_LABEL_HK61 "Toggle Stylus Jitter" - ID_LABEL_HK62 "Toggle Cursor" +END + +STRINGTABLE +BEGIN ID_LABEL_HK63 "List Cheats" ID_LABEL_HK64 "Toggle Cheats" ID_LABEL_HK65 "Toggle Main GPU" diff --git a/desmume/src/movie.cpp b/desmume/src/movie.cpp index 2bda75014..6f82939e5 100644 --- a/desmume/src/movie.cpp +++ b/desmume/src/movie.cpp @@ -39,6 +39,8 @@ #include "version.h" #include "path.h" #include "emufile.h" +#include "replay.h" +#include "saves.h" using namespace std; bool freshMovie = false; //True when a movie loads, false when movie is altered. Used to determine if a movie has been altered since opening @@ -639,9 +641,17 @@ const char* _CDECL_ FCEUI_LoadMovie(const char *fname, bool _read_only, bool tas oldSettings = new MovieData(true); LoadSettingsFromMovie(currMovieData); - firstReset = true; - NDS_Reset(); - firstReset = false; + if (currMovieData.savestate.size() == 0) + { + firstReset = true; + NDS_Reset(); + firstReset = false; + } + else + { + EMUFILE_MEMORY efs = EMUFILE_MEMORY(&currMovieData.savestate); + savestate_load(efs); + } ////WE NEED TO LOAD A SAVESTATE //if(currMovieData.savestate.size() != 0) @@ -729,7 +739,7 @@ bool MovieData::loadSramFrom(std::vector* buf) //begin recording a new movie //TODO - BUG - the record-from-another-savestate doesnt work. -void FCEUI_SaveMovie(const char *fname, std::wstring author, int flag, std::string sramfname, const DateTime &rtcstart) +void FCEUI_SaveMovie(const char *fname, std::wstring author, START_FROM startFrom, std::string sramfname, const DateTime &rtcstart) { //if(!FCEU_IsValidUI(FCEUI_RECORDMOVIE)) // return; @@ -758,15 +768,26 @@ void FCEUI_SaveMovie(const char *fname, std::wstring author, int flag, std::stri NDS_CreateDummyFirmware(&CommonSettings.fw_config); } - NDS_Reset(); - //todo ? - //poweron(true); - //else - // MovieData::dumpSavestateTo(&currMovieData.savestate,Z_BEST_COMPRESSION); + if (startFrom == START_SAVESTATE) + { + // ?? MovieData::dumpSavestateTo(&currMovieData.savestate,Z_BEST_COMPRESSION); + EMUFILE_MEMORY efs; + savestate_save(efs, Z_BEST_COMPRESSION); + currMovieData.savestate.resize(efs.size()); + efs.fseek(0, SEEK_SET); + efs.fread(currMovieData.savestate.begin()._Ptr, efs.size()); + } + else + { + NDS_Reset(); - if(flag == 1) - EMUFILE::readAllBytes(&currMovieData.sram, sramfname); + //todo ? + //poweron(true); + + if (startFrom == START_SRAM) + EMUFILE::readAllBytes(&currMovieData.sram, sramfname); + } //we are going to go ahead and dump the header. from now on we will only be appending frames currMovieData.dump(*osRecordingMovie, false); diff --git a/desmume/src/movie.h b/desmume/src/movie.h index 498a62916..532bc9c7d 100644 --- a/desmume/src/movie.h +++ b/desmume/src/movie.h @@ -28,6 +28,8 @@ #include "utils/guid.h" #include "utils/md5.h" +#include "replay.h" + struct UserInput; class EMUFILE; @@ -276,7 +278,7 @@ extern MovieData currMovieData; //adelikat: main needs this for frame counter d extern bool movie_reset_command; bool FCEUI_MovieGetInfo(EMUFILE &fp, MOVIE_INFO &info, bool skipFrameCount); -void FCEUI_SaveMovie(const char *fname, std::wstring author, int flag, std::string sramfname, const DateTime &rtcstart); +void FCEUI_SaveMovie(const char *fname, std::wstring author, START_FROM startFrom, std::string sramfname, const DateTime &rtcstart); const char* _CDECL_ FCEUI_LoadMovie(const char *fname, bool _read_only, bool tasedit, int _pauseframe); // returns NULL on success, errmsg on failure void UnloadMovieEmulationSettings(); bool AreMovieEmulationSettingsActive(); diff --git a/desmume/src/saves.cpp b/desmume/src/saves.cpp index b5d385819..480945da2 100644 --- a/desmume/src/saves.cpp +++ b/desmume/src/saves.cpp @@ -1043,12 +1043,9 @@ bool savestate_save (const char *file_name) { EMUFILE_MEMORY ms; size_t elems_written; -#ifdef HAVE_LIBZ - if (!savestate_save(ms, Z_DEFAULT_COMPRESSION)) -#else - if (!savestate_save(ms, 0)) -#endif + if (!savestate_save(ms)) return false; + FILE* file = fopen(file_name,"wb"); if(file) { diff --git a/desmume/src/saves.h b/desmume/src/saves.h index b3db4723e..e7059cf6d 100644 --- a/desmume/src/saves.h +++ b/desmume/src/saves.h @@ -21,6 +21,7 @@ #define _SRAM_H #include "types.h" +#include "zlib.h" #define NB_STATES 10 @@ -64,6 +65,6 @@ void savestate_slot(int num); void loadstate_slot(int num); bool savestate_load(class EMUFILE &is); -bool savestate_save(class EMUFILE &outstream, int compressionLevel); +bool savestate_save(class EMUFILE &outstream, int compressionLevel = Z_DEFAULT_COMPRESSION); #endif From 2a7103ec0b2b8edebbd2a6cf3b4c6556439d80c8 Mon Sep 17 00:00:00 2001 From: SuuperW Date: Mon, 3 Sep 2018 05:35:05 -0500 Subject: [PATCH 12/13] Save movie's savestate to a separate file instead of encoding it in the movie file. (This gives significantly faster performance, and will make it easier for the user to edit the starting savestate if need be.) --- desmume/src/frontend/windows/replay.cpp | 6 ++++- desmume/src/movie.cpp | 32 +++++++++++++------------ desmume/src/movie.h | 7 ++---- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/desmume/src/frontend/windows/replay.cpp b/desmume/src/frontend/windows/replay.cpp index e9ea2cac5..a328aec1e 100644 --- a/desmume/src/frontend/windows/replay.cpp +++ b/desmume/src/frontend/windows/replay.cpp @@ -150,6 +150,7 @@ INT_PTR CALLBACK ReplayDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM OPENFILENAME ofn; char szChoice[MAX_PATH]={0}; char filename[MAX_PATH] = ""; + const char* error; switch(uMsg) { @@ -198,7 +199,10 @@ INT_PTR CALLBACK ReplayDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM return true; case IDOK: - FCEUI_LoadMovie(playfilename, replayreadonly, false, 80000); + error = FCEUI_LoadMovie(playfilename, replayreadonly, false, 80000); + if (error) + MessageBox(hwndDlg, error, "Failed to load movie", MB_OK); + ZeroMemory(&playfilename, sizeof(playfilename)); EndDialog(hwndDlg, 0); return true; diff --git a/desmume/src/movie.cpp b/desmume/src/movie.cpp index 6f82939e5..1db5465c8 100644 --- a/desmume/src/movie.cpp +++ b/desmume/src/movie.cpp @@ -277,7 +277,6 @@ void MovieData::installRtcStart(std::string& val) } } void MovieData::installComment(std::string& val) { comments.push_back(mbstowcs(val)); } -void MovieData::installSavestate(std::string& val) { BinaryDataFromString(val, &this->savestate); } void MovieData::installSram(std::string& val) { BinaryDataFromString(val, &this->sram); } void MovieData::installValue(std::string& key, std::string& val) @@ -337,8 +336,7 @@ int MovieData::dump(EMUFILE &fp, bool binary) if (binary) fp.fprintf("binary 1\n"); - if (savestate.size() != 0) - fp.fprintf("savestate %s\n", BytesToString(&savestate[0],savestate.size()).c_str()); + fp.fprintf("savestate %d\n", savestate?1:0); if (sram.size() != 0) fp.fprintf("sram %s\n", BytesToString(&sram[0],sram.size()).c_str()); @@ -641,17 +639,21 @@ const char* _CDECL_ FCEUI_LoadMovie(const char *fname, bool _read_only, bool tas oldSettings = new MovieData(true); LoadSettingsFromMovie(currMovieData); - if (currMovieData.savestate.size() == 0) + if (currMovieData.savestate) + { + // SS file name should be the same as the movie file name, except for extension + std::string ssName = fname; + ssName.erase(ssName.length() - 3, 3); + ssName.append("dst"); + if (!savestate_load(ssName.c_str())) + return "Could not load movie's savestate. There should be a .dst file with the same name as the movie, in the same folder."; + } + else { firstReset = true; NDS_Reset(); firstReset = false; } - else - { - EMUFILE_MEMORY efs = EMUFILE_MEMORY(&currMovieData.savestate); - savestate_load(efs); - } ////WE NEED TO LOAD A SAVESTATE //if(currMovieData.savestate.size() != 0) @@ -771,12 +773,12 @@ void FCEUI_SaveMovie(const char *fname, std::wstring author, START_FROM startFro if (startFrom == START_SAVESTATE) { - // ?? MovieData::dumpSavestateTo(&currMovieData.savestate,Z_BEST_COMPRESSION); - EMUFILE_MEMORY efs; - savestate_save(efs, Z_BEST_COMPRESSION); - currMovieData.savestate.resize(efs.size()); - efs.fseek(0, SEEK_SET); - efs.fread(currMovieData.savestate.begin()._Ptr, efs.size()); + // SS file name should be the same as the movie file name, except for extension + std::string ssName = fname; + ssName.erase(ssName.length() - 3, 3); + ssName.append("dst"); + savestate_save(ssName.c_str()); + currMovieData.savestate = true; } else { diff --git a/desmume/src/movie.h b/desmume/src/movie.h index 532bc9c7d..14e805684 100644 --- a/desmume/src/movie.h +++ b/desmume/src/movie.h @@ -143,7 +143,7 @@ public: u32 romChecksum; std::string romSerial; std::string romFilename; - std::vector savestate; + bool savestate = false; std::vector sram; std::vector records; std::vector comments; @@ -207,9 +207,6 @@ public: void clearRecordRange(int start, int len); void insertEmpty(int at, int frames); - static bool loadSavestateFrom(std::vector* buf); - static void dumpSavestateTo(std::vector* buf, int compressionLevel); - static bool loadSramFrom(std::vector* buf); //void TryDumpIncremental(); @@ -234,11 +231,11 @@ private: void installFirmLanguage(std::string& val) { firmLanguage = atoi(val.c_str()); } void installAdvancedTiming(std::string& val) { advancedTiming = atoi(val.c_str()) != 0; } void installJitBlockSize(std::string& val) { jitBlockSize = atoi(val.c_str()); } + void installSavestate(std::string& val) { savestate = atoi(val.c_str()) != 0; } void installRomChecksum(std::string& val); void installRtcStart(std::string& val); void installComment(std::string& val); - void installSavestate(std::string& val); void installSram(std::string& val); typedef void(MovieData::* ivm)(std::string&); From 4c5842d2aa58244d5ac6a890b3f0b7f8c10fd727 Mon Sep 17 00:00:00 2001 From: SuuperW Date: Mon, 3 Sep 2018 05:42:30 -0500 Subject: [PATCH 13/13] code cleanup --- desmume/src/movie.cpp | 43 ++++++------------------------------------- 1 file changed, 6 insertions(+), 37 deletions(-) diff --git a/desmume/src/movie.cpp b/desmume/src/movie.cpp index 1db5465c8..8625df825 100644 --- a/desmume/src/movie.cpp +++ b/desmume/src/movie.cpp @@ -478,14 +478,14 @@ static void closeRecordingMovie() } } -/// Stop movie playback. +// Stop movie playback. static void StopPlayback() { driver->USR_InfoMessage("Movie playback stopped."); movieMode = MOVIEMODE_INACTIVE; } -/// Stop movie playback without closing the movie. +// Stop movie playback without closing the movie. static void FinishPlayback() { driver->USR_InfoMessage("Movie finished playing."); @@ -493,7 +493,7 @@ static void FinishPlayback() } -/// Stop movie recording +// Stop movie recording static void StopRecording() { driver->USR_InfoMessage("Movie recording stopped."); @@ -597,36 +597,11 @@ const char* _CDECL_ FCEUI_LoadMovie(const char *fname, bool _read_only, bool tas currMovieData = MovieData(); strcpy(curMovieFilename, fname); - //FCEUFILE *fp = FCEU_fopen(fname,0,"rb",0); - //if (!fp) return; - //if(fp->isArchive() && !_read_only) { - // FCEU_PrintError("Cannot open a movie in read+write from an archive."); - // return; - //} - - //LoadFM2(currMovieData, fp->stream, INT_MAX, false); - bool loadedfm2 = false; - bool opened = false; -// { - EMUFILE *fp = new EMUFILE_FILE(fname, "rb"); -// if(fs.is_open()) -// { - loadedfm2 = LoadFM2(currMovieData, *fp, INT_MAX, false); - opened = true; -// } -// fs.close(); - delete fp; -// } - if(!opened) - { - // for some reason fs.open doesn't work, it has to be a whole new fstream object -// fstream fs (fname, std::ios_base::in); - loadedfm2 = LoadFM2(currMovieData, *fp, INT_MAX, false); -// fs.close(); - delete fp; - } + EMUFILE *fp = new EMUFILE_FILE(fname, "rb"); + loadedfm2 = LoadFM2(currMovieData, *fp, INT_MAX, false); + delete fp; if(!loadedfm2) return "failed to load movie"; @@ -655,12 +630,6 @@ const char* _CDECL_ FCEUI_LoadMovie(const char *fname, bool _read_only, bool tas firstReset = false; } - ////WE NEED TO LOAD A SAVESTATE - //if(currMovieData.savestate.size() != 0) - //{ - // bool success = MovieData::loadSavestateFrom(&currMovieData.savestate); - // if(!success) return; - //} lagframecounter=0; LagFrameFlag=0; lastLag=0;