From 92107d94dfb1c4884fc23da33c21a16748a669e5 Mon Sep 17 00:00:00 2001 From: Souryo Date: Sun, 9 Apr 2017 22:44:13 -0400 Subject: [PATCH] UPS patch support --- Core/Console.cpp | 8 +- Core/Console.h | 4 +- Core/MapperFactory.cpp | 4 +- Core/MapperFactory.h | 2 +- Core/MessageManager.cpp | 28 +++--- Core/RomLoader.cpp | 30 ++++-- Core/RomLoader.h | 5 +- GUI.NET/Dependencies/resources.en.xml | 4 +- GUI.NET/Dependencies/resources.es.xml | 6 +- GUI.NET/Dependencies/resources.fr.xml | 6 +- GUI.NET/Dependencies/resources.ja.xml | 8 +- GUI.NET/Dependencies/resources.pt.xml | 6 +- GUI.NET/Dependencies/resources.ru.xml | 6 +- GUI.NET/Dependencies/resources.uk.xml | 6 +- .../Forms/Config/frmPreferences.Designer.cs | 2 +- GUI.NET/Forms/frmMain.cs | 46 +++++++-- GUI.NET/InteropEmu.cs | 2 +- InteropDLL/ConsoleWrapper.cpp | 2 +- PGOHelper/PGOHelper.cpp | 2 +- Utilities/UpsPatcher.cpp | 99 +++++++++++++++++++ Utilities/UpsPatcher.h | 12 +++ Utilities/Utilities.vcxproj | 2 + Utilities/Utilities.vcxproj.filters | 6 ++ 23 files changed, 229 insertions(+), 67 deletions(-) create mode 100644 Utilities/UpsPatcher.cpp create mode 100644 Utilities/UpsPatcher.h diff --git a/Core/Console.cpp b/Core/Console.cpp index 583fca9b..2e56a234 100644 --- a/Core/Console.cpp +++ b/Core/Console.cpp @@ -42,7 +42,7 @@ void Console::Release() Console::Instance.reset(new Console()); } -void Console::Initialize(string romFilename, stringstream *filestream, string ipsFilename, int32_t archiveFileIndex) +void Console::Initialize(string romFilename, stringstream *filestream, string patchFilename, int32_t archiveFileIndex) { SoundMixer::StopAudio(); @@ -52,7 +52,7 @@ void Console::Initialize(string romFilename, stringstream *filestream, string ip } MessageManager::SendNotification(ConsoleNotificationType::GameStopped); - shared_ptr mapper = MapperFactory::InitializeFromFile(romFilename, filestream, ipsFilename, archiveFileIndex); + shared_ptr mapper = MapperFactory::InitializeFromFile(romFilename, filestream, patchFilename, archiveFileIndex); if(mapper) { _romFilepath = romFilename; @@ -109,10 +109,10 @@ void Console::Initialize(string romFilename, stringstream *filestream, string ip } } -void Console::LoadROM(string filepath, stringstream *filestream, int32_t archiveFileIndex, string ipsFile) +void Console::LoadROM(string filepath, stringstream *filestream, int32_t archiveFileIndex, string patchFilepath) { Console::Pause(); - Instance->Initialize(filepath, filestream, ipsFile, archiveFileIndex); + Instance->Initialize(filepath, filestream, patchFilepath, archiveFileIndex); Console::Resume(); } diff --git a/Core/Console.h b/Core/Console.h index f42717ea..aebccebe 100644 --- a/Core/Console.h +++ b/Core/Console.h @@ -47,7 +47,7 @@ class Console bool _initialized = false; void ResetComponents(bool softReset); - void Initialize(string filename, stringstream *filestream = nullptr, string ipsFilename = "", int32_t archiveFileIndex = -1); + void Initialize(string filename, stringstream *filestream = nullptr, string patchFilename = "", int32_t archiveFileIndex = -1); void UpdateNesModel(bool sendNotification); double GetFrameDelay(); @@ -73,7 +73,7 @@ class Console static void LoadState(istream &loadStream); static void LoadState(uint8_t *buffer, uint32_t bufferSize); - static void LoadROM(string filepath, stringstream *filestream = nullptr, int32_t archiveFileIndex = -1, string ipsFile = ""); + static void LoadROM(string filepath, stringstream *filestream = nullptr, int32_t archiveFileIndex = -1, string patchFilepath = ""); static bool LoadROM(string romName, uint32_t crc32Hash); static string GetROMPath(); static string GetRomName(); diff --git a/Core/MapperFactory.cpp b/Core/MapperFactory.cpp index 192490f8..51623662 100644 --- a/Core/MapperFactory.cpp +++ b/Core/MapperFactory.cpp @@ -543,11 +543,11 @@ BaseMapper* MapperFactory::GetMapperFromID(RomData &romData) return nullptr; } -shared_ptr MapperFactory::InitializeFromFile(string romFilename, stringstream *filestream, string ipsFilename, int32_t archiveFileIndex) +shared_ptr MapperFactory::InitializeFromFile(string romFilename, stringstream *filestream, string patchFilename, int32_t archiveFileIndex) { RomLoader loader; - if(loader.LoadFile(romFilename, filestream, ipsFilename, archiveFileIndex)) { + if(loader.LoadFile(romFilename, filestream, patchFilename, archiveFileIndex)) { RomData romData = loader.GetRomData(); shared_ptr mapper(GetMapperFromID(romData)); diff --git a/Core/MapperFactory.h b/Core/MapperFactory.h index 84110dd7..522344cf 100644 --- a/Core/MapperFactory.h +++ b/Core/MapperFactory.h @@ -12,5 +12,5 @@ class MapperFactory static const uint16_t FdsMapperID = 65535; static const uint16_t NsfMapperID = 65534; - static shared_ptr InitializeFromFile(string romFilename, stringstream *filestream, string ipsFilename, int32_t archiveFileIndex); + static shared_ptr InitializeFromFile(string romFilename, stringstream *filestream, string patchFilename, int32_t archiveFileIndex); }; diff --git a/Core/MessageManager.cpp b/Core/MessageManager.cpp index ba549603..8e5f0386 100644 --- a/Core/MessageManager.cpp +++ b/Core/MessageManager.cpp @@ -12,7 +12,7 @@ std::unordered_map MessageManager::_enResources = { { "Error", u8"Error" }, { "GameInfo", u8"Game Info" }, { "GameLoaded", u8"Game loaded" }, - { "IPS", u8"IPS" }, + { "Patch", u8"Patch" }, { "Movies", u8"Movies" }, { "NetPlay", u8"Net Play" }, { "Region", u8"Region" }, @@ -22,7 +22,7 @@ std::unordered_map MessageManager::_enResources = { { "Test", u8"Test" }, { "VideoRecorder", u8"Video Recorder" }, - { "ApplyingIps", u8"Applying patch: %1" }, + { "ApplyingPatch", u8"Applying patch: %1" }, { "CheatApplied", u8"1 cheat applied." }, { "CheatsApplied", u8"%1 cheats applied." }, { "CheatsDisabled", u8"All cheats disabled." }, @@ -80,7 +80,7 @@ std::unordered_map MessageManager::_frResources = { { "Error", u8"Erreur" }, { "GameInfo", u8"Info sur le ROM" }, { "GameLoaded", u8"Jeu chargé" }, - { "IPS", u8"IPS" }, + { "Patch", u8"Patch" }, { "Movies", u8"Films" }, { "NetPlay", u8"Jeu en ligne" }, { "Region", u8"Région" }, @@ -90,7 +90,7 @@ std::unordered_map MessageManager::_frResources = { { "Test", u8"Test" }, { "VideoRecorder", u8"Enregistreur vidéo" }, - { "ApplyingIps", u8"Fichier IPS appliqué : %1" }, + { "ApplyingPatch", u8"Patch appliqué : %1" }, { "CheatApplied", u8"%1 code activé." }, { "CheatsApplied", u8"%1 codes activés." }, { "CheatsDisabled", u8"Tous les codes ont étés désactivés." }, @@ -148,7 +148,7 @@ std::unordered_map MessageManager::_jaResources = { { "Error", u8"エラー" }, { "GameInfo", u8"ゲーム情報" }, { "GameLoaded", u8"ゲーム開始" }, - { "IPS", u8"IPS" }, + { "Patch", u8"パッチ" }, { "Movies", u8"動画" }, { "NetPlay", u8"ネットプレー" }, { "Region", u8"地域" }, @@ -158,7 +158,7 @@ std::unordered_map MessageManager::_jaResources = { { "Test", u8"テスト" }, { "VideoRecorder", u8"動画レコーダー" }, - { "ApplyingIps", u8"パッチファイルを適用しました: %1" }, + { "ApplyingPatch", u8"パッチファイルを適用しました: %1" }, { "CheatApplied", u8"チートコード%1個を有効にしました。" }, { "CheatsApplied", u8"チートコード%1個を有効にしました。" }, { "CheatsDisabled", u8"チートコードを無効にしました。" }, @@ -216,7 +216,7 @@ std::unordered_map MessageManager::_ruResources = { { "Error", u8"Ошибка" }, { "GameInfo", u8"Информация об игре" }, { "GameLoaded", u8"Игра загружена" }, - { "IPS", u8"IPS" }, + { "Patch", u8"Patch" }, { "Movies", u8"Записи" }, { "NetPlay", u8"Игра по сети" }, { "Region", u8"Регион" }, @@ -226,7 +226,7 @@ std::unordered_map MessageManager::_ruResources = { { "Test", u8"Тест" }, { "VideoRecorder", u8"Video Recorder" }, - { "ApplyingIps", u8"Применён патч: %1" }, + { "ApplyingPatch", u8"Применён патч: %1" }, { "CheatApplied", u8"1 Чит применён." }, { "CheatsApplied", u8"Читов применено %1" }, { "CheatsDisabled", u8"All cheats disabled." }, @@ -284,7 +284,7 @@ std::unordered_map MessageManager::_esResources = { { "Error", u8"Error" }, { "GameInfo", u8"Info del Juego" }, { "GameLoaded", u8"Juego Cargado" }, - { "IPS", u8"IPS" }, + { "Patch", u8"Patch" }, { "Movies", u8"Videos" }, { "NetPlay", u8"Juego Online" }, { "Region", u8"Región" }, @@ -294,7 +294,7 @@ std::unordered_map MessageManager::_esResources = { { "Test", u8"Test" }, { "VideoRecorder", u8"Video Recorder" }, - { "ApplyingIps", u8"Aplicando parche: %1" }, + { "ApplyingPatch", u8"Aplicando parche: %1" }, { "CheatApplied", u8"1 truco aplicado." }, { "CheatsApplied", u8"%1 trucos aplicados." }, { "CheatsDisabled", u8"All cheats disabled." }, @@ -353,7 +353,7 @@ std::unordered_map MessageManager::_ukResources = { { "Error", u8"Помилка" }, { "GameInfo", u8"Інформація про гру" }, { "GameLoaded", u8"Гра завантажена" }, - { "IPS", u8"IPS" }, + { "Patch", u8"Patch" }, { "Movies", u8"Записи" }, { "NetPlay", u8"Гра по мережi" }, { "Region", u8"Регiон" }, @@ -363,7 +363,7 @@ std::unordered_map MessageManager::_ukResources = { { "Test", u8"Тест" }, { "VideoRecorder", u8"Video Recorder" }, - { "ApplyingIps", u8"Застосовано патч: %1" }, + { "ApplyingPatch", u8"Застосовано патч: %1" }, { "CheatApplied", u8"1 Чiт застосований." }, { "CheatsApplied", u8"Чiтів застосовано %1" }, { "CheatsDisabled", u8"All cheats disabled." }, @@ -421,7 +421,7 @@ std::unordered_map MessageManager::_ptResources = { { "Error", u8"Erro" }, { "GameInfo", u8"Informações do Jogo" }, { "GameLoaded", u8"Jogo Carregado" }, - { "IPS", u8"IPS" }, + { "Patch", u8"Patch" }, { "Movies", u8"Vídeos" }, { "NetPlay", u8"Jogo Online" }, { "Region", u8"Região" }, @@ -431,7 +431,7 @@ std::unordered_map MessageManager::_ptResources = { { "Test", u8"Teste" }, { "VideoRecorder", u8"Video Recorder" }, - { "ApplyingIps", u8"Aplicando patch: %1" }, + { "ApplyingPatch", u8"Aplicando patch: %1" }, { "CheatApplied", u8"1 cheat aplicado." }, { "CheatsApplied", u8"%1 cheats aplicados." }, { "CheatsDisabled", u8"All cheats disabled." }, diff --git a/Core/RomLoader.cpp b/Core/RomLoader.cpp index 23c52d34..cc3506b9 100644 --- a/Core/RomLoader.cpp +++ b/Core/RomLoader.cpp @@ -3,6 +3,7 @@ #include "../Utilities/ArchiveReader.h" #include "../Utilities/CRC32.h" #include "../Utilities/IpsPatcher.h" +#include "../Utilities/UpsPatcher.h" #include "../Utilities/ZipReader.h" #include "../Utilities/SZReader.h" #include "RomLoader.h" @@ -94,14 +95,29 @@ uint8_t* RomLoader::ReadFile(istream &file, uint32_t &fileSize) return buffer; } +void RomLoader::ApplyPatch(string patchPath, vector &data) +{ + //Apply patch file + MessageManager::DisplayMessage("Patch", "ApplyingPatch", FolderUtilities::GetFilename(patchPath, true)); + ifstream patchFile(patchPath, ios::binary | ios::in); + if(patchFile.good()) { + char buffer[5] = {}; + patchFile.read(buffer, 5); + patchFile.close(); + if(memcmp(buffer, "PATCH", 5) == 0) { + data = IpsPatcher::PatchBuffer(patchPath, data); + } else if(memcmp(buffer, "UPS1", 4) == 0) { + data = UpsPatcher::PatchBuffer(patchPath, data); + } + } +} + bool RomLoader::LoadFromMemory(uint8_t* buffer, size_t length, string romName) { vector fileData(buffer, buffer + length); - - if(!_ipsFilename.empty()) { - //Apply IPS patch - MessageManager::DisplayMessage("IPS", "ApplyingIps", FolderUtilities::GetFilename(_ipsFilename, true)); - fileData = IpsPatcher::PatchBuffer(_ipsFilename, fileData); + + if(!_patchFilename.empty()) { + ApplyPatch(_patchFilename, fileData); } uint32_t crc = CRC32::GetCRC(buffer, length); @@ -155,10 +171,10 @@ bool RomLoader::LoadFromMemory(uint8_t* buffer, size_t length, string romName) return !_romData.Error; } -bool RomLoader::LoadFile(string filename, istream *filestream, string ipsFilename, int32_t archiveFileIndex) +bool RomLoader::LoadFile(string filename, istream *filestream, string patchFilename, int32_t archiveFileIndex) { _filename = filename; - _ipsFilename = ipsFilename; + _patchFilename = patchFilename; ifstream file; istream* input = nullptr; diff --git a/Core/RomLoader.h b/Core/RomLoader.h index 7ab553a9..53702f7b 100644 --- a/Core/RomLoader.h +++ b/Core/RomLoader.h @@ -8,7 +8,7 @@ class RomLoader private: RomData _romData; string _filename; - string _ipsFilename; + string _patchFilename; bool LoadFromArchive(istream &zipFile, ArchiveReader& reader, int32_t archiveFileIndex = -1); bool LoadFromStream(istream &romFile, string romName); @@ -17,9 +17,10 @@ class RomLoader uint8_t* ReadFile(istream &file, uint32_t &fileSize); bool LoadFromMemory(uint8_t* buffer, size_t length, string romName); static int32_t FindMatchingRomInFile(string filename, uint32_t crc32Hash); + void ApplyPatch(string patchPath, vector &data); public: - bool LoadFile(string filename, istream *filestream = nullptr, string ipsFilename = "", int32_t archiveFileIndex = -1); + bool LoadFile(string filename, istream *filestream = nullptr, string patchFilename = "", int32_t archiveFileIndex = -1); RomData GetRomData(); static string FindMatchingRomInFolder(string folder, string romFilename, uint32_t crc32Hash, bool useFastSearch, int32_t &archiveFileIndex); static vector GetArchiveRomList(string filename); diff --git a/GUI.NET/Dependencies/resources.en.xml b/GUI.NET/Dependencies/resources.en.xml index e9718db1..b5e2908c 100644 --- a/GUI.NET/Dependencies/resources.en.xml +++ b/GUI.NET/Dependencies/resources.en.xml @@ -7,7 +7,7 @@ Avi files (*.avi)|*.avi|All Files (*.*)|*.* Palette Files (*.pal)|*.pal|All Files (*.*)|*.* All supported formats (*.nes, *.zip, *.7z, *.nsf, *.nsfe, *.fds, *.unf)|*.NES;*.ZIP;*.7z;*.FDS;*.NSF;*.NSFE;*.UNF|NES Roms (*.nes, *.unf)|*.NES;*.UNF|Famicom Disk System Roms (*.fds)|*.FDS|NSF files (*.nsf, *.nsfe)|*.nsf;*.nsfe|ZIP Archives (*.zip)|*.ZIP|7-Zip Archives (*.7z)|*.7z|All (*.*)|*.* - All supported formats (*.nes, *.zip, *.7z, *.fds, *.nsf, *.nsfe, *.unf, *.ips)|*.NES;*.ZIP;*.7z;*.IPS;*.FDS;*.NSF;*.NSFE;*.UNF|NES Roms (*.nes, *.unf)|*.NES;*.UNF|Famicom Disk System Roms (*.fds)|*.FDS|NSF files (*.nsf, *.nsfe)|*.nsf;*.nsfe|ZIP Archives (*.zip)|*.ZIP|7-Zip Archives (*.7z)|*.7z|IPS Patches (*.ips)|*.IPS|All (*.*)|*.* + All supported formats (*.nes, *.zip, *.7z, *.fds, *.nsf, *.nsfe, *.unf, *.ips, *.ups)|*.NES;*.ZIP;*.7z;*.IPS;*.UPS;*.FDS;*.NSF;*.NSFE;*.UNF|NES Roms (*.nes, *.unf)|*.NES;*.UNF|Famicom Disk System Roms (*.fds)|*.FDS|NSF files (*.nsf, *.nsfe)|*.nsf;*.nsfe|ZIP Archives (*.zip)|*.ZIP|7-Zip Archives (*.7z)|*.7z|IPS/UPS Patches (*.ips, *.ups)|*.IPS;*.UPS|All (*.*)|*.* Test files (*.mtp)|*.mtp|All (*.*)|*.* All supported formats (*.cht, *.xml)|*.cht;*.xml @@ -42,7 +42,7 @@ This option allows Mesen to load HDNes-format HD packs if they are found. HD Packs should be placed in the "HdPacks" folder in a subfolder matching the name of the ROM. e.g: MyRom.nes should have their HD Pack in "HdPacks\MyRom\hires.txt". Note: Support for HD Packs is a work in progress and some limitations remain. You are running the latest version of Mesen Patch and reset the current game? - Please select a ROM matching the IPS patch file. + Please select a ROM matching the IPS/UPS patch file. Unable to download file. Check your internet connection and try again. Details: {0} Mesen could not launch because it was unable to load MesenCore.dll due to missing dependencies. Mesen was unable to start due to missing files. Error: MesenCore.dll is missing. diff --git a/GUI.NET/Dependencies/resources.es.xml b/GUI.NET/Dependencies/resources.es.xml index 9c425be1..81f985f5 100644 --- a/GUI.NET/Dependencies/resources.es.xml +++ b/GUI.NET/Dependencies/resources.es.xml @@ -325,7 +325,7 @@ Pausar la emulación al finalizar el video Permitir entradas aunque Mesen esté en segundo plano Pausar la emulación aunque Mesen esté en segundo plano - Cargar los archivos IPS automáticamente + Cargar los archivos IPS/UPS automáticamente Abrir el directorio de Mesen Asociación de archivos Asociación de archivos @@ -516,7 +516,7 @@ Archivos avi (*.avi)|*.avi|Todos los archivos (*.*)|*.* Archivos pal (*.pal)|*.pal|Todos los archivos (*.*)|*.* Todos los formatos soportados (*.nes, *.zip, *.7z, *.fds, *.nsf, *.nsfe, *.unf)|*.NES;*.ZIP;*.7z;*.FDS;*.NSF;*.NSFE;*.UNF|Roms de NES (*.nes, *.unf)|*.NES;*.UNF|Roms de Famicom Disk System (*.fds)|*.FDS|Archivos NSF (*.nsf, *.nsfe)|*.NSF;*.NSFE|Archivos ZIP (*.zip)|*.ZIP|Archivos 7-Zip (*.7z)|*.7z|Todos los archivos (*.*)|*.* - Todos los formatos soportados (*.nes, *.zip, *.7z, *.fds, *.nsf, *.nsfe, *.unf, *.ips)|*.NES;*.ZIP;*.7z;*.IPS;*.FDS;*.NSF;*.NSFE;*.UNF|Roms de NES(*.nes, *.unf)|*.NES;*.UNF|Roms de Famicom Disk System (*.fds)|*.FDS|Archivos NSF (*.nsf, *.nsfe)|*.NSF;*.NSFE|Archivos ZIP (*.zip)|*.ZIP|Archivos 7-Zip (*.7z)|*.7z|Archivos IPS (*.ips)|*.IPS|Todos los archivos (*.*)|*.* + Todos los formatos soportados (*.nes, *.zip, *.7z, *.fds, *.nsf, *.nsfe, *.unf, *.ips, *.ups)|*.NES;*.ZIP;*.7z;*.IPS;*.UPS;*.FDS;*.NSF;*.NSFE;*.UNF|Roms de NES(*.nes, *.unf)|*.NES;*.UNF|Roms de Famicom Disk System (*.fds)|*.FDS|Archivos NSF (*.nsf, *.nsfe)|*.NSF;*.NSFE|Archivos ZIP (*.zip)|*.ZIP|Archivos 7-Zip (*.7z)|*.7z|Archivos IPS/UPS (*.ips, *.ups)|*.IPS;*.UPS|Todos los archivos (*.*)|*.* Archivos de test (*.mtp)|*.mtp|Todos los archivos (*.*)|*.* Todos los formatos soportados (*.cht, *.xml)|*.cht;*.xml @@ -550,7 +550,7 @@ Esta opción permite los paquetes de gráficos en alta resolución de carga Mesen en el mismo formato que los del emulador HDNes. Los paquetes de alta resolución deberán ser colocados en los "HdPacks" en una subcarpeta con el nombre de la ROM. Ejemplo: Un paquete para "MiRom.nes" debe estar colocado en "HdPacks\MiRom\hires.txt". Nota: El soporte para paquetes de alta resolución aún no es perfecto - algunas limitaciones siguen presentes. Ya utiliza la versión mas reciente de Mesen. ¿Aplicar el parche y reiniciar el juego? - Elija la ROM que corresponde al archivo IPS seleccionado. + Elija la ROM que corresponde al archivo IPS/UPS seleccionado. No se puede descargar el archivo. Compruebe su conexión a Internet e inténtelo de nuevo. Detalles del error: {0} Mesen no puede inciarse porque porque no puede cargar MesenCore.dll debido a dependencias no encontradas. Mesen no puede iniciarse debido a que faltan archivos. Error: No se encuentra el archivo MesenCore.dll. diff --git a/GUI.NET/Dependencies/resources.fr.xml b/GUI.NET/Dependencies/resources.fr.xml index b4b0fa33..84344de4 100644 --- a/GUI.NET/Dependencies/resources.fr.xml +++ b/GUI.NET/Dependencies/resources.fr.xml @@ -327,7 +327,7 @@ Pauser l'émulation à la fin d'un film Permettre les entrées lorsque Mesen est en arrière-plan Pauser l'émulation lorsque Mesen est en arrière-plan - Charger les fichiers IPS automatiquement + Charger les fichiers IPS/UPS automatiquement Ouvrir le dossier de Mesen Associations de fichiers Associations de fichiers @@ -530,7 +530,7 @@ Fichiers avi (*.avi)|*.avi|Tous les fichiers (*.*)|*.* Fichier de palette (*.pal)|*.pal|Tous les fichiers (*.*)|*.* Tous les formats supportés (*.nes, *.zip, *.7z, *.fds, *.nsf, *.nsfe, *.unf)|*.NES;*.ZIP;*.7z;*.FDS;*.NSF;*.NSFE;*.UNF|Roms de NES (*.nes, *.unf)|*.NES;*.UNF|Roms du Famicom Disk System (*.fds)|*.FDS|Fichiers NSF (*.nsf, *.nsfe)|*.NSF;*.NSFE|Fichiers ZIP (*.zip)|*.ZIP|Fichiers 7-Zip (*.7z)|*.7z|Tous les fichiers (*.*)|*.* - Tous les formats supportés (*.nes, *.zip, *.7z, *.fds, *.nsf, *.nsfe, *.unf, *.ips)|*.NES;*.ZIP;*.7z;*.IPS;*.FDS;*.NSF;*.NSFE;*.UNF|Roms de NES (*.nes, *.unf)|*.NES;*.UNF|Roms du Famicom Disk System (*.fds)|*.FDS|Fichiers NSF (*.nsf, *.nsfe)|*.NSF;*.NSFE|Fichiers ZIP (*.zip)|*.ZIP|Fichiers 7-Zip (*.7z)|*.7z|Fichiers IPS (*.ips)|*.IPS|Tous les fichiers (*.*)|*.* + Tous les formats supportés (*.nes, *.zip, *.7z, *.fds, *.nsf, *.nsfe, *.unf, *.ips, *.ups)|*.NES;*.ZIP;*.7z;*.IPS;*.UPS;*.FDS;*.NSF;*.NSFE;*.UNF|Roms de NES (*.nes, *.unf)|*.NES;*.UNF|Roms du Famicom Disk System (*.fds)|*.FDS|Fichiers NSF (*.nsf, *.nsfe)|*.NSF;*.NSFE|Fichiers ZIP (*.zip)|*.ZIP|Fichiers 7-Zip (*.7z)|*.7z|Fichiers IPS/UPS (*.ips, *.ups)|*.IPS;*.UPS|Tous les fichiers (*.*)|*.* Fichiers de test (*.mtp)|*.mtp|Tous les fichiers (*.*)|*.* Tous les formats supportés (*.cht, *.xml)|*.cht;*.xml @@ -565,7 +565,7 @@ Cette option permet à Mesen de charger des packages de graphiques haute-résolution dans le même format que l'émulateur HDNes. Les packages haute-résolution doivent être placés dans le dossier "HdPacks", dans un sous-dossier correspondant au nom du ROM. Exemple : Un package pour "MonRom.nes" doit être placé dans "HdPacks\MonRom\hires.txt". Note: Le support pour les packages haute-résolution n'est pas encore parfait - certaines limitations sont encore présentes. Vous utilisez déjà la version la plus récente de Mesen. Appliquer la patch et faire un reset du jeu? - Choisissez un ROM qui correspond au fichier IPS choisi. + Choisissez un ROM qui correspond au fichier IPS/UPS choisi. Impossible de télécharger le fichier. Vérifier votre connexion internet et essayez à nouveau. Détails de l'erreur: {0} Mesen n'a pas été en mesure de charger le fichier MesenCore.dll, et ne peut donc pas être lancé. Mesen est incapable de démarrer puisqu'il manque des fichiers. Erreur: Le fichier MesenCore.dll est introuvable. diff --git a/GUI.NET/Dependencies/resources.ja.xml b/GUI.NET/Dependencies/resources.ja.xml index 81dc8c69..a5bb00fe 100644 --- a/GUI.NET/Dependencies/resources.ja.xml +++ b/GUI.NET/Dependencies/resources.ja.xml @@ -326,7 +326,7 @@ 動画が終わると自動的にポーズする Mesenが最前面ではない時、コントローラは反応しない Mesenが最前面ではない時、自動的にポーズする - 自動的にIPSファイルをロードする + 自動的にパッチファイル(IPS・UPS)をロードする Mesenのフォルダを開く ファイルの関連付け ファイルの関連付け @@ -512,7 +512,7 @@ AVIファイル (*.avi)|*.avi|すべてのファイル (*.*)|*.* パレットファイル (*.pal)|*.pal|すべてのファイル (*.*)|*.* 対応するすべてのファイル (*.nes, *.zip, *.7z, *.fds, *.nsf, *.nsfe, *.unf)|*.NES;*.ZIP;*.FDS;*.7z;*.NSF;*.NSFE;*.UNF|ファミコンゲーム (*.nes, *.unf)|*.NES;*.UNF|ファミコンディスクシステムのゲーム (*.fds)|*.FDS|NSFファイル (*.nsf, *.nsfe)|*.NSF;*.NSFE|ZIPファイル (*.zip)|*.ZIP|7-Zipファイル (*.7z)|*.7z|すべてのファイル (*.*)|*.* - 対応するすべてのファイル (*.nes, *.zip, *.7z, *.fds, *.nsf, *.nsfe, *.unf, *.ips)|*.NES;*.ZIP;*.7z;*.IPS;*.FDS;*.NSF;*.NSFE;*.UNF|ファミコンゲーム (*.nes, *.unf)|*.NES;*.UNF|ファミコンディスクシステムのゲーム (*.fds)|*.FDS|NSFファイル (*.nsf, *.nsfe)|*.NSF;*.NSFE|ZIPファイル (*.zip)|*.ZIP|7-Zipファイル (*.7z)|*.7z|IPSファイル (*.ips)|*.IPS|すべてのファイル (*.*)|*.* + 対応するすべてのファイル (*.nes, *.zip, *.7z, *.fds, *.nsf, *.nsfe, *.unf, *.ips, *.ups)|*.NES;*.ZIP;*.7z;*.IPS;*.UPS;*.FDS;*.NSF;*.NSFE;*.UNF|ファミコンゲーム (*.nes, *.unf)|*.NES;*.UNF|ファミコンディスクシステムのゲーム (*.fds)|*.FDS|NSFファイル (*.nsf, *.nsfe)|*.NSF;*.NSFE|ZIPファイル (*.zip)|*.ZIP|7-Zipファイル (*.7z)|*.7z|パッチファイル (*.ips, *.ups)|*.IPS;*.UPS|すべてのファイル (*.*)|*.* テストファイル (*.mtp)|*.mtp|すべてのファイル (*.*)|*.* 対応するすべてのファイル (*.cht, *.xml)|*.cht;*.xml @@ -546,8 +546,8 @@ 選んだBIOSファイルは使えません。 このオプションを有効にすれば、MesenはHDNesのようにHDパックをロード出来るようになります。 HDパックはMesenのフォルダの中にある「HdPacks」のフォルダにゲームと同じ名前のサブフォルダに置くと自動的にロードされます。 例)ゲームファイルは「MyRom.nes」なら、「HdPacks\MyRom」にHDパックを置くとロードされます。 この機能はまだ開発中で、不完全なところがあります、ご了承ください。 既にMesenの最新のバージョンを使っています。 - IPSパッチを当てて、ゲームをリセットしますか? - IPSファイルに合うゲームファイルを選んでください。 + パッチファイルを当てて、ゲームをリセットしますか? + パッチファイルに合うゲームファイルを選んでください。 ファイルをダウンロードできませんでした。ネット接続を確認してから、再試行してください。 エラーの詳細: {0} MesenはMesenCore.dllをロード出来なかったため、起動できませんでした。 必要なファイルはロード出来なかったため、Mesenは起動できません。 エラー: MesenCore.dllはロードできません。 diff --git a/GUI.NET/Dependencies/resources.pt.xml b/GUI.NET/Dependencies/resources.pt.xml index ebe3338c..b4bca61f 100644 --- a/GUI.NET/Dependencies/resources.pt.xml +++ b/GUI.NET/Dependencies/resources.pt.xml @@ -325,7 +325,7 @@ Pausar a emulação ao finalizar o vídeo Permitir inputs quando Mesen estiver em segundo plano Pausar a emulação quando Mesen estiver em segundo plano - Carregar os arquivos IPS automaticamente + Carregar os arquivos IPS/UPS automaticamente Abrir a pasta de Mesen Associação de arquivos Associação de arquivos @@ -516,7 +516,7 @@ Arquivos avi (*.avi)|*.avi|Todos os arquivos (*.*)|*.* Arquivos pal (*.pal)|*.pal|Todos os arquivos (*.*)|*.* Todos os formatos suportados (*.nes, *.zip, *.7z, *.fds, *.nsf, *.nsfe, *.unf)|*.NES;*.ZIP;*.7z;*.FDS;*.NSF;*.NSFE;*.UNF|Roms de NES (*.nes, *.unf)|*.NES;*.UNF|Roms de Famicom Disk System (*.fds)|*.FDS|Arquivos NSF (*.nsf, *.nsfe)|*.NSF;*.NSFE|Arquivos ZIP (*.zip)|*.ZIP|Arquivos 7-Zip (*.7z)|*.7z|Todos os arquivos (*.*)|*.* - Todos os formatos suportados (*.nes, *.zip, *.7z, *.fds, *.nsf, *.nsfe, *.unf, *.ips)|*.NES;*.ZIP;*.7z;*.IPS;*.FDS;*.NSF;*.NSFE;*.UNF|Roms de NES(*.nes, *.unf)|*.NES;*.UNF|Roms de Famicom Disk System (*.fds)|*.FDS|Arquivos NSF (*.nsf, *.nsfe)|*.NSF;*.NSFE|Arquivos ZIP (*.zip)|*.ZIP|Arquivos 7-Zip (*.7z)|*.7z|Arquivos IPS (*.ips)|*.IPS|Todos os arquivos (*.*)|*.* + Todos os formatos suportados (*.nes, *.zip, *.7z, *.fds, *.nsf, *.nsfe, *.unf, *.ips, *.ups)|*.NES;*.ZIP;*.7z;*.IPS;*.UPS;*.FDS;*.NSF;*.NSFE;*.UNF|Roms de NES(*.nes, *.unf)|*.NES;*.UNF|Roms de Famicom Disk System (*.fds)|*.FDS|Arquivos NSF (*.nsf, *.nsfe)|*.NSF;*.NSFE|Arquivos ZIP (*.zip)|*.ZIP|Arquivos 7-Zip (*.7z)|*.7z|Arquivos IPS/UPS (*.ips, *.ups)|*.IPS;*.UPS|Todos os arquivos (*.*)|*.* Arquivos de teste (*.mtp)|*.mtp|Todos os arquivos (*.*)|*.* Todos os formatos suportados (*.cht, *.xml)|*.cht;*.xml @@ -550,7 +550,7 @@ Esta opção permite os pacotes de gráficos de alta resolução sejam carregados no mesmo formato que os do emulador HDNes. Os pacotes de alta resolução devem ser colocados nos "HdPacks" em uma subpasta com o mesmo nome da ROM. Exemplo: Um pacote para "MinhaRom.nes" deve ser colocado em "HdPacks\MinhaRom\hires.txt". Nota: O suporte para os pacotes de alta resolução não é perfeito - algumas limitações seguem presentes. Já utiliza a versão mais recente do Mesen. Aplicar o patch e reiniciar o jogo? - Selecione a ROM que corresponde ao arquivo IPS selecionado. + Selecione a ROM que corresponde ao arquivo IPS/UPS selecionado. Não foi possível baixar o arquivo. Verifique sua conexão com a internet e tente de novo. Detalhes do erro: {0} Mesen não pode iniciar pois foi incapaz de carregar MesenCore.dll devido a falta de dependências. Mesen não pode iniciar devido a falta de arquivos. Erro: Não se encontra o arquivo MesenCore.dll. diff --git a/GUI.NET/Dependencies/resources.ru.xml b/GUI.NET/Dependencies/resources.ru.xml index 28b955f5..c98f2323 100644 --- a/GUI.NET/Dependencies/resources.ru.xml +++ b/GUI.NET/Dependencies/resources.ru.xml @@ -326,7 +326,7 @@ Ставить на паузу после проигрывания записи Разрешить ввод в фоне Ставить на паузу при потере фокуса - Автоматически загружать IPS + Автоматически загружать IPS/UPS Открыть папку Mesen Ассоциации файлов Ассоциации файлов @@ -520,7 +520,7 @@ Avi файлы (*.avi)|*.avi|All Files (*.*)|*.* Файлы палитры (*.pal)|*.pal|All Files (*.*)|*.* Все поддерживаемые форматы (*.nes, *.zip, *.7z, *.nsf, *.nsfe, *.fds, *.unf)|*.NES;*.ZIP;*.7z;*.FDS;*.NSF;*.NSFE;*.UNF|NES Roms (*.nes, *.unf)|*.NES;*.UNF|Famicom Disk System Roms (*.fds)|*.FDS|NSF files (*.nsf, *.nsfe)|*.nsf;*.nsfe|ZIP Archives (*.zip)|*.ZIP|7-Zip Archives (*.7z)|*.7z|All (*.*)|*.* - Все поддерживаемые форматы (*.nes, *.zip, *.7z, *.fds, *.nsf, *.nsfe, *.unf, *.ips)|*.NES;*.ZIP;*.7z;*.IPS;*.FDS;*.NSF;*.NSFE;*.UNF|NES Roms (*.nes, *.unf)|*.NES;*.UNF|Famicom Disk System Roms (*.fds)|*.FDS|NSF files (*.nsf, *.nsfe)|*.nsf;*.nsfe|ZIP Archives (*.zip)|*.ZIP|7-Zip Archives (*.7z)|*.7z|IPS Patches (*.ips)|*.IPS|All (*.*)|*.* + Все поддерживаемые форматы (*.nes, *.zip, *.7z, *.fds, *.nsf, *.nsfe, *.unf, *.ips, *.ups)|*.NES;*.ZIP;*.7z;*.IPS;*.UPS;*.FDS;*.NSF;*.NSFE;*.UNF|NES Roms (*.nes, *.unf)|*.NES;*.UNF|Famicom Disk System Roms (*.fds)|*.FDS|NSF files (*.nsf, *.nsfe)|*.nsf;*.nsfe|ZIP Archives (*.zip)|*.ZIP|7-Zip Archives (*.7z)|*.7z|IPS/UPS Patches (*.ips, *.ups)|*.IPS;*.UPS|All (*.*)|*.* Test files (*.mtp)|*.mtp|All (*.*)|*.* Все поддерживаемые форматы (*.cht, *.xml)|*.cht;*.xml @@ -555,7 +555,7 @@ Данная опция позволяет использовать HD packs для эмулятора HDNes если они найдены. HD Packs должны быть помещены в папку "HdPacks" в папке с именем совпадающем с именем ROM. например: HD Pack для MyRom.nes должны лежать в "HdPacks\MyRom\hires.txt". Замечание: Поддержка HD Packs не закончена и имеет ряд ограничений. Вы используете последнюю версию Mesen Пропатчить и сбросить текущую игру? - Пожалуйста выберите ROM соответствующий IPS. + Пожалуйста выберите ROM соответствующий IPS/UPS. Невозможно загрузить файл. Проверьте ваше соединение с интернетом и попробуйте ещё раз. Подробно: {0} Mesen could not launch because it was unable to load MesenCore.dll due to missing dependencies. Mesen не может запуститься из за отсутствующих файлов. Ошибка: MesenCore.dll не найден. diff --git a/GUI.NET/Dependencies/resources.uk.xml b/GUI.NET/Dependencies/resources.uk.xml index dc0325ee..e7e4ccab 100644 --- a/GUI.NET/Dependencies/resources.uk.xml +++ b/GUI.NET/Dependencies/resources.uk.xml @@ -326,7 +326,7 @@ Ставити на паузу після програвання запису Дозволити введення в тлі Ставити на паузу при втраті фокуса - Автоматично завантажувати IPS + Автоматично завантажувати IPS/UPS Відкрити папку Mesen Асоціації файлів Асоціації файлів @@ -519,7 +519,7 @@ Avi файли (*.avi)|*.avi|All Files (*.*)|*.* Файли палiтр (*.pal)|*.pal|All Files (*.*)|*.* Всі підтримувані формати (*.nes, *.zip, *.7z, *.nsf, *.nsfe, *.fds, *.unf)|*.NES;*.ZIP;*.7z;*.FDS;*.NSF;*.NSFE;*.UNF|NES Roms (*.nes, *.unf)|*.NES;*.UNF|Famicom Disk System Roms (*.fds)|*.FDS|NSF files (*.nsf, *.nsfe)|*.nsf;*.nsfe|ZIP Archives (*.zip)|*.ZIP|7-Zip Archives (*.7z)|*.7z|All (*.*)|*.* - Всі підтримувані формати (*.nes, *.zip, *.7z, *.fds, *.nsf, *.nsfe, *.unf, *.ips)|*.NES;*.ZIP;*.7z;*.IPS;*.FDS;*.NSF;*.NSFE;*.UNF|NES Roms (*.nes, *.unf)|*.NES;*.UNF|Famicom Disk System Roms (*.fds)|*.FDS|NSF files (*.nsf, *.nsfe)|*.nsf;*.nsfe|ZIP Archives (*.zip)|*.ZIP|7-Zip Archives (*.7z)|*.7z|IPS Patches (*.ips)|*.IPS|All (*.*)|*.* + Всі підтримувані формати (*.nes, *.zip, *.7z, *.fds, *.nsf, *.nsfe, *.unf, *.ips, *.ups)|*.NES;*.ZIP;*.7z;*.IPS;*.UPS;*.FDS;*.NSF;*.NSFE;*.UNF|NES Roms (*.nes, *.unf)|*.NES;*.UNF|Famicom Disk System Roms (*.fds)|*.FDS|NSF files (*.nsf, *.nsfe)|*.nsf;*.nsfe|ZIP Archives (*.zip)|*.ZIP|7-Zip Archives (*.7z)|*.7z|IPS/UPS Patches (*.ips, *.ups)|*.IPS;*.UPS|All (*.*)|*.* Test files (*.mtp)|*.mtp|All (*.*)|*.* Всі підтримувані формати (*.cht, *.xml)|*.cht;*.xml @@ -554,7 +554,7 @@ Дана опція дозволяє використовувати HD packs для емулятора HDNes якщо вони знайдени. HD Packs повинні бути поміщені в папку "HdPacks" в папці з ім'ям збігається з ім'ям ROM. наприклад: HD Pack для MyRom.nes повинні лежати в "HdPacks\MyRom\hires.txt". Зауваження: Підтримка HD Packs не закінчена і має ряд обмежень. Ви використовуєте останню версію Mesen Пропатчити і скинути поточну гру? - Будь ласка, оберіть ROM відповідний IPS. + Будь ласка, оберіть ROM відповідний IPS/UPS. Неможливо завантажити файл. Перевірте ваше з'єднання з інтернетом і спробуйте ще раз. Детально: {0} Mesen could not launch because it was unable to load MesenCore.dll due to missing dependencies. Mesen не може запуститися через відсутні файли. Помилка: MesenCore.dll не знайдений. diff --git a/GUI.NET/Forms/Config/frmPreferences.Designer.cs b/GUI.NET/Forms/Config/frmPreferences.Designer.cs index e9c2e4d5..551a7ac7 100644 --- a/GUI.NET/Forms/Config/frmPreferences.Designer.cs +++ b/GUI.NET/Forms/Config/frmPreferences.Designer.cs @@ -221,7 +221,7 @@ namespace Mesen.GUI.Forms.Config this.chkAutoLoadIps.Name = "chkAutoLoadIps"; this.chkAutoLoadIps.Size = new System.Drawing.Size(132, 17); this.chkAutoLoadIps.TabIndex = 9; - this.chkAutoLoadIps.Text = "Auto-load IPS patches"; + this.chkAutoLoadIps.Text = "Auto-load IPS/UPS patches"; this.chkAutoLoadIps.UseVisualStyleBackColor = true; // // flowLayoutPanel6 diff --git a/GUI.NET/Forms/frmMain.cs b/GUI.NET/Forms/frmMain.cs index 2cefcc55..5223797b 100644 --- a/GUI.NET/Forms/frmMain.cs +++ b/GUI.NET/Forms/frmMain.cs @@ -478,11 +478,25 @@ namespace Mesen.GUI.Forms } } + private bool IsPatchFile(string filename) + { + using(FileStream stream = File.OpenRead(filename)) { + byte[] header = new byte[5]; + stream.Read(header, 0, 5); + if(header[0] == 'P' && header[1] == 'A' && header[2] == 'T' && header[3] == 'C' && header[4] == 'H') { + return true; + } else if(header[0] == 'U' && header[1] == 'P' && header[2] == 'S' && header[3] == '1') { + return true; + } + } + return false; + } + private void LoadFile(string filename) { if(File.Exists(filename)) { - if(Path.GetExtension(filename).ToLowerInvariant() == ".ips") { - LoadIpsFile(filename); + if(IsPatchFile(filename)) { + LoadPatchFile(filename); } else if(Path.GetExtension(filename).ToLowerInvariant() == ".mmo") { InteropEmu.MoviePlay(filename); } else { @@ -491,7 +505,7 @@ namespace Mesen.GUI.Forms } } - private void LoadIpsFile(string ipsFile) + private void LoadPatchFile(string patchFile) { if(_emuThread == null) { if(MesenMsgBox.Show("SelectRomIps", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.OK) { @@ -502,15 +516,15 @@ namespace Mesen.GUI.Forms } if(ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) { - LoadROM(ofd.FileName, true, -1, ipsFile); + LoadROM(ofd.FileName, true, -1, patchFile); } } } else if(MesenMsgBox.Show("PatchAndReset", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.OK) { - LoadROM(_currentRomPath, true, _currentRomArchiveIndex, ipsFile); + LoadROM(_currentRomPath, true, _currentRomArchiveIndex, patchFile); } } - private void LoadROM(string filename, bool autoLoadIps = false, int archiveFileIndex = -1, string ipsFileToApply = null) + private void LoadROM(string filename, bool autoLoadPatches = false, int archiveFileIndex = -1, string patchFileToApply = null) { _currentRomPath = filename; _currentRomArchiveIndex = -1; @@ -524,14 +538,26 @@ namespace Mesen.GUI.Forms ctrlLoading.Visible = true; } - string ipsFile = ipsFileToApply ?? Path.Combine(Path.GetDirectoryName(filename), Path.GetFileNameWithoutExtension(filename)) + ".ips"; - if(!File.Exists(ipsFile)) { - autoLoadIps = false; + string patchFile = patchFileToApply; + if(patchFile == null) { + string ipsFile = Path.Combine(Path.GetDirectoryName(filename), Path.GetFileNameWithoutExtension(filename)) + ".ips"; + if(!File.Exists(ipsFile)) { + string upsFile = Path.Combine(Path.GetDirectoryName(filename), Path.GetFileNameWithoutExtension(filename)) + ".ups"; + if(File.Exists(upsFile)) { + patchFile = upsFile; + } + } else { + patchFile = ipsFile; + } + } + + if(!File.Exists(patchFile)) { + autoLoadPatches = false; } Task loadRomTask = new Task(() => { lock(_loadRomLock) { - InteropEmu.LoadROM(filename, archiveFileIndex, autoLoadIps ? ipsFile : string.Empty); + InteropEmu.LoadROM(filename, archiveFileIndex, autoLoadPatches ? patchFile : string.Empty); } }); diff --git a/GUI.NET/InteropEmu.cs b/GUI.NET/InteropEmu.cs index 071081ca..d58557ff 100644 --- a/GUI.NET/InteropEmu.cs +++ b/GUI.NET/InteropEmu.cs @@ -26,7 +26,7 @@ namespace Mesen.GUI [DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool IsRunning(); - [DllImport(DLLPath)] public static extern void LoadROM([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filename, Int32 archiveFileIndex, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string ipsFile); + [DllImport(DLLPath)] public static extern void LoadROM([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filename, Int32 archiveFileIndex, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string patchFile); [DllImport(DLLPath)] public static extern void AddKnownGameFolder([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string folder); [DllImport(DLLPath, EntryPoint = "GetArchiveRomList")] private static extern IntPtr GetArchiveRomListWrapper([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filename); diff --git a/InteropDLL/ConsoleWrapper.cpp b/InteropDLL/ConsoleWrapper.cpp index 6e1f509c..b8957203 100644 --- a/InteropDLL/ConsoleWrapper.cpp +++ b/InteropDLL/ConsoleWrapper.cpp @@ -110,7 +110,7 @@ namespace InteropEmu { DllExport bool __stdcall IsRunning() { return Console::IsRunning(); } - DllExport void __stdcall LoadROM(char* filename, int32_t archiveFileIndex, char* ipsFile) { Console::LoadROM(filename, nullptr, archiveFileIndex, ipsFile); } + DllExport void __stdcall LoadROM(char* filename, int32_t archiveFileIndex, char* patchFile) { Console::LoadROM(filename, nullptr, archiveFileIndex, patchFile); } DllExport void __stdcall AddKnownGameFolder(char* folder) { FolderUtilities::AddKnownGameFolder(folder); } DllExport const char* __stdcall GetArchiveRomList(char* filename) { diff --git a/PGOHelper/PGOHelper.cpp b/PGOHelper/PGOHelper.cpp index 7d6bb9e4..8e538b50 100644 --- a/PGOHelper/PGOHelper.cpp +++ b/PGOHelper/PGOHelper.cpp @@ -37,7 +37,7 @@ enum class VideoFilterType extern "C" { void __stdcall SetVideoFilter(VideoFilterType filter); void __stdcall InitializeEmu(char* homeFolder, void*, void*, bool, bool, bool); - void __stdcall LoadROM(const char* filename, int32_t archiveFileIndex, char* ipsFile); + void __stdcall LoadROM(const char* filename, int32_t archiveFileIndex, char* patchFile); void __stdcall Run(); void __stdcall Stop(); } diff --git a/Utilities/UpsPatcher.cpp b/Utilities/UpsPatcher.cpp new file mode 100644 index 00000000..92b6d3d6 --- /dev/null +++ b/Utilities/UpsPatcher.cpp @@ -0,0 +1,99 @@ +#include "stdafx.h" +#include +#include +#include "UpsPatcher.h" +#include "CRC32.h" + +uint64_t UpsPatcher::ReadBase128Number(ifstream &file) +{ + uint64_t result = 0; + int shift = 0; + uint8_t buffer; + while(true) { + file.read((char*)&buffer, 1); + if(file.eof()) { + return -1; + } + result += (buffer & 0x7F) << shift; + shift += 7; + if(buffer & 0x80) { + break; + } + result += (uint64_t)1 << shift; + } + + return result; +} + +vector UpsPatcher::PatchBuffer(string upsFilepath, vector input) +{ + ifstream upsFile(upsFilepath, std::ios::in | std::ios::binary); + + if(upsFile) { + upsFile.seekg(0, std::ios::end); + size_t fileSize = (size_t)upsFile.tellg(); + upsFile.seekg(0, std::ios::beg); + + char header[4]; + upsFile.read((char*)&header, 4); + if(memcmp((char*)&header, "UPS1", 4) != 0) { + //Invalid UPS file + return input; + } + + uint64_t inputFileSize = ReadBase128Number(upsFile); + uint64_t outputFileSize = ReadBase128Number(upsFile); + if(inputFileSize == -1 || outputFileSize == -1) { + //Invalid file + return input; + } + + vector output; + output.resize(outputFileSize); + std::copy(input.begin(), input.end(), output.begin()); + + uint64_t pos = 0; + while((size_t)upsFile.tellg() < fileSize - 12) { + uint64_t offset = ReadBase128Number(upsFile); + if(offset == -1) { + //Invalid file + return input; + } + + pos += offset; + + while(true) { + uint8_t xorValue = 0; + upsFile.read((char*)&xorValue, 1); + if((size_t)upsFile.tellg() > fileSize - 12) { + //Invalid file + return input; + } + + output[pos] ^= xorValue; + pos++; + + if(!xorValue) { + break; + } + } + } + + uint8_t inputChecksum[4]; + uint8_t outputChecksum[4]; + upsFile.read((char*)inputChecksum, 4); + upsFile.read((char*)outputChecksum, 4); + uint32_t patchInputCrc = inputChecksum[0] | (inputChecksum[1] << 8) | (inputChecksum[2] << 16) | (inputChecksum[3] << 24); + uint32_t patchOutputCrc = outputChecksum[0] | (outputChecksum[1] << 8) | (outputChecksum[2] << 16) | (outputChecksum[3] << 24); + uint32_t inputCrc = CRC32::GetCRC(input.data(), input.size()); + uint32_t outputCrc = CRC32::GetCRC(output.data(), output.size()); + + if(patchInputCrc != inputCrc || patchOutputCrc != outputCrc) { + return input; + } + + upsFile.close(); + return output; + } + return input; +} diff --git a/Utilities/UpsPatcher.h b/Utilities/UpsPatcher.h new file mode 100644 index 00000000..c2aaddcd --- /dev/null +++ b/Utilities/UpsPatcher.h @@ -0,0 +1,12 @@ +#pragma once + +#include "stdafx.h" + +class UpsPatcher +{ +private: + static uint64_t UpsPatcher::ReadBase128Number(ifstream &file); + +public: + static vector PatchBuffer(string upsFilepath, vector input); +}; \ No newline at end of file diff --git a/Utilities/Utilities.vcxproj b/Utilities/Utilities.vcxproj index 3b9cfff6..f9577b32 100644 --- a/Utilities/Utilities.vcxproj +++ b/Utilities/Utilities.vcxproj @@ -354,6 +354,7 @@ + @@ -491,6 +492,7 @@ + NotUsing diff --git a/Utilities/Utilities.vcxproj.filters b/Utilities/Utilities.vcxproj.filters index 7ef29c6b..2c0c367e 100644 --- a/Utilities/Utilities.vcxproj.filters +++ b/Utilities/Utilities.vcxproj.filters @@ -143,6 +143,9 @@ Header Files + + Header Files + @@ -250,5 +253,8 @@ Avi + + Source Files + \ No newline at end of file