Merge pull request #187 from SuuperW/movies

Movies
This commit is contained in:
zeromus 2018-09-13 18:44:28 -04:00 committed by GitHub
commit e828070d4d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 479 additions and 271 deletions

View File

@ -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)
{

View File

@ -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());
}
}

View File

@ -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);

View File

@ -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;
@ -243,8 +247,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 +259,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 +320,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 +409,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;
}

View File

@ -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();

View File

@ -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

View File

@ -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"

View File

@ -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
@ -66,6 +68,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 +201,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 +209,31 @@ MovieData::MovieData()
, binaryFlag(false)
, rtcStart(FCEUI_MovieGetRTCDefault())
{
if (fromCurrentSettings)
{
useExtBios = CommonSettings.UseExtBIOS;
if (useExtBios)
swiFromBios = CommonSettings.SWIFromBIOS;
useExtFirmware = CommonSettings.UseExtFirmware;
if (useExtFirmware)
bootFromFirmware = CommonSettings.BootFromFirmware;
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)
@ -211,68 +242,48 @@ 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::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);
}
@ -287,13 +298,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)
{
@ -315,6 +325,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++)
@ -323,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());
@ -343,104 +355,116 @@ 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)
{
//TODO - start with something different. like 'desmume movie version 1"
int curr = fp.ftell();
int endOfMovie;
if (size == INT_MAX)
endOfMovie = fp.size();
else
endOfMovie = fp.ftell() + size;
//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, COMMENT
} 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();
// 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, size);
return true;
}
switch(state)
{
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:
if (stopAfterHeader) break;
else if (movieData.binaryFlag)
{
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;
LoadFM2_binarychunk(movieData, fp, endOfMovie - fp.ftell());
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;
else
{
int currcount = movieData.records.size();
movieData.records.resize(currcount + 1);
movieData.records[currcount].parse(fp);
}
}
else // key value
{
fp.unget();
std::string key = readUntilWhitespace(fp);
readUntilNotWhitespace(fp);
std::string 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;
}
// just in case readUntilNotWhitespace read past the limit set by size parameter
fp.fseek(endOfMovie, SEEK_SET);
return true;
}
@ -454,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.");
@ -469,7 +493,7 @@ static void FinishPlayback()
}
/// Stop movie recording
// Stop movie recording
static void StopRecording()
{
driver->USR_InfoMessage("Movie recording stopped.");
@ -491,7 +515,66 @@ void FCEUI_StopMovie()
freshMovie = false;
}
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 != "")
{
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] = movieData.firmNickname[i];
}
if (movieData.firmMessage != "")
{
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] = movieData.firmMessage[i];
}
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 (movieData.advancedTiming != -1)
CommonSettings.advanced_timing = movieData.advancedTiming;
if (movieData.jitBlockSize > 0 && movieData.jitBlockSize <= 100)
{
CommonSettings.use_jit = true;
CommonSettings.jit_max_block_size = movieData.jitBlockSize;
}
else
CommonSettings.use_jit = false;
}
void UnloadMovieEmulationSettings()
{
if (oldSettings && !firstReset)
{
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)
{
@ -514,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";
@ -552,20 +610,26 @@ 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)
// set emulation/firmware settings
oldSettings = new MovieData(true);
LoadSettingsFromMovie(currMovieData);
if (currMovieData.savestate)
{
NDS_CreateDummyFirmware(&CommonSettings.fw_config);
// 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;
}
NDS_Reset();
////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;
@ -646,7 +710,7 @@ bool MovieData::loadSramFrom(std::vector<u8>* 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;
@ -675,15 +739,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)
{
// 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
{
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);

View File

@ -28,6 +28,8 @@
#include "utils/guid.h"
#include "utils/md5.h"
#include "replay.h"
struct UserInput;
class EMUFILE;
@ -132,8 +134,7 @@ private:
class MovieData
{
public:
MovieData();
MovieData(bool fromCurrentSettings = false);
int version;
int emuVersion;
@ -142,7 +143,7 @@ public:
u32 romChecksum;
std::string romSerial;
std::string romFilename;
std::vector<u8> savestate;
bool savestate = false;
std::vector<u8> sram;
std::vector<MovieRecord> records;
std::vector<std::wstring> comments;
@ -155,6 +156,21 @@ public:
//was the frame data stored in binary?
bool binaryFlag;
int useExtBios = -1;
int swiFromBios = -1;
int useExtFirmware = -1;
int bootFromFirmware = -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<std::string,std::string>
@ -191,22 +207,65 @@ public:
void clearRecordRange(int start, int len);
void insertEmpty(int at, int frames);
static bool loadSavestateFrom(std::vector<u8>* buf);
static void dumpSavestateTo(std::vector<u8>* buf, int compressionLevel);
static bool loadSramFrom(std::vector<u8>* buf);
//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 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()); }
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 installSavestate(std::string& val) { savestate = atoi(val.c_str()) != 0; }
void installBool(std::string& val, bool& var)
{
var = atoi(val.c_str())!=0;
}
void installRomChecksum(std::string& val);
void installRtcStart(std::string& val);
void installComment(std::string& val);
void installSram(std::string& val);
typedef void(MovieData::* ivm)(std::string&);
std::map<std::string, ivm> 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},
{"useExtBios", &MovieData::installUseExtBios},
{"swiFromBios", &MovieData::installSwiFromBios},
{"useExtFirmware", &MovieData::installUseExtFirmware},
{"bootFromFirmware", &MovieData::installBootFromFirmware},
{"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}
};
};
extern int currFrameCounter;
@ -216,8 +275,10 @@ 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();
void FCEUI_StopMovie();
void FCEUMOV_AddInputState();
void FCEUMOV_HandlePlayback();

View File

@ -1042,12 +1042,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)
{

View File

@ -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