From db94b7c8a64b0469681cb4010b9852196fd13438 Mon Sep 17 00:00:00 2001 From: rogerman Date: Sat, 25 Jan 2014 00:39:52 +0000 Subject: [PATCH] movie.cpp: - Do some preliminary cleanup of the code. - Fix bug where firmware nicknames and messages weren't being saved properly. --- desmume/src/movie.cpp | 212 +++++++++++++++++---------------- desmume/src/movie.h | 24 ++-- desmume/src/utils/ConvertUTF.h | 5 + 3 files changed, 128 insertions(+), 113 deletions(-) diff --git a/desmume/src/movie.cpp b/desmume/src/movie.cpp index 8fd308d13..7c8c82fcb 100644 --- a/desmume/src/movie.cpp +++ b/desmume/src/movie.cpp @@ -1,5 +1,5 @@ /* - Copyright 2008-2011 DeSmuME team + Copyright 2008-2014 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,6 +23,7 @@ #include "utils/guid.h" #include "utils/xstring.h" #include "utils/datetime.h" +#include "utils/ConvertUTF.h" #include "movie.h" #include "NDSSystem.h" #include "readwrite.h" @@ -87,8 +88,6 @@ void MovieData::insertEmpty(int at, int frames) } } - - void MovieRecord::clear() { pad = 0; @@ -96,7 +95,6 @@ void MovieRecord::clear() touch.padding = 0; } - bool MovieRecord::Compare(MovieRecord& compareRec) { //Check pad @@ -137,7 +135,6 @@ void MovieRecord::dumpPad(EMUFILE* fp, u16 pad) } } - void MovieRecord::parsePad(EMUFILE* fp, u16& pad) { @@ -151,8 +148,7 @@ void MovieRecord::parsePad(EMUFILE* fp, u16& pad) } } - -void MovieRecord::parse(MovieData* md, EMUFILE* fp) +void MovieRecord::parse(EMUFILE* fp) { //by the time we get in here, the initial pipe has already been extracted @@ -171,8 +167,7 @@ void MovieRecord::parse(MovieData* md, EMUFILE* fp) //should be left at a newline } - -void MovieRecord::dump(MovieData* md, EMUFILE* fp, int index) +void MovieRecord::dump(EMUFILE* fp) { //dump the misc commands //*os << '|' << setw(1) << (int)commands; @@ -212,7 +207,6 @@ void MovieData::truncateAt(int frame) records.resize(frame); } - 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 @@ -270,23 +264,11 @@ void MovieData::installValue(std::string& key, std::string& val) installBool(val,binaryFlag); else if(key == "savestate") { - int len = Base64StringToBytesLength(val); - if(len == -1) len = HexStringToBytesLength(val); // wasn't base64, try hex - if(len >= 1) - { - savestate.resize(len); - StringToBytes(val,&savestate[0],len); // decodes either base64 or hex - } + BinaryDataFromString(val, &this->savestate); } else if(key == "sram") { - int len = Base64StringToBytesLength(val); - if(len == -1) len = HexStringToBytesLength(val); // wasn't base64, try hex - if(len >= 1) - { - sram.resize(len); - StringToBytes(val,&sram[0],len); // decodes either base64 or hex - } + BinaryDataFromString(val, &this->sram); } } @@ -314,23 +296,20 @@ int MovieData::dump(EMUFILE* fp, bool binary) fp->fprintf("bootFromFirmware %d\n", CommonSettings.BootFromFirmware?1:0); } else { - char temp_str[27]; - int i; - - /* FIXME: harshly only use the lower byte of the UTF-16 character. - * This would cause strange behaviour if the user could set UTF-16 but - * they cannot yet. - */ - for (i = 0; i < CommonSettings.fw_config.nickname_len; i++) { - temp_str[i] = CommonSettings.fw_config.nickname[i]; - } - temp_str[i] = '\0'; - fp->fprintf("firmNickname %s\n", temp_str); - for (i = 0; i < CommonSettings.fw_config.message_len; i++) { - temp_str[i] = CommonSettings.fw_config.message[i]; - } - temp_str[i] = '\0'; - fp->fprintf("firmMessage %s\n", temp_str); + UTF8 fwNicknameUTF8[MAX_FW_NICKNAME_LENGTH*4]; + UTF8 *fwNicknameUTF8Start = fwNicknameUTF8; + const UTF16 *fwNicknameUTF16 = (const UTF16 *)CommonSettings.fw_config.nickname; + memset(fwNicknameUTF8, 0, sizeof(fwNicknameUTF8)); + ConvertUTF16toUTF8(&fwNicknameUTF16, fwNicknameUTF16 + CommonSettings.fw_config.nickname_len, &fwNicknameUTF8Start, fwNicknameUTF8Start + sizeof(fwNicknameUTF8), strictConversion); + + UTF8 fwMessageUTF8[MAX_FW_MESSAGE_LENGTH*4]; + UTF8 *fwMessageUTF8Start = fwMessageUTF8; + const UTF16 *fwMessageUTF16 = (const UTF16 *)CommonSettings.fw_config.message; + memset(fwMessageUTF8, 0, sizeof(fwMessageUTF8)); + ConvertUTF16toUTF8(&fwMessageUTF16, fwMessageUTF16 + CommonSettings.fw_config.message_len, &fwMessageUTF8Start, fwMessageUTF8Start + sizeof(fwMessageUTF8), strictConversion); + + fp->fprintf("firmNickname %s\n", fwNicknameUTF8); + fp->fprintf("firmMessage %s\n", fwMessageUTF8); fp->fprintf("firmFavColour %d\n", CommonSettings.fw_config.fav_colour); fp->fprintf("firmBirthMonth %d\n", CommonSettings.fw_config.birth_month); fp->fprintf("firmBirthDay %d\n", CommonSettings.fw_config.birth_day); @@ -355,11 +334,11 @@ int MovieData::dump(EMUFILE* fp, bool binary) //put one | to start the binary dump fp->fputc('|'); for(int i=0;i<(int)records.size();i++) - records[i].dumpBinary(this,fp,i); + records[i].dumpBinary(fp); } else for(int i=0;i<(int)records.size();i++) - records[i].dump(this,fp,i); + records[i].dump(fp); int end = fp->ftell(); return end-start; @@ -420,7 +399,7 @@ bool LoadFM2(MovieData& movieData, EMUFILE* fp, int size, bool stopAfterHeader) int currcount = movieData.records.size(); movieData.records.resize(currcount+1); int preparse = fp->ftell(); - movieData.records[currcount].parse(&movieData, fp); + movieData.records[currcount].parse(fp); int postparse = fp->ftell(); size -= (postparse-preparse); state = NEWLINE; @@ -749,36 +728,8 @@ void FCEUI_SaveMovie(const char *fname, std::wstring author, int flag, std::stri } else { - UserInput& input = NDS_getProcessingUserInput(); - - MovieRecord* mr = &currMovieData.records[currFrameCounter]; - - if(mr->command_microphone()) input.mic.micButtonPressed = 1; - else input.mic.micButtonPressed = 0; - - if(mr->command_reset()) NDS_Reset(); - - if(mr->command_lid()) input.buttons.F = true; - else input.buttons.F = false; - - u16 pad = mr->pad; - input.buttons.R = (((pad>>12)&1)!=0); - input.buttons.L = (((pad>>11)&1)!=0); - input.buttons.D = (((pad>>10)&1)!=0); - input.buttons.U = (((pad>>9)&1)!=0); - input.buttons.T = (((pad>>8)&1)!=0); - input.buttons.S = (((pad>>7)&1)!=0); - input.buttons.B = (((pad>>6)&1)!=0); - input.buttons.A = (((pad>>5)&1)!=0); - input.buttons.Y = (((pad>>4)&1)!=0); - input.buttons.X = (((pad>>3)&1)!=0); - input.buttons.W = (((pad>>2)&1)!=0); - input.buttons.E = (((pad>>1)&1)!=0); - input.buttons.G = (((pad>>0)&1)!=0); - - input.touch.touchX = mr->touch.x << 4; - input.touch.touchY = mr->touch.y << 4; - input.touch.isTouch = mr->touch.touch != 0; + UserInput &input = NDS_getProcessingUserInput(); + ReplayRecToDesmumeInput(currMovieData.records[currFrameCounter], &input); } //if we are on the last frame, then pause the emulator if the player requested it @@ -811,34 +762,15 @@ void FCEUI_SaveMovie(const char *fname, std::wstring author, int flag, std::stri { if(movieMode == MOVIEMODE_RECORD) { - const UserInput& input = NDS_getFinalUserInput(); - MovieRecord mr; - - mr.commands = 0; - - if(input.mic.micButtonPressed == 1) - mr.commands = MOVIECMD_MIC; - - mr.pad = nds.pad; - - if(input.buttons.F) - mr.commands = MOVIECMD_LID; - - if(movie_reset_command) { - mr.commands = MOVIECMD_RESET; - movie_reset_command = false; - } - - mr.touch.touch = input.touch.isTouch ? 1 : 0; - mr.touch.x = input.touch.isTouch ? input.touch.touchX >> 4 : 0; - mr.touch.y = input.touch.isTouch ? input.touch.touchY >> 4 : 0; + const UserInput &input = NDS_getFinalUserInput(); + DesmumeInputToReplayRec(input, &mr); assert(mr.touch.touch || (!mr.touch.x && !mr.touch.y)); //assert(nds.touchX == input.touch.touchX && nds.touchY == input.touch.touchY); //assert((mr.touch.x << 4) == nds.touchX && (mr.touch.y << 4) == nds.touchY); - mr.dump(&currMovieData, osRecordingMovie,currMovieData.records.size()); + mr.dump(osRecordingMovie); currMovieData.records.push_back(mr); // it's apparently un-threadsafe to do this here @@ -1136,7 +1068,7 @@ bool FCEUI_MovieGetInfo(EMUFILE* fp, MOVIE_INFO& info, bool skipFrameCount) return true; } -bool MovieRecord::parseBinary(MovieData* md, EMUFILE* fp) +bool MovieRecord::parseBinary(EMUFILE* fp) { commands=fp->fgetc(); fp->fread((char *) &pad, sizeof pad); @@ -1147,13 +1079,13 @@ bool MovieRecord::parseBinary(MovieData* md, EMUFILE* fp) } -void MovieRecord::dumpBinary(MovieData* md, EMUFILE* fp, int index) +void MovieRecord::dumpBinary(EMUFILE* fp) { - fp->fputc(md->records[index].commands); - fp->fwrite((char *) &md->records[index].pad, sizeof md->records[index].pad); - fp->fwrite((char *) &md->records[index].touch.x, sizeof md->records[index].touch.x); - fp->fwrite((char *) &md->records[index].touch.y, sizeof md->records[index].touch.y); - fp->fwrite((char *) &md->records[index].touch.touch, sizeof md->records[index].touch.touch); + fp->fputc(this->commands); + fp->fwrite((char *) &this->pad, sizeof(this->pad)); + fp->fwrite((char *) &this->touch.x, sizeof(this->touch.x)); + fp->fwrite((char *) &this->touch.y, sizeof(this->touch.y)); + fp->fwrite((char *) &this->touch.touch, sizeof(this->touch.touch)); } void LoadFM2_binarychunk(MovieData& movieData, EMUFILE* fp, int size) @@ -1179,7 +1111,7 @@ void LoadFM2_binarychunk(MovieData& movieData, EMUFILE* fp, int size) movieData.records.resize(numRecords); for(int i=0;i *outBinaryData) +{ + int len = Base64StringToBytesLength(inStringData); + if(len == -1) len = HexStringToBytesLength(inStringData); // wasn't base64, try hex + if(len >= 1) + { + outBinaryData->resize(len); + StringToBytes(inStringData, &outBinaryData->front(), len); // decodes either base64 or hex + } +} + +void ReplayRecToDesmumeInput(const MovieRecord &theRecord, UserInput *theInput) +{ + if (theInput == NULL) + { + return; + } + + if(theRecord.command_reset()) + { + NDS_Reset(); + return; + } + else + { + movie_reset_command = false; + } + + const u16 pad = theRecord.pad; + theInput->buttons.R = (((pad>>12)&1)!=0); + theInput->buttons.L = (((pad>>11)&1)!=0); + theInput->buttons.D = (((pad>>10)&1)!=0); + theInput->buttons.U = (((pad>>9)&1)!=0); + theInput->buttons.T = (((pad>>8)&1)!=0); + theInput->buttons.S = (((pad>>7)&1)!=0); + theInput->buttons.B = (((pad>>6)&1)!=0); + theInput->buttons.A = (((pad>>5)&1)!=0); + theInput->buttons.Y = (((pad>>4)&1)!=0); + theInput->buttons.X = (((pad>>3)&1)!=0); + theInput->buttons.W = (((pad>>2)&1)!=0); + theInput->buttons.E = (((pad>>1)&1)!=0); + theInput->buttons.G = (((pad>>0)&1)!=0); + theInput->buttons.F = theRecord.command_lid(); + + theInput->touch.touchX = theRecord.touch.x << 4; + theInput->touch.touchY = theRecord.touch.y << 4; + theInput->touch.isTouch = (theRecord.touch.touch != 0); + + theInput->mic.micButtonPressed = (theRecord.command_microphone()) ? 1 : 0; +} + +void DesmumeInputToReplayRec(const UserInput &theInput, MovieRecord *theRecord) +{ + theRecord->commands = 0; + + if(theInput.mic.micButtonPressed == 1) + theRecord->commands = MOVIECMD_MIC; + + theRecord->pad = nds.pad; + + if(theInput.buttons.F) + theRecord->commands = MOVIECMD_LID; + + if(movie_reset_command) { + theRecord->commands = MOVIECMD_RESET; + movie_reset_command = false; + } + + theRecord->touch.touch = theInput.touch.isTouch ? 1 : 0; + theRecord->touch.x = (theInput.touch.isTouch) ? theInput.touch.touchX >> 4 : 0; + theRecord->touch.y = (theInput.touch.isTouch) ? theInput.touch.touchY >> 4 : 0; +} diff --git a/desmume/src/movie.h b/desmume/src/movie.h index a7da82bad..777a6e096 100644 --- a/desmume/src/movie.h +++ b/desmume/src/movie.h @@ -1,5 +1,5 @@ /* - Copyright 2008-2010 DeSmuME team + Copyright 2008-2014 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,6 +29,8 @@ #include "utils/guid.h" #include "utils/md5.h" +struct UserInput; + typedef struct { int movie_version; // version of the movie format in the file @@ -79,10 +81,10 @@ public: //misc commands like reset, etc. //small now to save space; we might need to support more commands later. //the disk format will support up to 64bit if necessary - uint8 commands; - bool command_reset() { return (commands&MOVIECMD_RESET)!=0; } - bool command_microphone() { return (commands&MOVIECMD_MIC)!=0; } - bool command_lid() { return (commands&MOVIECMD_LID)!=0; } + u8 commands; + bool command_reset() const { return (commands&MOVIECMD_RESET)!=0; } + bool command_microphone() const { return (commands&MOVIECMD_MIC)!=0; } + bool command_lid() const { return (commands&MOVIECMD_LID)!=0; } void toggleBit(int bit) { @@ -113,10 +115,10 @@ public: bool Compare(MovieRecord& compareRec); void clear(); - void parse(MovieData* md, EMUFILE* fp); - bool parseBinary(MovieData* md, EMUFILE* fp); - void dump(MovieData* md, EMUFILE* fp, int index); - void dumpBinary(MovieData* md, EMUFILE* fp, int index); + void parse(EMUFILE* fp); + bool parseBinary(EMUFILE* fp); + void dump(EMUFILE* fp); + void dumpBinary(EMUFILE* fp); void parsePad(EMUFILE* fp, u16& pad); void dumpPad(EMUFILE* fp, u16 pad); @@ -228,4 +230,8 @@ extern bool movie_readonly; extern bool ShowInputDisplay; void FCEUI_MakeBackupMovie(bool dispMessage); DateTime FCEUI_MovieGetRTCDefault(); +void BinaryDataFromString(std::string &inStringData, std::vector *outBinaryData); +void ReplayRecToDesmumeInput(const MovieRecord &theRecord, UserInput *theInput); +void DesmumeInputToReplayRec(const UserInput &theInput, MovieRecord *theRecord); + #endif diff --git a/desmume/src/utils/ConvertUTF.h b/desmume/src/utils/ConvertUTF.h index 9c51ddac0..88495033f 100644 --- a/desmume/src/utils/ConvertUTF.h +++ b/desmume/src/utils/ConvertUTF.h @@ -87,6 +87,9 @@ bit mask & shift operations. ------------------------------------------------------------------------ */ +#ifndef __CONVERTUTF_H__ +#define __CONVERTUTF_H__ + #if defined(_MSC_VER) typedef unsigned __int8 uint8_t; typedef unsigned __int16 uint16_t; @@ -154,4 +157,6 @@ Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd); } #endif +#endif // __CONVERTUTF_H__ + /* --------------------------------------------------------------------- */