movie.cpp:

- Do some preliminary cleanup of the code.
- Fix bug where firmware nicknames and messages weren't being saved properly.
This commit is contained in:
rogerman 2014-01-25 00:39:52 +00:00
parent 088495f0cd
commit db94b7c8a6
3 changed files with 128 additions and 113 deletions

View File

@ -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 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 it under the terms of the GNU General Public License as published by
@ -23,6 +23,7 @@
#include "utils/guid.h" #include "utils/guid.h"
#include "utils/xstring.h" #include "utils/xstring.h"
#include "utils/datetime.h" #include "utils/datetime.h"
#include "utils/ConvertUTF.h"
#include "movie.h" #include "movie.h"
#include "NDSSystem.h" #include "NDSSystem.h"
#include "readwrite.h" #include "readwrite.h"
@ -87,8 +88,6 @@ void MovieData::insertEmpty(int at, int frames)
} }
} }
void MovieRecord::clear() void MovieRecord::clear()
{ {
pad = 0; pad = 0;
@ -96,7 +95,6 @@ void MovieRecord::clear()
touch.padding = 0; touch.padding = 0;
} }
bool MovieRecord::Compare(MovieRecord& compareRec) bool MovieRecord::Compare(MovieRecord& compareRec)
{ {
//Check pad //Check pad
@ -137,7 +135,6 @@ void MovieRecord::dumpPad(EMUFILE* fp, u16 pad)
} }
} }
void MovieRecord::parsePad(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(EMUFILE* fp)
void MovieRecord::parse(MovieData* md, EMUFILE* fp)
{ {
//by the time we get in here, the initial pipe has already been extracted //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 //should be left at a newline
} }
void MovieRecord::dump(EMUFILE* fp)
void MovieRecord::dump(MovieData* md, EMUFILE* fp, int index)
{ {
//dump the misc commands //dump the misc commands
//*os << '|' << setw(1) << (int)commands; //*os << '|' << setw(1) << (int)commands;
@ -212,7 +207,6 @@ void MovieData::truncateAt(int frame)
records.resize(frame); records.resize(frame);
} }
void MovieData::installValue(std::string& key, std::string& val) 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 //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); installBool(val,binaryFlag);
else if(key == "savestate") else if(key == "savestate")
{ {
int len = Base64StringToBytesLength(val); BinaryDataFromString(val, &this->savestate);
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
}
} }
else if(key == "sram") else if(key == "sram")
{ {
int len = Base64StringToBytesLength(val); BinaryDataFromString(val, &this->sram);
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
}
} }
} }
@ -314,23 +296,20 @@ int MovieData::dump(EMUFILE* fp, bool binary)
fp->fprintf("bootFromFirmware %d\n", CommonSettings.BootFromFirmware?1:0); fp->fprintf("bootFromFirmware %d\n", CommonSettings.BootFromFirmware?1:0);
} }
else { else {
char temp_str[27]; UTF8 fwNicknameUTF8[MAX_FW_NICKNAME_LENGTH*4];
int i; UTF8 *fwNicknameUTF8Start = fwNicknameUTF8;
const UTF16 *fwNicknameUTF16 = (const UTF16 *)CommonSettings.fw_config.nickname;
/* FIXME: harshly only use the lower byte of the UTF-16 character. memset(fwNicknameUTF8, 0, sizeof(fwNicknameUTF8));
* This would cause strange behaviour if the user could set UTF-16 but ConvertUTF16toUTF8(&fwNicknameUTF16, fwNicknameUTF16 + CommonSettings.fw_config.nickname_len, &fwNicknameUTF8Start, fwNicknameUTF8Start + sizeof(fwNicknameUTF8), strictConversion);
* they cannot yet.
*/ UTF8 fwMessageUTF8[MAX_FW_MESSAGE_LENGTH*4];
for (i = 0; i < CommonSettings.fw_config.nickname_len; i++) { UTF8 *fwMessageUTF8Start = fwMessageUTF8;
temp_str[i] = CommonSettings.fw_config.nickname[i]; const UTF16 *fwMessageUTF16 = (const UTF16 *)CommonSettings.fw_config.message;
} memset(fwMessageUTF8, 0, sizeof(fwMessageUTF8));
temp_str[i] = '\0'; ConvertUTF16toUTF8(&fwMessageUTF16, fwMessageUTF16 + CommonSettings.fw_config.message_len, &fwMessageUTF8Start, fwMessageUTF8Start + sizeof(fwMessageUTF8), strictConversion);
fp->fprintf("firmNickname %s\n", temp_str);
for (i = 0; i < CommonSettings.fw_config.message_len; i++) { fp->fprintf("firmNickname %s\n", fwNicknameUTF8);
temp_str[i] = CommonSettings.fw_config.message[i]; fp->fprintf("firmMessage %s\n", fwMessageUTF8);
}
temp_str[i] = '\0';
fp->fprintf("firmMessage %s\n", temp_str);
fp->fprintf("firmFavColour %d\n", CommonSettings.fw_config.fav_colour); fp->fprintf("firmFavColour %d\n", CommonSettings.fw_config.fav_colour);
fp->fprintf("firmBirthMonth %d\n", CommonSettings.fw_config.birth_month); fp->fprintf("firmBirthMonth %d\n", CommonSettings.fw_config.birth_month);
fp->fprintf("firmBirthDay %d\n", CommonSettings.fw_config.birth_day); 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 //put one | to start the binary dump
fp->fputc('|'); fp->fputc('|');
for(int i=0;i<(int)records.size();i++) for(int i=0;i<(int)records.size();i++)
records[i].dumpBinary(this,fp,i); records[i].dumpBinary(fp);
} }
else else
for(int i=0;i<(int)records.size();i++) for(int i=0;i<(int)records.size();i++)
records[i].dump(this,fp,i); records[i].dump(fp);
int end = fp->ftell(); int end = fp->ftell();
return end-start; return end-start;
@ -420,7 +399,7 @@ bool LoadFM2(MovieData& movieData, EMUFILE* fp, int size, bool stopAfterHeader)
int currcount = movieData.records.size(); int currcount = movieData.records.size();
movieData.records.resize(currcount+1); movieData.records.resize(currcount+1);
int preparse = fp->ftell(); int preparse = fp->ftell();
movieData.records[currcount].parse(&movieData, fp); movieData.records[currcount].parse(fp);
int postparse = fp->ftell(); int postparse = fp->ftell();
size -= (postparse-preparse); size -= (postparse-preparse);
state = NEWLINE; state = NEWLINE;
@ -749,36 +728,8 @@ void FCEUI_SaveMovie(const char *fname, std::wstring author, int flag, std::stri
} }
else else
{ {
UserInput& input = NDS_getProcessingUserInput(); UserInput &input = NDS_getProcessingUserInput();
ReplayRecToDesmumeInput(currMovieData.records[currFrameCounter], &input);
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;
} }
//if we are on the last frame, then pause the emulator if the player requested it //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) if(movieMode == MOVIEMODE_RECORD)
{ {
const UserInput& input = NDS_getFinalUserInput();
MovieRecord mr; MovieRecord mr;
const UserInput &input = NDS_getFinalUserInput();
mr.commands = 0; DesmumeInputToReplayRec(input, &mr);
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;
assert(mr.touch.touch || (!mr.touch.x && !mr.touch.y)); assert(mr.touch.touch || (!mr.touch.x && !mr.touch.y));
//assert(nds.touchX == input.touch.touchX && nds.touchY == input.touch.touchY); //assert(nds.touchX == input.touch.touchX && nds.touchY == input.touch.touchY);
//assert((mr.touch.x << 4) == nds.touchX && (mr.touch.y << 4) == nds.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); currMovieData.records.push_back(mr);
// it's apparently un-threadsafe to do this here // 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; return true;
} }
bool MovieRecord::parseBinary(MovieData* md, EMUFILE* fp) bool MovieRecord::parseBinary(EMUFILE* fp)
{ {
commands=fp->fgetc(); commands=fp->fgetc();
fp->fread((char *) &pad, sizeof pad); 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->fputc(this->commands);
fp->fwrite((char *) &md->records[index].pad, sizeof md->records[index].pad); fp->fwrite((char *) &this->pad, sizeof(this->pad));
fp->fwrite((char *) &md->records[index].touch.x, sizeof md->records[index].touch.x); fp->fwrite((char *) &this->touch.x, sizeof(this->touch.x));
fp->fwrite((char *) &md->records[index].touch.y, sizeof md->records[index].touch.y); fp->fwrite((char *) &this->touch.y, sizeof(this->touch.y));
fp->fwrite((char *) &md->records[index].touch.touch, sizeof md->records[index].touch.touch); fp->fwrite((char *) &this->touch.touch, sizeof(this->touch.touch));
} }
void LoadFM2_binarychunk(MovieData& movieData, EMUFILE* fp, int size) 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); movieData.records.resize(numRecords);
for(int i=0;i<numRecords;i++) for(int i=0;i<numRecords;i++)
{ {
movieData.records[i].parseBinary(&movieData,fp); movieData.records[i].parseBinary(fp);
} }
} }
@ -1268,3 +1200,75 @@ void FCEUI_MakeBackupMovie(bool dispMessage)
} }
} }
void BinaryDataFromString(std::string &inStringData, std::vector<u8> *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;
}

