From 3a4cea91c070603cdba6a8fee8dbbeaa285da173 Mon Sep 17 00:00:00 2001 From: Sour Date: Tue, 20 Mar 2018 22:05:38 -0400 Subject: [PATCH] UI: Added option to allow save states to be loaded even when hash mismatches (if mapper matches) --- Core/BaseMapper.cpp | 32 +++------- Core/BaseMapper.h | 6 +- Core/BaseVideoFilter.cpp | 2 +- Core/Console.cpp | 61 +++++-------------- Core/Console.h | 6 +- Core/Debugger.cpp | 2 +- Core/EmulationSettings.h | 2 + Core/GameServerConnection.cpp | 5 +- Core/HdPackBuilder.cpp | 4 +- Core/LuaApi.cpp | 10 +-- Core/MovieRecorder.cpp | 2 +- Core/RomData.h | 37 ----------- Core/SaveStateManager.cpp | 46 ++++++++++---- Core/SaveStateManager.h | 2 +- Core/Types.h | 51 +++++++++++++++- Core/VsControlManager.cpp | 2 +- GUI.NET/Config/PreferenceInfo.cs | 2 + GUI.NET/Dependencies/resources.ca.xml | 4 +- GUI.NET/Dependencies/resources.es.xml | 3 +- GUI.NET/Dependencies/resources.fr.xml | 3 +- GUI.NET/Dependencies/resources.ja.xml | 3 +- GUI.NET/Dependencies/resources.pt.xml | 3 +- GUI.NET/Dependencies/resources.ru.xml | 3 +- GUI.NET/Dependencies/resources.uk.xml | 3 +- .../Forms/Config/frmPreferences.Designer.cs | 33 +++++++--- GUI.NET/Forms/Config/frmPreferences.cs | 1 + GUI.NET/InteropEmu.cs | 2 + InteropDLL/ConsoleWrapper.cpp | 11 ++-- 28 files changed, 178 insertions(+), 163 deletions(-) diff --git a/Core/BaseMapper.cpp b/Core/BaseMapper.cpp index 730ba64b..d10ad852 100644 --- a/Core/BaseMapper.cpp +++ b/Core/BaseMapper.cpp @@ -706,29 +706,17 @@ shared_ptr 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() diff --git a/Core/BaseMapper.h b/Core/BaseMapper.h index aee07d48..40f6f11b 100644 --- a/Core/BaseMapper.h +++ b/Core/BaseMapper.h @@ -170,11 +170,7 @@ public: virtual void SetDefaultNametables(uint8_t* nametableA, uint8_t* nametableB); shared_ptr 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); diff --git a/Core/BaseVideoFilter.cpp b/Core/BaseVideoFilter.cpp index e79ee082..d5644291 100644 --- a/Core/BaseVideoFilter.cpp +++ b/Core/BaseVideoFilter.cpp @@ -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); diff --git a/Core/Console.cpp b/Core/Console.cpp index 84c05943..151a55a2 100644 --- a/Core/Console.cpp +++ b/Core/Console.cpp @@ -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(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; diff --git a/Core/Console.h b/Core/Console.h index 336d87bf..ede12642 100644 --- a/Core/Console.h +++ b/Core/Console.h @@ -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(); diff --git a/Core/Debugger.cpp b/Core/Debugger.cpp index 2e57cf9f..fdb1ab31 100644 --- a/Core/Debugger.cpp +++ b/Core/Debugger.cpp @@ -36,7 +36,7 @@ string Debugger::_disassemblerOutput = ""; Debugger::Debugger(shared_ptr console, shared_ptr cpu, shared_ptr ppu, shared_ptr apu, shared_ptr memoryManager, shared_ptr mapper) { - _romName = Console::GetRomName(); + _romName = Console::GetMapperInfo().RomName; _console = console; _cpu = cpu; _ppu = ppu; diff --git a/Core/EmulationSettings.h b/Core/EmulationSettings.h index c18ddd44..aea29bad 100644 --- a/Core/EmulationSettings.h +++ b/Core/EmulationSettings.h @@ -77,6 +77,8 @@ enum EmulationFlags : uint64_t DebuggerWindowEnabled = 0x4000000000000, BreakOnCrash = 0x8000000000000, + + AllowMismatchingSaveState = 0x10000000000000, ForceMaxSpeed = 0x4000000000000000, ConsoleMode = 0x8000000000000000, diff --git a/Core/GameServerConnection.cpp b/Core/GameServerConnection.cpp index a2322a72..2bc89931 100644 --- a/Core/GameServerConnection.cpp +++ b/Core/GameServerConnection.cpp @@ -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(); } diff --git a/Core/HdPackBuilder.cpp b/Core/HdPackBuilder.cpp index 7027d868..6d0140e2 100644 --- a/Core/HdPackBuilder.cpp +++ b/Core/HdPackBuilder.cpp @@ -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 << "" << std::to_string(HdNesPack::CurrentVersion) << std::endl; ss << "" << _hdData.Scale << std::endl; - ss << "" << Console::GetHashInfo().Sha1Hash << std::endl; + ss << "" << Console::GetMapperInfo().Hash.Sha1Hash << std::endl; if(_flags & HdPackRecordFlags::IgnoreOverscan) { OverscanDimensions overscan = EmulationSettings::GetOverscanDimensions(); ss << "" << overscan.Top << "," << overscan.Right << "," << overscan.Bottom << "," << overscan.Left << std::endl; diff --git a/Core/LuaApi.cpp b/Core/LuaApi.cpp index 2530065b..882adde4 100644 --- a/Core/LuaApi.cpp +++ b/Core/LuaApi.cpp @@ -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; } diff --git a/Core/MovieRecorder.cpp b/Core/MovieRecorder.cpp index 569fe141..fe01b41c 100644 --- a/Core/MovieRecorder.cpp +++ b/Core/MovieRecorder.cpp @@ -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) { diff --git a/Core/RomData.h b/Core/RomData.h index 36e783da..0bd02b3c 100644 --- a/Core/RomData.h +++ b/Core/RomData.h @@ -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; diff --git a/Core/SaveStateManager.cpp b/Core/SaveStateManager.cpp index 6246e339..91f63517 100644 --- a/Core/SaveStateManager.cpp +++ b/Core/SaveStateManager.cpp @@ -16,7 +16,7 @@ atomic 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)); diff --git a/Core/SaveStateManager.h b/Core/SaveStateManager.h index 0445a308..c2a9b1e4 100644 --- a/Core/SaveStateManager.h +++ b/Core/SaveStateManager.h @@ -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); diff --git a/Core/Types.h b/Core/Types.h index 9cffb845..51adcaf6 100644 --- a/Core/Types.h +++ b/Core/Types.h @@ -291,4 +291,53 @@ public: char Description[10000] = {}; RecordMovieFrom RecordFrom = RecordMovieFrom::StartWithoutSaveData; -}; \ No newline at end of file +}; + +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; +}; diff --git a/Core/VsControlManager.cpp b/Core/VsControlManager.cpp index a6b323d0..c753b08f 100644 --- a/Core/VsControlManager.cpp +++ b/Core/VsControlManager.cpp @@ -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: { diff --git a/GUI.NET/Config/PreferenceInfo.cs b/GUI.NET/Config/PreferenceInfo.cs index 35bf9680..63fbd8e7 100644 --- a/GUI.NET/Config/PreferenceInfo.cs +++ b/GUI.NET/Config/PreferenceInfo.cs @@ -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); diff --git a/GUI.NET/Dependencies/resources.ca.xml b/GUI.NET/Dependencies/resources.ca.xml index 4cbd5189..45fe7dc1 100644 --- a/GUI.NET/Dependencies/resources.ca.xml +++ b/GUI.NET/Dependencies/resources.ca.xml @@ -373,10 +373,12 @@ Drecera #2 Còpies de seguretat - Desat de partida automàtic + Desat de partida Desa automàticament cada minuts (prem F8 per a carregar-la) Mostrar una notificación en pantalla al hacer la copia de seguridad automática + Allow save states to be loaded on modified ROMs (e.g IPS patches) + Còpies de seguretat al núvol Show full file path in recent file list diff --git a/GUI.NET/Dependencies/resources.es.xml b/GUI.NET/Dependencies/resources.es.xml index d5b96651..27f6d900 100644 --- a/GUI.NET/Dependencies/resources.es.xml +++ b/GUI.NET/Dependencies/resources.es.xml @@ -372,10 +372,11 @@ Atajo #2 Copias de seguridad - Guardado de estado automático + Guardado de estado Crear una copia de seguridad de cada estado minutos (Pulse F8 para cargar) Mostrar una notificación en pantalla al hacer la copia de seguridad automática + Allow save states to be loaded on modified ROMs (e.g IPS patches) Copia de seguridad online Show full file path in recent file list diff --git a/GUI.NET/Dependencies/resources.fr.xml b/GUI.NET/Dependencies/resources.fr.xml index a4bd310c..f51f24d1 100644 --- a/GUI.NET/Dependencies/resources.fr.xml +++ b/GUI.NET/Dependencies/resources.fr.xml @@ -382,10 +382,11 @@ Raccourci #2 Sauvegardes - Sauvegarde d'état automatique + Sauvegardes d'état Créer une sauvegarde d'état à chaque minutes (Appuyer sur F8 pour charger) Afficher une notification à l'écran au moment de la sauvegarde automatique + Permettre le chargement de sauvegardes créés dans un autre ROM (ex: IPS) Sauvegarde en ligne 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. diff --git a/GUI.NET/Dependencies/resources.ja.xml b/GUI.NET/Dependencies/resources.ja.xml index e7e52341..9bbb891c 100644 --- a/GUI.NET/Dependencies/resources.ja.xml +++ b/GUI.NET/Dependencies/resources.ja.xml @@ -382,10 +382,11 @@ ショートカットキー2 セーブデータ - オートクイックセーブ + クイックセーブ オートクイックセーブを 分おきにする(F8でクイックロード) オートクイックセーブする際、通信を表示する + 違うROMで作られたクイックセーブをロード可能にする クラウドバックアップ MesenはGoogle Driveを利用することでクラウドバックアップが出来ます。 Google Drive同期を有効にすれば、ゲームのセーブデータはGoogle Driveにバックアップされ、どんなパソコンからでもアクセスが可能になります。 diff --git a/GUI.NET/Dependencies/resources.pt.xml b/GUI.NET/Dependencies/resources.pt.xml index f52ecc9c..26a4a53d 100644 --- a/GUI.NET/Dependencies/resources.pt.xml +++ b/GUI.NET/Dependencies/resources.pt.xml @@ -370,10 +370,11 @@ Atalho #1 Atalho #2 Cópias de segurança - Salvar estado automático + Salvar estado Salvar estado do jogo automaticamente a cada minutos (Aperte F8 para carregar) Mostrar uma notificação na tela ao fazer a cópia de segurança automática + Allow save states to be loaded on modified ROMs (e.g IPS patches) Cópia de segurança online Show full file path in recent file list diff --git a/GUI.NET/Dependencies/resources.ru.xml b/GUI.NET/Dependencies/resources.ru.xml index 54ded9b4..5651eb93 100644 --- a/GUI.NET/Dependencies/resources.ru.xml +++ b/GUI.NET/Dependencies/resources.ru.xml @@ -380,10 +380,11 @@ Вариант #2 Сохранения - Автоматические сохранения + Сохранения Автоматически создавать сохранения через минут (нажмите F8 для загрузки) Оповещать при сохранении + Allow save states to be loaded on modified ROMs (e.g IPS patches) Облачные сохранения Mesen имеет возможность интеграции с Google Drive. Когда интеграция с Google Drive включена, ваши сохранения становятся доступны с любого компьютера и могут быть синхронизированы между компьютерами. Также, сохранения хранящиеся на Google Drive могут быть восстановлены если вы удалите их со своего компьютера. diff --git a/GUI.NET/Dependencies/resources.uk.xml b/GUI.NET/Dependencies/resources.uk.xml index 378e53c7..c2e16744 100644 --- a/GUI.NET/Dependencies/resources.uk.xml +++ b/GUI.NET/Dependencies/resources.uk.xml @@ -380,10 +380,11 @@ Варiант #2 Збереження - Автоматичні збереження + Збереження Автоматично створювати збереження через хвилин (натисніть F8 для завантаження) Сповіщати при збереженні + Allow save states to be loaded on modified ROMs (e.g IPS patches) Хмарнi збереження Mesen має можливість інтеграції з Google Drive . Коли інтеграція з Google Drive включена, ваші збереження стають доступні з будь-якого комп'ютера і можуть бути синхронізовані між комп'ютерами. Також, збереження зберігаються на Google Drive можуть бути відновлені якщо ви видалите їх зі свого комп'ютера. diff --git a/GUI.NET/Forms/Config/frmPreferences.Designer.cs b/GUI.NET/Forms/Config/frmPreferences.Designer.cs index f1d0e921..c39bc8d4 100644 --- a/GUI.NET/Forms/Config/frmPreferences.Designer.cs +++ b/GUI.NET/Forms/Config/frmPreferences.Designer.cs @@ -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; } } \ No newline at end of file diff --git a/GUI.NET/Forms/Config/frmPreferences.cs b/GUI.NET/Forms/Config/frmPreferences.cs index ee13612a..5a0ad0cf 100644 --- a/GUI.NET/Forms/Config/frmPreferences.cs +++ b/GUI.NET/Forms/Config/frmPreferences.cs @@ -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); diff --git a/GUI.NET/InteropEmu.cs b/GUI.NET/InteropEmu.cs index 38351374..0846e028 100644 --- a/GUI.NET/InteropEmu.cs +++ b/GUI.NET/InteropEmu.cs @@ -1532,6 +1532,8 @@ namespace Mesen.GUI DebuggerWindowEnabled = 0x4000000000000, BreakOnCrash = 0x8000000000000, + AllowMismatchingSaveStates = 0x10000000000000, + ForceMaxSpeed = 0x4000000000000000, ConsoleMode = 0x8000000000000000, } diff --git a/InteropDLL/ConsoleWrapper.cpp b/InteropDLL/ConsoleWrapper.cpp index 63c6f8a4..7b8af423 100644 --- a/InteropDLL/ConsoleWrapper.cpp +++ b/InteropDLL/ConsoleWrapper.cpp @@ -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)) {