add "record from sram" (to fix SF bug #828)

This commit is contained in:
zeromus 2018-06-18 22:19:59 -05:00
parent 166e7a8ad9
commit e3b7197128
7 changed files with 107 additions and 9 deletions

View File

@ -76,6 +76,8 @@ uint8 geniech[3];
uint32 genieaddr[3];
CartInfo *currCartInfo;
static INLINE void setpageptr(int s, uint32 A, uint8 *p, int ram) {
uint32 AB = A >> 11;
int x;

View File

@ -25,6 +25,8 @@ typedef struct {
// other code in the future.
} CartInfo;
extern CartInfo *currCartInfo;
void FCEU_SaveGameSave(CartInfo *LocalHWInfo);
void FCEU_LoadGameSave(CartInfo *LocalHWInfo);
void FCEU_ClearGameSave(CartInfo *LocalHWInfo);

View File

@ -851,6 +851,7 @@ static BOOL CALLBACK RecordDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LP
SendDlgItemMessage(hwndDlg, IDC_COMBO_RECORDFROM, CB_INSERTSTRING, i++, (LPARAM)"Start");
SendDlgItemMessage(hwndDlg, IDC_COMBO_RECORDFROM, CB_INSERTSTRING, i++, (LPARAM)"Now");
SendDlgItemMessage(hwndDlg, IDC_COMBO_RECORDFROM, CB_INSERTSTRING, i++, (LPARAM)"SaveRam");
memset(&wfd, 0, sizeof(wfd));
hFind = FindFirstFile(findGlob, &wfd);
@ -941,7 +942,7 @@ static BOOL CALLBACK RecordDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LP
// convert Unicode wstring to UTF8 char* string
WideCharToMultiByte(CP_UTF8, 0, (p->authorName).c_str(), -1, taseditorConfig.lastAuthorName, AUTHOR_NAME_MAX_LEN, 0, 0);
if (lIndex >= 2)
if (lIndex >= 3)
p->szSavestateFilename = GetSavePath(hwndDlg);
EndDialog(hwndDlg, 1);
}
@ -983,11 +984,11 @@ void FCEUD_MovieRecordTo()
if (!GameInfo) return;
static struct CreateMovieParameters p;
p.szFilename = strdup(FCEU_MakeFName(FCEUMKF_MOVIE,0,0).c_str());
if(p.recordFrom >= 2) p.recordFrom=1;
if(p.recordFrom >= 3) p.recordFrom=1;
if(DialogBoxParam(fceu_hInstance, "IDD_RECORDINP", hAppWnd, RecordDialogProc, (LPARAM)&p))
{
if(p.recordFrom >= 2)
if(p.recordFrom >= 3)
{
// attempt to load the savestate
// FIXME: pop open a messagebox if this fails
@ -1006,6 +1007,7 @@ void FCEUD_MovieRecordTo()
EMOVIE_FLAG flags = MOVIE_FLAG_NONE;
if(p.recordFrom == 0) flags = MOVIE_FLAG_FROM_POWERON;
if(p.recordFrom == 2) flags = MOVIE_FLAG_FROM_SAVERAM;
FCEUI_SaveMovie(p.szFilename.c_str(), flags, p.authorName);
}
}

View File

@ -907,6 +907,7 @@ int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode) {
}
GameInterface = iNESGI;
currCartInfo = &iNESCart;
FCEU_printf("\n");
// since apparently the iNES format doesn't store this information,

View File