View File

@ -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 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 it under the terms of the GNU General Public License as published by
@ -29,6 +29,8 @@
#include "utils/guid.h" #include "utils/guid.h"
#include "utils/md5.h" #include "utils/md5.h"
struct UserInput;
typedef struct typedef struct
{ {
int movie_version; // version of the movie format in the file int movie_version; // version of the movie format in the file
@ -79,10 +81,10 @@ public:
//misc commands like reset, etc. //misc commands like reset, etc.
//small now to save space; we might need to support more commands later. //small now to save space; we might need to support more commands later.
//the disk format will support up to 64bit if necessary //the disk format will support up to 64bit if necessary
uint8 commands; u8 commands;
bool command_reset() { return (commands&MOVIECMD_RESET)!=0; } bool command_reset() const { return (commands&MOVIECMD_RESET)!=0; }
bool command_microphone() { return (commands&MOVIECMD_MIC)!=0; } bool command_microphone() const { return (commands&MOVIECMD_MIC)!=0; }
bool command_lid() { return (commands&MOVIECMD_LID)!=0; } bool command_lid() const { return (commands&MOVIECMD_LID)!=0; }
void toggleBit(int bit) void toggleBit(int bit)
{ {
@ -113,10 +115,10 @@ public:
bool Compare(MovieRecord& compareRec); bool Compare(MovieRecord& compareRec);
void clear(); void clear();
void parse(MovieData* md, EMUFILE* fp); void parse(EMUFILE* fp);
bool parseBinary(MovieData* md, EMUFILE* fp); bool parseBinary(EMUFILE* fp);
void dump(MovieData* md, EMUFILE* fp, int index); void dump(EMUFILE* fp);
void dumpBinary(MovieData* md, EMUFILE* fp, int index); void dumpBinary(EMUFILE* fp);
void parsePad(EMUFILE* fp, u16& pad); void parsePad(EMUFILE* fp, u16& pad);
void dumpPad(EMUFILE* fp, u16 pad); void dumpPad(EMUFILE* fp, u16 pad);
@ -228,4 +230,8 @@ extern bool movie_readonly;
extern bool ShowInputDisplay; extern bool ShowInputDisplay;
void FCEUI_MakeBackupMovie(bool dispMessage); void FCEUI_MakeBackupMovie(bool dispMessage);
DateTime FCEUI_MovieGetRTCDefault(); DateTime FCEUI_MovieGetRTCDefault();
void BinaryDataFromString(std::string &inStringData, std::vector<u8> *outBinaryData);
void ReplayRecToDesmumeInput(const MovieRecord &theRecord, UserInput *theInput);
void DesmumeInputToReplayRec(const UserInput &theInput, MovieRecord *theRecord);
#endif #endif

View File

@ -87,6 +87,9 @@
bit mask & shift operations. bit mask & shift operations.
------------------------------------------------------------------------ */ ------------------------------------------------------------------------ */
#ifndef __CONVERTUTF_H__
#define __CONVERTUTF_H__
#if defined(_MSC_VER) #if defined(_MSC_VER)
typedef unsigned __int8 uint8_t; typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t; typedef unsigned __int16 uint16_t;
@ -154,4 +157,6 @@ Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd);
} }
#endif #endif
#endif // __CONVERTUTF_H__
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */