UI: Added option to allow save states to be loaded even when hash mismatches (if mapper matches)

This commit is contained in:
Sour 2018-03-20 22:05:38 -04:00
parent acf49e4226
commit 3a4cea91c0
28 changed files with 178 additions and 163 deletions

View file

@ -706,29 +706,17 @@ shared_ptr<BaseControlDevice> BaseMapper::GetMapperControlDevice()
return _mapperControlDevice;
}
GameSystem BaseMapper::GetGameSystem()
MapperInfo BaseMapper::GetMapperInfo()
{
return _gameSystem;
}
string BaseMapper::GetRomName()
{
return _romName;
}
RomFormat BaseMapper::GetRomFormat()
{
return _romFormat;
}
uint16_t BaseMapper::GetMapperId()
{
return _mapperID;
}
HashInfo BaseMapper::GetHashInfo()
{
return _hashInfo;
return {
_romName,
_romFormat,
_gameSystem,
_mapperID,
_subMapperID,
_hashInfo,
HasChrRam()
};
}
MirroringType BaseMapper::GetMirroringType()

View file

@ -170,11 +170,7 @@ public:
virtual void SetDefaultNametables(uint8_t* nametableA, uint8_t* nametableB);
shared_ptr<BaseControlDevice> GetMapperControlDevice();
GameSystem GetGameSystem();
HashInfo GetHashInfo();
string GetRomName();
RomFormat GetRomFormat();
uint16_t GetMapperId();
MapperInfo GetMapperInfo();
__forceinline uint8_t ReadRAM(uint16_t addr) override;
uint8_t DebugReadRAM(uint16_t addr);

View file

@ -113,7 +113,7 @@ void BaseVideoFilter::TakeScreenshot(VideoFilterType filterType, string filename
void BaseVideoFilter::TakeScreenshot(VideoFilterType filterType)
{
string romFilename = FolderUtilities::GetFilename(Console::GetRomName(), false);
string romFilename = FolderUtilities::GetFilename(Console::GetMapperInfo().RomName, false);
int counter = 0;
string baseFilename = FolderUtilities::CombinePath(FolderUtilities::GetScreenshotFolder(), romFilename);

View file

@ -83,7 +83,7 @@ bool Console::Initialize(VirtualFile &romFile, VirtualFile &patchFile)
SaveBatteries();
//Save current game state before loading another one
SaveStateManager::SaveRecentGame(_mapper->GetRomName(), _romFilepath, _patchFilename);
SaveStateManager::SaveRecentGame(GetMapperInfo().RomName, _romFilepath, _patchFilename);
}
if(romFile.IsValid()) {
@ -130,7 +130,9 @@ bool Console::Initialize(VirtualFile &romFile, VirtualFile &patchFile)
_cpu.reset(new CPU(_memoryManager.get()));
_apu.reset(new APU(_memoryManager.get()));
switch(_mapper->GetGameSystem()) {
GameSystem system = _mapper->GetMapperInfo().GameSystem;
switch(system) {
case GameSystem::FDS:
EmulationSettings::SetPpuModel(PpuModel::Ppu2C02);
_systemActionManager.reset(new FdsSystemActionManager(Console::GetInstance(), _mapper));
@ -147,7 +149,7 @@ bool Console::Initialize(VirtualFile &romFile, VirtualFile &patchFile)
//Temporarely disable battery saves to prevent battery files from being created for the wrong game (for Battle Box & Turbo File)
BatteryManager::SetSaveEnabled(false);
if(_mapper->GetGameSystem() == GameSystem::VsUniSystem) {
if(system == GameSystem::VsUniSystem) {
_controlManager.reset(new VsControlManager(_systemActionManager, _mapper->GetMapperControlDevice()));
} else {
_controlManager.reset(new ControlManager(_systemActionManager, _mapper->GetMapperControlDevice()));
@ -196,7 +198,7 @@ bool Console::Initialize(VirtualFile &romFile, VirtualFile &patchFile)
string modelName = _model == NesModel::PAL ? "PAL" : (_model == NesModel::Dendy ? "Dendy" : "NTSC");
string messageTitle = MessageManager::Localize("GameLoaded") + " (" + modelName + ")";
MessageManager::DisplayMessage(messageTitle, FolderUtilities::GetFilename(_mapper->GetRomName(), false));
MessageManager::DisplayMessage(messageTitle, FolderUtilities::GetFilename(GetMapperInfo().RomName, false));
if(EmulationSettings::GetOverclockRate() != 100) {
MessageManager::DisplayMessage("ClockRate", std::to_string(EmulationSettings::GetOverclockRate()) + "%");
}
@ -206,7 +208,7 @@ bool Console::Initialize(VirtualFile &romFile, VirtualFile &patchFile)
}
//Reset battery source to current game if new game failed to load
BatteryManager::Initialize(FolderUtilities::GetFilename(GetRomName(), false));
BatteryManager::Initialize(FolderUtilities::GetFilename(GetMapperInfo().RomName, false));
if(_mapper) {
VideoDecoder::GetInstance()->StartThread();
}
@ -227,7 +229,7 @@ bool Console::LoadROM(string romName, HashInfo hashInfo)
{
string currentRomFilepath = Console::GetRomPath().GetFilePath();
if(!currentRomFilepath.empty()) {
HashInfo gameHashInfo = Instance->_mapper->GetHashInfo();
HashInfo gameHashInfo = Console::GetMapperInfo().Hash;
if(gameHashInfo.Crc32Hash == hashInfo.Crc32Hash || gameHashInfo.Sha1Hash.compare(hashInfo.Sha1Hash) == 0 || gameHashInfo.PrgChrMd5Hash.compare(hashInfo.PrgChrMd5Hash) == 0) {
//Current game matches, power cycle game and return
Instance->PowerCycle();
@ -246,7 +248,7 @@ string Console::FindMatchingRom(string romName, HashInfo hashInfo)
{
VirtualFile currentRom = Console::GetRomPath();
if(currentRom.IsValid() && !Console::GetPatchFile().IsValid()) {
HashInfo gameHashInfo = Instance->_mapper->GetHashInfo();
HashInfo gameHashInfo = Console::GetMapperInfo().Hash;
if(gameHashInfo.Crc32Hash == hashInfo.Crc32Hash || gameHashInfo.Sha1Hash.compare(hashInfo.Sha1Hash) == 0 || gameHashInfo.PrgChrMd5Hash.compare(hashInfo.PrgChrMd5Hash) == 0) {
//Current game matches
return currentRom;
@ -281,55 +283,20 @@ VirtualFile Console::GetRomPath()
return static_cast<VirtualFile>(Instance->_romFilepath);
}
string Console::GetRomName()
{
if(Instance->_mapper) {
return Instance->_mapper->GetRomName();
} else {
return "";
}
}
VirtualFile Console::GetPatchFile()
{
return Instance ? (VirtualFile)Instance->_patchFilename : VirtualFile();
}
RomFormat Console::GetRomFormat()
MapperInfo Console::GetMapperInfo()
{
if(Instance->_mapper) {
return Instance->_mapper->GetRomFormat();
return Instance->_mapper->GetMapperInfo();
} else {
return RomFormat::Unknown;
return { };
}
}
uint16_t Console::GetMapperId()
{
if(Instance->_mapper) {
return Instance->_mapper->GetMapperId();
} else {
return 0;
}
}
bool Console::IsChrRam()
{
if(Instance->_mapper) {
return Instance->_mapper->HasChrRam();
} else {
return false;
}
}
HashInfo Console::GetHashInfo()
{
if(Instance->_mapper) {
return Instance->_mapper->GetHashInfo();
} else {
return {};
}
}
NesModel Console::GetModel()
{
return Instance->_model;
@ -543,7 +510,7 @@ void Console::Run()
}
if(!crashed) {
SaveStateManager::SaveRecentGame(_mapper->GetRomName(), _romFilepath, _patchFilename);
SaveStateManager::SaveRecentGame(GetMapperInfo().RomName, _romFilepath, _patchFilename);
}
_rewindManager.reset();
@ -606,7 +573,7 @@ void Console::UpdateNesModel(bool sendNotification)
NesModel model = EmulationSettings::GetNesModel();
if(model == NesModel::Auto) {
switch(_mapper->GetGameSystem()) {
switch(_mapper->GetMapperInfo().GameSystem) {
case GameSystem::NesPal: model = NesModel::PAL; break;
case GameSystem::Dendy: model = NesModel::Dendy; break;
default: model = NesModel::NTSC; break;

View file

@ -120,12 +120,8 @@ class Console
static bool LoadROM(string romName, HashInfo hashInfo);
static string FindMatchingRom(string romName, HashInfo hashInfo);
static VirtualFile GetRomPath();
static string GetRomName();
static VirtualFile GetPatchFile();
static bool IsChrRam();
static RomFormat GetRomFormat();
static uint16_t GetMapperId();
static HashInfo GetHashInfo();
static MapperInfo Console::GetMapperInfo();
static NesModel GetModel();
static uint32_t GetLagCounter();

View file

@ -36,7 +36,7 @@ string Debugger::_disassemblerOutput = "";
Debugger::Debugger(shared_ptr<Console> console, shared_ptr<CPU> cpu, shared_ptr<PPU> ppu, shared_ptr<APU> apu, shared_ptr<MemoryManager> memoryManager, shared_ptr<BaseMapper> mapper)
{
_romName = Console::GetRomName();
_romName = Console::GetMapperInfo().RomName;
_console = console;
_cpu = cpu;
_ppu = ppu;

View file

@ -77,6 +77,8 @@ enum EmulationFlags : uint64_t
DebuggerWindowEnabled = 0x4000000000000,
BreakOnCrash = 0x8000000000000,
AllowMismatchingSaveState = 0x10000000000000,
ForceMaxSpeed = 0x4000000000000000,
ConsoleMode = 0x8000000000000000,

View file

@ -39,7 +39,8 @@ GameServerConnection::~GameServerConnection()
void GameServerConnection::SendGameInformation()
{
Console::Pause();
GameInformationMessage gameInfo(Console::GetRomName(), Console::GetHashInfo().Crc32Hash, _controllerPort, EmulationSettings::CheckFlag(EmulationFlags::Paused));
MapperInfo mapperInfo = Console::GetMapperInfo();
GameInformationMessage gameInfo(mapperInfo.RomName, mapperInfo.Hash.Crc32Hash, _controllerPort, EmulationSettings::CheckFlag(EmulationFlags::Paused));
SendNetMessage(gameInfo);
SaveStateMessage saveState;
SendNetMessage(saveState);
@ -96,7 +97,7 @@ void GameServerConnection::ProcessHandshakeResponse(HandShakeMessage* message)
MessageManager::DisplayMessage("NetPlay", _connectionData->PlayerName + " (" + playerPortMessage + ") connected.");
if(Console::GetRomName().size() > 0) {
if(Console::GetMapperInfo().RomName.size() > 0) {
SendGameInformation();
}

View file

@ -38,7 +38,7 @@ HdPackBuilder::HdPackBuilder(string saveFolder, ScaleFilterType filterType, uint
_hdData.Scale = scale;
}
_romName = FolderUtilities::GetFilename(Console::GetRomName(), false);
_romName = FolderUtilities::GetFilename(Console::GetMapperInfo().RomName, false);
_instance = this;
}
@ -220,7 +220,7 @@ void HdPackBuilder::SaveHdPack()
int pngIndex = 0;
ss << "<ver>" << std::to_string(HdNesPack::CurrentVersion) << std::endl;
ss << "<scale>" << _hdData.Scale << std::endl;
ss << "<supportedRom>" << Console::GetHashInfo().Sha1Hash << std::endl;
ss << "<supportedRom>" << Console::GetMapperInfo().Hash.Sha1Hash << std::endl;
if(_flags & HdPackRecordFlags::IgnoreOverscan) {
OverscanDimensions overscan = EmulationSettings::GetOverscanDimensions();
ss << "<overscan>" << overscan.Top << "," << overscan.Right << "," << overscan.Bottom << "," << overscan.Left << std::endl;

View file

@ -674,17 +674,19 @@ int LuaApi::GetRomInfo(lua_State *lua)
LuaCallHelper l(lua);
checkparams();
MapperInfo mapperInfo = Console::GetMapperInfo();
lua_newtable(lua);
lua_pushstringvalue(name, Console::GetRomName());
lua_pushstringvalue(name, mapperInfo.RomName);
lua_pushstringvalue(path, ((string)Console::GetRomPath()));
HashInfo hashInfo = Console::GetHashInfo();
HashInfo hashInfo = mapperInfo.Hash;
lua_pushintvalue(fileCrc32Hash, hashInfo.Crc32Hash);
lua_pushstringvalue(fileSha1Hash, hashInfo.Sha1Hash);
lua_pushintvalue(prgChrCrc32Hash, hashInfo.PrgCrc32Hash);
lua_pushstringvalue(prgChrMd5Hash, hashInfo.PrgChrMd5Hash);
lua_pushintvalue(format, Console::GetRomFormat());
lua_pushboolvalue(isChrRam, Console::IsChrRam());
lua_pushintvalue(format, mapperInfo.RomFormat);
lua_pushboolvalue(isChrRam, mapperInfo.UsesChrRam);
return 1;
}

View file

@ -73,7 +73,7 @@ void MovieRecorder::GetGameSettings(stringstream &out)
if(patchFile.IsValid()) {
WriteString(out, MovieKeys::PatchFile, patchFile.GetFileName());
WriteString(out, MovieKeys::PatchFileSha1, patchFile.GetSha1Hash());
WriteString(out, MovieKeys::PatchedRomSha1, Console::GetHashInfo().Sha1Hash);
WriteString(out, MovieKeys::PatchedRomSha1, Console::GetMapperInfo().Hash.Sha1Hash);
}
switch(model) {

View file

@ -10,34 +10,6 @@ enum class RomHeaderVersion
OldiNes = 2
};
enum class GameSystem
{
NesNtsc,
NesPal,
Famicom,
Dendy,
VsUniSystem,
Playchoice,
FDS,
Unknown,
};
enum class BusConflictType
{
Default = 0,
Yes,
No
};
struct HashInfo
{
uint32_t Crc32Hash = 0;
uint32_t PrgCrc32Hash = 0;
uint32_t PrgChrCrc32Hash = 0;
string Sha1Hash;
string PrgChrMd5Hash;
};
struct NESHeader
{
/*
@ -278,15 +250,6 @@ struct GameInfo
string SubmapperID;
};
enum class RomFormat
{
Unknown = 0,
iNes = 1,
Unif = 2,
Fds = 3,
Nsf = 4,
};
struct RomData
{
string RomName;

View file

@ -16,7 +16,7 @@ atomic<uint32_t> SaveStateManager::_lastIndex(1);
string SaveStateManager::GetStateFilepath(int stateIndex)
{
string folder = FolderUtilities::GetSaveStateFolder();
string filename = FolderUtilities::GetFilename(Console::GetRomName(), false) + "_" + std::to_string(stateIndex) + ".mst";
string filename = FolderUtilities::GetFilename(Console::GetMapperInfo().RomName, false) + "_" + std::to_string(stateIndex) + ".mst";
return FolderUtilities::CombinePath(folder, filename);
}
@ -61,10 +61,14 @@ void SaveStateManager::SaveState(ostream &stream)
stream.write((char*)&emuVersion, sizeof(emuVersion));
stream.write((char*)&SaveStateManager::FileFormatVersion, sizeof(uint32_t));
string sha1Hash = Console::GetHashInfo().Sha1Hash;
MapperInfo mapperInfo = Console::GetMapperInfo();
stream.write((char*)&mapperInfo.MapperId, sizeof(uint16_t));
stream.write((char*)&mapperInfo.SubMapperId, sizeof(uint8_t));
string sha1Hash = mapperInfo.Hash.Sha1Hash;
stream.write(sha1Hash.c_str(), sha1Hash.size());
string romName = Console::GetRomName();
string romName = mapperInfo.RomName;
uint32_t nameLength = (uint32_t)romName.size();
stream.write((char*)&nameLength, sizeof(uint32_t));
stream.write(romName.c_str(), romName.size());
@ -127,6 +131,17 @@ bool SaveStateManager::LoadState(istream &stream, bool hashCheckRequired)
return false;
}
} else {
int32_t mapperId = -1;
int32_t subMapperId = -1;
if(fileFormatVersion >= 8) {
uint16_t id;
uint8_t sid;
stream.read((char*)&id, sizeof(uint16_t));
stream.read((char*)&sid, sizeof(uint8_t));
mapperId = id;
subMapperId = sid;
}
char hash[41] = {};
stream.read(hash, 40);
@ -137,13 +152,20 @@ bool SaveStateManager::LoadState(istream &stream, bool hashCheckRequired)
stream.read(nameBuffer.data(), nameBuffer.size());
string romName(nameBuffer.data(), nameLength);
if(Console::GetHashInfo().Sha1Hash != string(hash)) {
//Wrong game
HashInfo info;
info.Sha1Hash = hash;
if(!Console::LoadROM(romName, info)) {
MessageManager::DisplayMessage("SaveStates", "SaveStateMissingRom", romName);
return false;
MapperInfo mapperInfo = Console::GetMapperInfo();
bool gameLoaded = !mapperInfo.Hash.Sha1Hash.empty();
if(mapperInfo.Hash.Sha1Hash != string(hash)) {
//CRC doesn't match
if(!EmulationSettings::CheckFlag(EmulationFlags::AllowMismatchingSaveState) || !gameLoaded ||
mapperInfo.MapperId != mapperId || mapperInfo.SubMapperId != subMapperId)
{
//If mismatching states aren't allowed, or a game isn't loaded, or the mapper types don't match, try to find and load the matching ROM
HashInfo info;
info.Sha1Hash = hash;
if(!Console::LoadROM(romName, info)) {
MessageManager::DisplayMessage("SaveStates", "SaveStateMissingRom", romName);
return false;
}
}
}
}
@ -195,8 +217,8 @@ bool SaveStateManager::LoadState(int stateIndex)
void SaveStateManager::SaveRecentGame(string romName, string romPath, string patchPath)
{
if(!EmulationSettings::CheckFlag(EmulationFlags::ConsoleMode) && !EmulationSettings::CheckFlag(EmulationFlags::DisableGameSelectionScreen) && Console::GetRomFormat() != RomFormat::Nsf) {
string filename = FolderUtilities::GetFilename(Console::GetRomName(), false) + ".rgd";
if(!EmulationSettings::CheckFlag(EmulationFlags::ConsoleMode) && !EmulationSettings::CheckFlag(EmulationFlags::DisableGameSelectionScreen) && Console::GetMapperInfo().RomFormat != RomFormat::Nsf) {
string filename = FolderUtilities::GetFilename(Console::GetMapperInfo().RomName, false) + ".rgd";
ZipWriter writer;
writer.Initialize(FolderUtilities::CombinePath(FolderUtilities::GetRecentGamesFolder(), filename));

View file

@ -11,7 +11,7 @@ private:
static string GetStateFilepath(int stateIndex);
public:
static const uint32_t FileFormatVersion = 7;
static const uint32_t FileFormatVersion = 8;
static uint64_t GetStateInfo(int stateIndex);

View file

@ -291,4 +291,53 @@ public:
char Description[10000] = {};
RecordMovieFrom RecordFrom = RecordMovieFrom::StartWithoutSaveData;
};
};
enum class GameSystem
{
NesNtsc,
NesPal,
Famicom,
Dendy,
VsUniSystem,
Playchoice,
FDS,
Unknown,
};
enum class BusConflictType
{
Default = 0,
Yes,
No
};
struct HashInfo
{
uint32_t Crc32Hash = 0;
uint32_t PrgCrc32Hash = 0;
uint32_t PrgChrCrc32Hash = 0;
string Sha1Hash;
string PrgChrMd5Hash;
};
enum class RomFormat
{
Unknown = 0,
iNes = 1,
Unif = 2,
Fds = 3,
Nsf = 4,
};
struct MapperInfo
{
string RomName;
RomFormat RomFormat;
GameSystem GameSystem;
uint16_t MapperId;
uint8_t SubMapperId;
HashInfo Hash;
bool UsesChrRam;
};

View file

@ -100,7 +100,7 @@ uint8_t VsControlManager::ReadRAM(uint16_t addr)
{
uint8_t value = 0;
uint32_t crc = Console::GetHashInfo().PrgCrc32Hash;
uint32_t crc = Console::GetMapperInfo().Hash.PrgCrc32Hash;
switch(addr) {
case 0x4016: {

View file

@ -23,6 +23,7 @@ namespace Mesen.GUI.Config
public bool AutoSave = true;
public Int32 AutoSaveDelay = 5;
public bool AutoSaveNotify = false;
public bool AllowMismatchingSaveStates = false;
public bool FdsAutoLoadDisk = true;
public bool FdsFastForwardOnLoad = false;
@ -176,6 +177,7 @@ namespace Mesen.GUI.Config
InteropEmu.SetFlag(EmulationFlags.PauseWhenInBackground, preferenceInfo.PauseWhenInBackground);
InteropEmu.SetFlag(EmulationFlags.DisableGameDatabase, preferenceInfo.DisableGameDatabase);
InteropEmu.SetFlag(EmulationFlags.DisableOsd, preferenceInfo.DisableOsd);
InteropEmu.SetFlag(EmulationFlags.AllowMismatchingSaveStates, preferenceInfo.AllowMismatchingSaveStates);
InteropEmu.SetFlag(EmulationFlags.ShowFrameCounter, preferenceInfo.ShowFrameCounter);
InteropEmu.SetFlag(EmulationFlags.ShowGameTimer, preferenceInfo.ShowGameTimer);

View file

@ -373,10 +373,12 @@
<Control ID="colBinding2">Drecera #2</Control>
<Control ID="tpgSaveData">Còpies de seguretat</Control>
<Control ID="grpAutomaticSaves">Desat de partida automàtic</Control>
<Control ID="grpAutomaticSaves">Desat de partida</Control>
<Control ID="chkAutoSave">Desa automàticament cada</Control>
<Control ID="lblAutoSave">minuts (prem F8 per a carregar-la)</Control>
<Control ID="chkAutoSaveNotify">Mostrar una notificación en pantalla al hacer la copia de seguridad automática</Control>
<Control ID="chkAllowMismatchingSaveStates">Allow save states to be loaded on modified ROMs (e.g IPS patches)</Control>
<Control ID="grpCloudSaves">Còpies de seguretat al núvol</Control>
<Control ID="chkShowFullPathInRecents">Show full file path in recent file list</Control>

View file

@ -372,10 +372,11 @@
<Control ID="colBinding2">Atajo #2</Control>
<Control ID="tpgSaveData">Copias de seguridad</Control>
<Control ID="grpAutomaticSaves">Guardado de estado automático</Control>
<Control ID="grpAutomaticSaves">Guardado de estado</Control>
<Control ID="chkAutoSave">Crear una copia de seguridad de cada estado</Control>
<Control ID="lblAutoSave">minutos (Pulse F8 para cargar)</Control>
<Control ID="chkAutoSaveNotify">Mostrar una notificación en pantalla al hacer la copia de seguridad automática</Control>
<Control ID="chkAllowMismatchingSaveStates">Allow save states to be loaded on modified ROMs (e.g IPS patches)</Control>
<Control ID="grpCloudSaves">Copia de seguridad online</Control>
<Control ID="chkShowFullPathInRecents">Show full file path in recent file list</Control>

View file

@ -382,10 +382,11 @@
<Control ID="colBinding2">Raccourci #2</Control>
<Control ID="tpgSaveData">Sauvegardes</Control>
<Control ID="grpAutomaticSaves">Sauvegarde d'état automatique</Control>
<Control ID="grpAutomaticSaves">Sauvegardes d'état</Control>
<Control ID="chkAutoSave">Créer une sauvegarde d'état à chaque</Control>
<Control ID="lblAutoSave">minutes (Appuyer sur F8 pour charger)</Control>
<Control ID="chkAutoSaveNotify">Afficher une notification à l'écran au moment de la sauvegarde automatique</Control>
<Control ID="chkAllowMismatchingSaveStates">Permettre le chargement de sauvegardes créés dans un autre ROM (ex: IPS)</Control>
<Control ID="grpCloudSaves">Sauvegarde en ligne</Control>
<Control ID="lblGoogleDriveIntegration">Mesen peut utiliser Google Drive pour mettre vos sauvegardes dans votre compte Google Drive. Lorsque l'intégration est activée, toutes les données de sauvegarde de vos jeux (fichiers .sav et sauvegardes rapides) sont facilement accessibles à partir de n'importe quel ordinateur.</Control>

View file

@ -382,10 +382,11 @@
<Control ID="colBinding2">ショートカットキー2</Control>
<Control ID="tpgSaveData">セーブデータ</Control>
<Control ID="grpAutomaticSaves">オートクイックセーブ</Control>
<Control ID="grpAutomaticSaves">クイックセーブ</Control>
<Control ID="chkAutoSave">オートクイックセーブを</Control>
<Control ID="lblAutoSave">分おきにするF8でクイックロード</Control>
<Control ID="chkAutoSaveNotify">オートクイックセーブする際、通信を表示する</Control>
<Control ID="chkAllowMismatchingSaveStates">違うROMで作られたクイックセーブをロード可能にする</Control>
<Control ID="grpCloudSaves">クラウドバックアップ</Control>
<Control ID="lblGoogleDriveIntegration">MesenはGoogle Driveを利用することでクラウドバックアップが出来ます。 Google Drive同期を有効にすれば、ゲームのセーブデータはGoogle Driveにバックアップされ、どんなパソコンからでもアクセスが可能になります。</Control>

View file

@ -370,10 +370,11 @@
<Control ID="colBinding1">Atalho #1</Control>
<Control ID="colBinding2">Atalho #2</Control>
<Control ID="tpgSaveData">Cópias de segurança</Control>
<Control ID="grpAutomaticSaves">Salvar estado automático</Control>
<Control ID="grpAutomaticSaves">Salvar estado</Control>
<Control ID="chkAutoSave">Salvar estado do jogo automaticamente a cada</Control>
<Control ID="lblAutoSave">minutos (Aperte F8 para carregar)</Control>
<Control ID="chkAutoSaveNotify">Mostrar uma notificação na tela ao fazer a cópia de segurança automática</Control>
<Control ID="chkAllowMismatchingSaveStates">Allow save states to be loaded on modified ROMs (e.g IPS patches)</Control>
<Control ID="grpCloudSaves">Cópia de segurança online</Control>
<Control ID="chkShowFullPathInRecents">Show full file path in recent file list</Control>

View file

@ -380,10 +380,11 @@
<Control ID="colBinding2">Вариант #2</Control>
<Control ID="tpgSaveData">Сохранения</Control>
<Control ID="grpAutomaticSaves">Автоматические сохранения</Control>
<Control ID="grpAutomaticSaves">Сохранения</Control>
<Control ID="chkAutoSave">Автоматически создавать сохранения через</Control>
<Control ID="lblAutoSave">минут (нажмите F8 для загрузки)</Control>
<Control ID="chkAutoSaveNotify">Оповещать при сохранении</Control>
<Control ID="chkAllowMismatchingSaveStates">Allow save states to be loaded on modified ROMs (e.g IPS patches)</Control>
<Control ID="grpCloudSaves">Облачные сохранения</Control>
<Control ID="lblGoogleDriveIntegration">Mesen имеет возможность интеграции с Google Drive. Когда интеграция с Google Drive включена, ваши сохранения становятся доступны с любого компьютера и могут быть синхронизированы между компьютерами. Также, сохранения хранящиеся на Google Drive могут быть восстановлены если вы удалите их со своего компьютера.</Control>

View file

@ -380,10 +380,11 @@
<Control ID="colBinding2">Варiант #2</Control>
<Control ID="tpgSaveData">Збереження</Control>
<Control ID="grpAutomaticSaves">Автоматичні збереження</Control>
<Control ID="grpAutomaticSaves">Збереження</Control>
<Control ID="chkAutoSave">Автоматично створювати збереження через</Control>
<Control ID="lblAutoSave">хвилин (натисніть F8 для завантаження)</Control>
<Control ID="chkAutoSaveNotify">Сповіщати при збереженні</Control>
<Control ID="chkAllowMismatchingSaveStates">Allow save states to be loaded on modified ROMs (e.g IPS patches)</Control>
<Control ID="grpCloudSaves">Хмарнi збереження</Control>
<Control ID="lblGoogleDriveIntegration">Mesen має можливість інтеграції з Google Drive . Коли інтеграція з Google Drive включена, ваші збереження стають доступні з будь-якого комп'ютера і можуть бути синхронізовані між комп'ютерами. Також, збереження зберігаються на Google Drive можуть бути відновлені якщо ви видалите їх зі свого комп'ютера.</Control>

View file

@ -146,6 +146,7 @@ namespace Mesen.GUI.Forms.Config
this.lblUiDisplaySettings = new System.Windows.Forms.Label();
this.lblGameSelectionScreenSettings = new System.Windows.Forms.Label();
this.tmrSyncDateTime = new System.Windows.Forms.Timer(this.components);
this.chkAllowMismatchingSaveStates = new Mesen.GUI.Controls.ctrlRiskyOption();
this.tlpMain.SuspendLayout();
this.flowLayoutPanel2.SuspendLayout();
this.tableLayoutPanel5.SuspendLayout();
@ -517,9 +518,9 @@ namespace Mesen.GUI.Forms.Config
//
this.grpCloudSaves.Controls.Add(this.tlpCloudSaves);
this.grpCloudSaves.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpCloudSaves.Location = new System.Drawing.Point(3, 76);
this.grpCloudSaves.Location = new System.Drawing.Point(3, 99);
this.grpCloudSaves.Name = "grpCloudSaves";
this.grpCloudSaves.Size = new System.Drawing.Size(477, 308);
this.grpCloudSaves.Size = new System.Drawing.Size(477, 285);
this.grpCloudSaves.TabIndex = 2;
this.grpCloudSaves.TabStop = false;
this.grpCloudSaves.Text = "Cloud Saves";
@ -536,7 +537,7 @@ namespace Mesen.GUI.Forms.Config
this.tlpCloudSaves.RowCount = 2;
this.tlpCloudSaves.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tlpCloudSaves.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tlpCloudSaves.Size = new System.Drawing.Size(471, 289);
this.tlpCloudSaves.Size = new System.Drawing.Size(471, 266);
this.tlpCloudSaves.TabIndex = 0;
//
// tlpCloudSaveDesc
@ -688,32 +689,34 @@ namespace Mesen.GUI.Forms.Config
this.grpAutomaticSaves.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpAutomaticSaves.Location = new System.Drawing.Point(3, 3);
this.grpAutomaticSaves.Name = "grpAutomaticSaves";
this.grpAutomaticSaves.Size = new System.Drawing.Size(477, 67);
this.grpAutomaticSaves.Size = new System.Drawing.Size(477, 90);
this.grpAutomaticSaves.TabIndex = 3;
this.grpAutomaticSaves.TabStop = false;
this.grpAutomaticSaves.Text = "Automatic Save States";
this.grpAutomaticSaves.Text = "Save States";
//
// tableLayoutPanel4
//
this.tableLayoutPanel4.ColumnCount = 1;
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel4.Controls.Add(this.chkAutoSaveNotify, 0, 2);
this.tableLayoutPanel4.Controls.Add(this.chkAllowMismatchingSaveStates, 0, 2);
this.tableLayoutPanel4.Controls.Add(this.chkAutoSaveNotify, 0, 1);
this.tableLayoutPanel4.Controls.Add(this.flpAutoSave, 0, 0);
this.tableLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel4.Location = new System.Drawing.Point(3, 16);
this.tableLayoutPanel4.Name = "tableLayoutPanel4";
this.tableLayoutPanel4.RowCount = 3;
this.tableLayoutPanel4.RowCount = 4;
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel4.Size = new System.Drawing.Size(471, 48);
this.tableLayoutPanel4.Size = new System.Drawing.Size(471, 71);
this.tableLayoutPanel4.TabIndex = 0;
//
// chkAutoSaveNotify
//
this.chkAutoSaveNotify.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.chkAutoSaveNotify.AutoSize = true;
this.chkAutoSaveNotify.Location = new System.Drawing.Point(15, 27);
this.chkAutoSaveNotify.Location = new System.Drawing.Point(15, 26);
this.chkAutoSaveNotify.Margin = new System.Windows.Forms.Padding(15, 3, 3, 3);
this.chkAutoSaveNotify.Name = "chkAutoSaveNotify";
this.chkAutoSaveNotify.Size = new System.Drawing.Size(240, 17);
@ -1718,6 +1721,17 @@ namespace Mesen.GUI.Forms.Config
this.tmrSyncDateTime.Enabled = true;
this.tmrSyncDateTime.Tick += new System.EventHandler(this.tmrSyncDateTime_Tick);
//
// chkAllowMismatchingSaveStates
//
this.chkAllowMismatchingSaveStates.Checked = false;
this.chkAllowMismatchingSaveStates.Dock = System.Windows.Forms.DockStyle.Fill;
this.chkAllowMismatchingSaveStates.Location = new System.Drawing.Point(0, 46);
this.chkAllowMismatchingSaveStates.MinimumSize = new System.Drawing.Size(0, 21);
this.chkAllowMismatchingSaveStates.Name = "chkAllowMismatchingSaveStates";
this.chkAllowMismatchingSaveStates.Size = new System.Drawing.Size(471, 23);
this.chkAllowMismatchingSaveStates.TabIndex = 7;
this.chkAllowMismatchingSaveStates.Text = "Allow save states to be loaded on modified ROMs (e.g IPS patches)";
//
// frmPreferences
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@ -1907,5 +1921,6 @@ namespace Mesen.GUI.Forms.Config
private System.Windows.Forms.CheckBox chkGameOverride;
private System.Windows.Forms.CheckBox chkAlwaysOnTop;
private System.Windows.Forms.CheckBox chkShowFullPathInRecents;
private ctrlRiskyOption chkAllowMismatchingSaveStates;
}
}

View file

@ -59,6 +59,7 @@ namespace Mesen.GUI.Forms.Config
AddBinding("AutoSave", chkAutoSave);
AddBinding("AutoSaveDelay", nudAutoSave);
AddBinding("AutoSaveNotify", chkAutoSaveNotify);
AddBinding("AllowMismatchingSaveStates", chkAllowMismatchingSaveStates);
AddBinding("DisplayMovieIcons", chkDisplayMovieIcons);
AddBinding("HidePauseOverlay", chkHidePauseOverlay);

View file

@ -1532,6 +1532,8 @@ namespace Mesen.GUI
DebuggerWindowEnabled = 0x4000000000000,
BreakOnCrash = 0x8000000000000,
AllowMismatchingSaveStates = 0x10000000000000,
ForceMaxSpeed = 0x4000000000000000,
ConsoleMode = 0x8000000000000000,
}

View file

@ -227,11 +227,12 @@ namespace InteropEmu {
if(romPath.empty()) {
_returnString = Console::GetRomPath();
romInfo.RomName = _returnString.c_str();
romInfo.Crc32 = Console::GetHashInfo().Crc32Hash;
romInfo.PrgCrc32 = Console::GetHashInfo().PrgCrc32Hash;
romInfo.Format = Console::GetRomFormat();
romInfo.IsChrRam = Console::IsChrRam();
romInfo.MapperId = Console::GetMapperId();
MapperInfo mapperInfo = Console::GetMapperInfo();
romInfo.Crc32 = mapperInfo.Hash.Crc32Hash;
romInfo.PrgCrc32 = mapperInfo.Hash.PrgCrc32Hash;
romInfo.Format = mapperInfo.RomFormat;
romInfo.IsChrRam = mapperInfo.UsesChrRam;
romInfo.MapperId = mapperInfo.MapperId;
} else {
RomLoader romLoader(true);
if(romLoader.LoadFile(romPath)) {