@ -11,6 +11,7 @@
#include "file.h"
#include "video.h"
#include "movie.h"
#include "cart.h"
#include "fds.h"
#include "vsuni.h"
#ifdef _S9XLUA_H
@ -461,6 +462,16 @@ void MovieData::installValue(std::string& key, std::string& val)
StringToBytes(val,&savestate[0],len); // decodes either base64 or hex
}
}
else if(key == "saveram")
{
int len = Base64StringToBytesLength(val);
if(len == -1) len = HexStringToBytesLength(val); // wasn't base64, try hex
if(len >= 1)
{
saveram.resize(len);
StringToBytes(val,&saveram[0],len); // decodes either base64 or hex
}
}
else if (key == "length")
{
installInt(val, loadFrameCount);
@ -499,6 +510,9 @@ int MovieData::dump(EMUFILE *os, bool binary)
if(savestate.size())
os->fprintf("savestate %s\n" , BytesToString(&savestate[0],savestate.size()).c_str() );
if(saveram.size())
os->fprintf("saveram %s\n" , BytesToString(&saveram[0],saveram.size()).c_str() );
if (this->loadFrameCount >= 0)
os->fprintf("length %d\n" , this->loadFrameCount);
@ -778,6 +792,8 @@ void FCEUI_StopMovie()
#endif
}
bool bogorf;
void poweron(bool shouldDisableBatteryLoading)
{
//// make a for-movie-recording power-on clear the game's save data, too
@ -802,9 +818,9 @@ void poweron(bool shouldDisableBatteryLoading)
//suppressAddPowerCommand=0;
extern int disableBatteryLoading;
disableBatteryLoading = 1;
if(!bogorf) disableBatteryLoading = 1;
PowerNES();
disableBatteryLoading = 0;
if(!bogorf) disableBatteryLoading = 0;
}
void FCEUMOV_CreateCleanMovie()
@ -846,6 +862,59 @@ void MovieData::dumpSavestateTo(std::vector<uint8>* buf, int compressionLevel)
ms.trim();
}
bool MovieData::loadSaveramFrom(std::vector<uint8>* buf)
{
EMUFILE_MEMORY ms(buf);
bool hasBattery = !!ms.read32le();
if(hasBattery != !!currCartInfo->battery)
{
FCEU_PrintError("movie battery load mismatch 1");
return false;
}
for(int i=0;i<4;i++)
{
int len = ms.read32le();
if(!currCartInfo->SaveGame[i] && len!=0)
{
FCEU_PrintError("movie battery load mismatch 2");
return false;
}
if(currCartInfo->SaveGameLen[i] != len)
{
FCEU_PrintError("movie battery load mismatch 3");
return false;
}
ms.fread(currCartInfo->SaveGame[i], len);
}
return true;
}
void MovieData::dumpSaveramTo(std::vector<uint8>* buf, int compressionLevel)
{
EMUFILE_MEMORY ms(buf);
ms.write32le(currCartInfo->battery?1:0);
for(int i=0;i<4;i++)
{
if(!currCartInfo->SaveGame[i])
{
ms.write32le((u32)0);
continue;
}
ms.write32le(currCartInfo->SaveGameLen[i]);
ms.fwrite(currCartInfo->SaveGame[i], currCartInfo->SaveGameLen[i]);
}
}
//begin playing an existing movie
bool FCEUI_LoadMovie(const char *fname, bool _read_only, int _pauseframe)
{
@ -901,7 +970,14 @@ bool FCEUI_LoadMovie(const char *fname, bool _read_only, int _pauseframe)
movieFromPoweron = false;
bool success = MovieData::loadSavestateFrom(&currMovieData.savestate);
if(!success) return true; //adelikat: I guess return true here? False is only for a bad movie filename, if it got this far the file was good?
} else {
}
else if(currMovieData.saveram.size())
{
movieFromPoweron = true;
bool success = MovieData::loadSaveramFrom(&currMovieData.saveram);
if(!success) return true; //adelikat: I guess return true here? False is only for a bad movie filename, if it got this far the file was good?
}
else {
movieFromPoweron = true;
}
@ -981,7 +1057,15 @@ void FCEUI_SaveMovie(const char *fname, EMOVIE_FLAG flags, std::wstring author)
movieFromPoweron = true;
poweron(true);
}
else
else if(flags & MOVIE_FLAG_FROM_SAVERAM)
{
movieFromPoweron = true;
MovieData::dumpSaveramTo(&currMovieData.saveram,Z_NO_COMPRESSION); //i guess with this there's a chance someone could hack the file, at least, so maybe it's helpfu
bogorf = true;
poweron(false);
bogorf = false;
}
else //from savestate
{
movieFromPoweron = false;
MovieData::dumpSavestateTo(&currMovieData.savestate,Z_BEST_COMPRESSION);

View File

@ -23,13 +23,15 @@ enum EMOVIE_FLAG
MOVIE_FLAG_PAL = (1<<2),
//movie was recorded from poweron. the alternative is from a savestate (or from reset)
//movie was recorded from poweron. the alternative is from a savestate (or from reset). OR from saveram.
MOVIE_FLAG_FROM_POWERON = (1<<3),
// set in newer version, used for old movie compatibility
//TODO - only use this flag to print a warning that the sync might be bad
//so that we can get rid of the sync hack code
MOVIE_FLAG_NOSYNCHACK = (1<<4)
MOVIE_FLAG_NOSYNCHACK = (1<<4),
MOVIE_FLAG_FROM_SAVERAM = (1<<5)
};
typedef struct
@ -178,6 +180,7 @@ public:
MD5DATA romChecksum;
std::string romFilename;
std::vector<uint8> savestate;
std::vector<uint8> saveram;
std::vector<MovieRecord> records;
std::vector<std::wstring> comments;
std::vector<std::string> subtitles;
@ -241,6 +244,9 @@ public:
static bool loadSavestateFrom(std::vector<uint8>* buf);
static void dumpSavestateTo(std::vector<uint8>* buf, int compressionLevel);
static bool loadSaveramFrom(std::vector<uint8>* buf);
static void dumpSaveramTo(std::vector<uint8>* buf, int compressionLevel);
private:
void installInt(std::string& val, int& var)
{

View File

@ -618,6 +618,7 @@ int UNIFLoad(const char *name, FCEUFILE *fp) {
strcpy(LoadedRomFName, name); //For the debugger list
GameInterface = UNIFGI;
currCartInfo = &UNIFCart;
return 1;
aborto: