UPS patch support

This commit is contained in:
Souryo 2017-04-09 22:44:13 -04:00
parent db96d7ca48
commit 92107d94df
23 changed files with 229 additions and 67 deletions

View file

@ -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<BaseMapper> mapper = MapperFactory::InitializeFromFile(romFilename, filestream, ipsFilename, archiveFileIndex);
shared_ptr<BaseMapper> 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();
}

View file

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

View file

@ -543,11 +543,11 @@ BaseMapper* MapperFactory::GetMapperFromID(RomData &romData)
return nullptr;
}
shared_ptr<BaseMapper> MapperFactory::InitializeFromFile(string romFilename, stringstream *filestream, string ipsFilename, int32_t archiveFileIndex)
shared_ptr<BaseMapper> 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<BaseMapper> mapper(GetMapperFromID(romData));

View file

@ -12,5 +12,5 @@ class MapperFactory
static const uint16_t FdsMapperID = 65535;
static const uint16_t NsfMapperID = 65534;
static shared_ptr<BaseMapper> InitializeFromFile(string romFilename, stringstream *filestream, string ipsFilename, int32_t archiveFileIndex);
static shared_ptr<BaseMapper> InitializeFromFile(string romFilename, stringstream *filestream, string patchFilename, int32_t archiveFileIndex);
};

View file

@ -12,7 +12,7 @@ std::unordered_map<string, string> 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<string, string> 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<string, string> 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<string, string> 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<string, string> 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<string, string> 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<string, string> 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<string, string> 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<string, string> 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<string, string> 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<string, string> 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<string, string> 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<string, string> 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<string, string> 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." },

View file

@ -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<uint8_t> &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<uint8_t> 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;

View file

@ -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<uint8_t> &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<string> GetArchiveRomList(string filename);

View file

@ -7,7 +7,7 @@
<Message ID="FilterAvi">Avi files (*.avi)|*.avi|All Files (*.*)|*.*</Message>
<Message ID="FilterPalette">Palette Files (*.pal)|*.pal|All Files (*.*)|*.*</Message>
<Message ID="FilterRom">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 (*.*)|*.*</Message>
<Message ID="FilterRomIps">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 (*.*)|*.*</Message>
<Message ID="FilterRomIps">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 (*.*)|*.*</Message>
<Message ID="FilterTest">Test files (*.mtp)|*.mtp|All (*.*)|*.*</Message>
<Message ID="FilterCheat">All supported formats (*.cht, *.xml)|*.cht;*.xml</Message>
@ -42,7 +42,7 @@
<Message ID="HDNesTooltip">This option allows Mesen to load HDNes-format HD packs if they are found.&#xA;&#xA;HD Packs should be placed in the "HdPacks" folder in a subfolder matching the name of the ROM.&#xA;e.g: MyRom.nes should have their HD Pack in "HdPacks\MyRom\hires.txt".&#xA;&#xA;Note: Support for HD Packs is a work in progress and some limitations remain.</Message>
<Message ID="MesenUpToDate">You are running the latest version of Mesen</Message>
<Message ID="PatchAndReset">Patch and reset the current game?</Message>
<Message ID="SelectRomIps">Please select a ROM matching the IPS patch file.</Message>
<Message ID="SelectRomIps">Please select a ROM matching the IPS/UPS patch file.</Message>
<Message ID="UnableToDownload">Unable to download file. Check your internet connection and try again.&#xA;&#xA;Details:&#xA;{0}</Message>
<Message ID="UnableToStartMissingDependencies">Mesen could not launch because it was unable to load MesenCore.dll due to missing dependencies.</Message>
<Message ID="UnableToStartMissingFiles">Mesen was unable to start due to missing files.&#xA;&#xA;Error: MesenCore.dll is missing.</Message>

View file

@ -325,7 +325,7 @@
<Control ID="chkPauseOnMovieEnd">Pausar la emulación al finalizar el video</Control>
<Control ID="chkAllowBackgroundInput">Permitir entradas aunque Mesen esté en segundo plano</Control>
<Control ID="chkPauseWhenInBackground">Pausar la emulación aunque Mesen esté en segundo plano</Control>
<Control ID="chkAutoLoadIps">Cargar los archivos IPS automáticamente</Control>
<Control ID="chkAutoLoadIps">Cargar los archivos IPS/UPS automáticamente</Control>
<Control ID="btnOpenMesenFolder">Abrir el directorio de Mesen</Control>
<Control ID="tpgFileAssociations">Asociación de archivos</Control>
<Control ID="grpFileAssociations">Asociación de archivos</Control>
@ -516,7 +516,7 @@
<Message ID="FilterAvi">Archivos avi (*.avi)|*.avi|Todos los archivos (*.*)|*.*</Message>
<Message ID="FilterPalette">Archivos pal (*.pal)|*.pal|Todos los archivos (*.*)|*.*</Message>
<Message ID="FilterRom">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 (*.*)|*.*</Message>
<Message ID="FilterRomIps">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 (*.*)|*.*</Message>
<Message ID="FilterRomIps">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 (*.*)|*.*</Message>
<Message ID="FilterTest">Archivos de test (*.mtp)|*.mtp|Todos los archivos (*.*)|*.*</Message>
<Message ID="FilterCheat">Todos los formatos soportados (*.cht, *.xml)|*.cht;*.xml</Message>
@ -550,7 +550,7 @@
<Message ID="HDNesTooltip">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.&#xA;&#xA;Los paquetes de alta resolución deberán ser colocados en los "HdPacks" en una subcarpeta con el nombre de la ROM.&#xA;Ejemplo: Un paquete para "MiRom.nes" debe estar colocado en "HdPacks\MiRom\hires.txt".&#xA;&#xA;Nota: El soporte para paquetes de alta resolución aún no es perfecto - algunas limitaciones siguen presentes.</Message>
<Message ID="MesenUpToDate">Ya utiliza la versión mas reciente de Mesen.</Message>
<Message ID="PatchAndReset">¿Aplicar el parche y reiniciar el juego?</Message>
<Message ID="SelectRomIps">Elija la ROM que corresponde al archivo IPS seleccionado.</Message>
<Message ID="SelectRomIps">Elija la ROM que corresponde al archivo IPS/UPS seleccionado.</Message>
<Message ID="UnableToDownload">No se puede descargar el archivo. Compruebe su conexión a Internet e inténtelo de nuevo.&#xA;&#xA;Detalles del error:&#xA;{0}</Message>
<Message ID="UnableToStartMissingDependencies">Mesen no puede inciarse porque porque no puede cargar MesenCore.dll debido a dependencias no encontradas.</Message>
<Message ID="UnableToStartMissingFiles">Mesen no puede iniciarse debido a que faltan archivos.&#xA;&#xA;Error: No se encuentra el archivo MesenCore.dll.</Message>

View file

@ -327,7 +327,7 @@
<Control ID="chkPauseOnMovieEnd">Pauser l'émulation à la fin d'un film</Control>
<Control ID="chkAllowBackgroundInput">Permettre les entrées lorsque Mesen est en arrière-plan</Control>
<Control ID="chkPauseWhenInBackground">Pauser l'émulation lorsque Mesen est en arrière-plan</Control>
<Control ID="chkAutoLoadIps">Charger les fichiers IPS automatiquement</Control>
<Control ID="chkAutoLoadIps">Charger les fichiers IPS/UPS automatiquement</Control>
<Control ID="btnOpenMesenFolder">Ouvrir le dossier de Mesen</Control>
<Control ID="tpgFileAssociations">Associations de fichiers</Control>
<Control ID="grpFileAssociations">Associations de fichiers</Control>
@ -530,7 +530,7 @@
<Message ID="FilterAvi">Fichiers avi (*.avi)|*.avi|Tous les fichiers (*.*)|*.*</Message>
<Message ID="FilterPalette">Fichier de palette (*.pal)|*.pal|Tous les fichiers (*.*)|*.*</Message>
<Message ID="FilterRom">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 (*.*)|*.*</Message>
<Message ID="FilterRomIps">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 (*.*)|*.*</Message>
<Message ID="FilterRomIps">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 (*.*)|*.*</Message>
<Message ID="FilterTest">Fichiers de test (*.mtp)|*.mtp|Tous les fichiers (*.*)|*.*</Message>
<Message ID="FilterCheat">Tous les formats supportés (*.cht, *.xml)|*.cht;*.xml</Message>
@ -565,7 +565,7 @@
<Message ID="HDNesTooltip">Cette option permet à Mesen de charger des packages de graphiques haute-résolution dans le même format que l'émulateur HDNes.&#xA;&#xA;Les packages haute-résolution doivent être placés dans le dossier "HdPacks", dans un sous-dossier correspondant au nom du ROM.&#xA;Exemple : Un package pour "MonRom.nes" doit être placé dans "HdPacks\MonRom\hires.txt".&#xA;&#xA;Note: Le support pour les packages haute-résolution n'est pas encore parfait - certaines limitations sont encore présentes.</Message>
<Message ID="MesenUpToDate">Vous utilisez déjà la version la plus récente de Mesen.</Message>
<Message ID="PatchAndReset">Appliquer la patch et faire un reset du jeu?</Message>
<Message ID="SelectRomIps">Choisissez un ROM qui correspond au fichier IPS choisi.</Message>
<Message ID="SelectRomIps">Choisissez un ROM qui correspond au fichier IPS/UPS choisi.</Message>
<Message ID="UnableToDownload">Impossible de télécharger le fichier. Vérifier votre connexion internet et essayez à nouveau.&#xA;&#xA;Détails de l'erreur:&#xA;{0}</Message>
<Message ID="UnableToStartMissingDependencies">Mesen n'a pas été en mesure de charger le fichier MesenCore.dll, et ne peut donc pas être lancé.</Message>
<Message ID="UnableToStartMissingFiles">Mesen est incapable de démarrer puisqu'il manque des fichiers.&#xA;&#xA;Erreur: Le fichier MesenCore.dll est introuvable.</Message>

View file

@ -326,7 +326,7 @@
<Control ID="chkPauseOnMovieEnd">動画が終わると自動的にポーズする</Control>
<Control ID="chkAllowBackgroundInput">Mesenが最前面ではない時、コントローラは反応しない</Control>
<Control ID="chkPauseWhenInBackground">Mesenが最前面ではない時、自動的にポーズする</Control>
<Control ID="chkAutoLoadIps">自動的にIPSファイルをロードする</Control>
<Control ID="chkAutoLoadIps">自動的にパッチファイルIPS・UPSをロードする</Control>
<Control ID="btnOpenMesenFolder">Mesenのフォルダを開く</Control>
<Control ID="tpgFileAssociations">ファイルの関連付け</Control>
<Control ID="grpFileAssociations">ファイルの関連付け</Control>
@ -512,7 +512,7 @@
<Message ID="FilterAvi">AVIファイル (*.avi)|*.avi|すべてのファイル (*.*)|*.*</Message>
<Message ID="FilterPalette">パレットファイル (*.pal)|*.pal|すべてのファイル (*.*)|*.*</Message>
<Message ID="FilterRom">対応するすべてのファイル (*.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|すべてのファイル (*.*)|*.*</Message>
<Message ID="FilterRomIps">対応するすべてのファイル (*.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|すべてのファイル (*.*)|*.*</Message>
<Message ID="FilterRomIps">対応するすべてのファイル (*.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|すべてのファイル (*.*)|*.*</Message>
<Message ID="FilterTest">テストファイル (*.mtp)|*.mtp|すべてのファイル (*.*)|*.*</Message>
<Message ID="FilterCheat">対応するすべてのファイル (*.cht, *.xml)|*.cht;*.xml</Message>
@ -546,8 +546,8 @@
<Message ID="InvalidFdsBios">選んだBIOSファイルは使えません。</Message>
<Message ID="HDNesTooltip">このオプションを有効にすれば、MesenはHDNesのようにHDパックをロード出来るようになります。&#xA;&#xA;HDパックはMesenのフォルダの中にある「HdPacks」のフォルダにゲームと同じ名前のサブフォルダに置くと自動的にロードされます。&#xA;ゲームファイルは「MyRom.nes」なら、「HdPacks\MyRom」にHDパックを置くとロードされます。&#xA;&#xA;この機能はまだ開発中で、不完全なところがあります、ご了承ください。</Message>
<Message ID="MesenUpToDate">既にMesenの最新のバージョンを使っています。</Message>
<Message ID="PatchAndReset">IPSパッチを当てて、ゲームをリセットしますか?</Message>
<Message ID="SelectRomIps">IPSファイルに合うゲームファイルを選んでください。</Message>
<Message ID="PatchAndReset">パッチファイルを当てて、ゲームをリセットしますか?</Message>
<Message ID="SelectRomIps">パッチファイルに合うゲームファイルを選んでください。</Message>
<Message ID="UnableToDownload">ファイルをダウンロードできませんでした。ネット接続を確認してから、再試行してください。&#xA;&#xA;エラーの詳細:&#xA;{0}</Message>
<Message ID="UnableToStartMissingDependencies">MesenはMesenCore.dllをロード出来なかったため、起動できませんでした。</Message>
<Message ID="UnableToStartMissingFiles">必要なファイルはロード出来なかったため、Mesenは起動できません。&#xA;&#xA;エラー: MesenCore.dllはロードできません。</Message>

View file

@ -325,7 +325,7 @@
<Control ID="chkPauseOnMovieEnd">Pausar a emulação ao finalizar o vídeo</Control>
<Control ID="chkAllowBackgroundInput">Permitir inputs quando Mesen estiver em segundo plano</Control>
<Control ID="chkPauseWhenInBackground">Pausar a emulação quando Mesen estiver em segundo plano</Control>
<Control ID="chkAutoLoadIps">Carregar os arquivos IPS automaticamente</Control>
<Control ID="chkAutoLoadIps">Carregar os arquivos IPS/UPS automaticamente</Control>
<Control ID="btnOpenMesenFolder">Abrir a pasta de Mesen</Control>
<Control ID="tpgFileAssociations">Associação de arquivos</Control>
<Control ID="grpFileAssociations">Associação de arquivos</Control>
@ -516,7 +516,7 @@
<Message ID="FilterAvi">Arquivos avi (*.avi)|*.avi|Todos os arquivos (*.*)|*.*</Message>
<Message ID="FilterPalette">Arquivos pal (*.pal)|*.pal|Todos os arquivos (*.*)|*.*</Message>
<Message ID="FilterRom">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 (*.*)|*.*</Message>
<Message ID="FilterRomIps">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 (*.*)|*.*</Message>
<Message ID="FilterRomIps">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 (*.*)|*.*</Message>
<Message ID="FilterTest">Arquivos de teste (*.mtp)|*.mtp|Todos os arquivos (*.*)|*.*</Message>
<Message ID="FilterCheat">Todos os formatos suportados (*.cht, *.xml)|*.cht;*.xml</Message>
@ -550,7 +550,7 @@
<Message ID="HDNesTooltip">Esta opção permite os pacotes de gráficos de alta resolução sejam carregados no mesmo formato que os do emulador HDNes.&#xA;&#xA;Os pacotes de alta resolução devem ser colocados nos "HdPacks" em uma subpasta com o mesmo nome da ROM.&#xA;Exemplo: Um pacote para "MinhaRom.nes" deve ser colocado em "HdPacks\MinhaRom\hires.txt".&#xA;&#xA;Nota: O suporte para os pacotes de alta resolução não é perfeito - algumas limitações seguem presentes.</Message>
<Message ID="MesenUpToDate">Já utiliza a versão mais recente do Mesen.</Message>
<Message ID="PatchAndReset">Aplicar o patch e reiniciar o jogo?</Message>
<Message ID="SelectRomIps">Selecione a ROM que corresponde ao arquivo IPS selecionado.</Message>
<Message ID="SelectRomIps">Selecione a ROM que corresponde ao arquivo IPS/UPS selecionado.</Message>
<Message ID="UnableToDownload">Não foi possível baixar o arquivo. Verifique sua conexão com a internet e tente de novo.&#xA;&#xA;Detalhes do erro:&#xA;{0}</Message>
<Message ID="UnableToStartMissingDependencies">Mesen não pode iniciar pois foi incapaz de carregar MesenCore.dll devido a falta de dependências.</Message>
<Message ID="UnableToStartMissingFiles">Mesen não pode iniciar devido a falta de arquivos.&#xA;&#xA;Erro: Não se encontra o arquivo MesenCore.dll.</Message>

View file

@ -326,7 +326,7 @@
<Control ID="chkPauseOnMovieEnd">Ставить на паузу после проигрывания записи</Control>
<Control ID="chkAllowBackgroundInput">Разрешить ввод в фоне</Control>
<Control ID="chkPauseWhenInBackground">Ставить на паузу при потере фокуса</Control>
<Control ID="chkAutoLoadIps">Автоматически загружать IPS</Control>
<Control ID="chkAutoLoadIps">Автоматически загружать IPS/UPS</Control>
<Control ID="btnOpenMesenFolder">Открыть папку Mesen</Control>
<Control ID="tpgFileAssociations">Ассоциации файлов</Control>
<Control ID="grpFileAssociations">Ассоциации файлов</Control>
@ -520,7 +520,7 @@
<Message ID="FilterAvi">Avi файлы (*.avi)|*.avi|All Files (*.*)|*.*</Message>
<Message ID="FilterPalette">Файлы палитры (*.pal)|*.pal|All Files (*.*)|*.*</Message>
<Message ID="FilterRom">Все поддерживаемые форматы (*.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 (*.*)|*.*</Message>
<Message ID="FilterRomIps">Все поддерживаемые форматы (*.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 (*.*)|*.*</Message>
<Message ID="FilterRomIps">Все поддерживаемые форматы (*.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 (*.*)|*.*</Message>
<Message ID="FilterTest">Test files (*.mtp)|*.mtp|All (*.*)|*.*</Message>
<Message ID="FilterCheat">Все поддерживаемые форматы (*.cht, *.xml)|*.cht;*.xml</Message>
@ -555,7 +555,7 @@
<Message ID="HDNesTooltip">Данная опция позволяет использовать HD packs для эмулятора HDNes если они найдены.&#xA;&#xA;HD Packs должны быть помещены в папку "HdPacks" в папке с именем совпадающем с именем ROM.&#xA;например: HD Pack для MyRom.nes должны лежать в "HdPacks\MyRom\hires.txt".&#xA;&#xA;Замечание: Поддержка HD Packs не закончена и имеет ряд ограничений.</Message>
<Message ID="MesenUpToDate">Вы используете последнюю версию Mesen</Message>
<Message ID="PatchAndReset">Пропатчить и сбросить текущую игру?</Message>
<Message ID="SelectRomIps">Пожалуйста выберите ROM соответствующий IPS.</Message>
<Message ID="SelectRomIps">Пожалуйста выберите ROM соответствующий IPS/UPS.</Message>
<Message ID="UnableToDownload">Невозможно загрузить файл. Проверьте ваше соединение с интернетом и попробуйте ещё раз.&#xA;&#xA;Подробно:&#xA;{0}</Message>
<Message ID="UnableToStartMissingDependencies">Mesen could not launch because it was unable to load MesenCore.dll due to missing dependencies.</Message>
<Message ID="UnableToStartMissingFiles">Mesen не может запуститься из за отсутствующих файлов.&#xA;&#xA;Ошибка: MesenCore.dll не найден.</Message>

View file

@ -326,7 +326,7 @@
<Control ID="chkPauseOnMovieEnd">Ставити на паузу після програвання запису</Control>
<Control ID="chkAllowBackgroundInput">Дозволити введення в тлі</Control>
<Control ID="chkPauseWhenInBackground">Ставити на паузу при втраті фокуса</Control>
<Control ID="chkAutoLoadIps">Автоматично завантажувати IPS</Control>
<Control ID="chkAutoLoadIps">Автоматично завантажувати IPS/UPS</Control>
<Control ID="btnOpenMesenFolder">Відкрити папку Mesen</Control>
<Control ID="tpgFileAssociations">Асоціації файлів</Control>
<Control ID="grpFileAssociations">Асоціації файлів</Control>
@ -519,7 +519,7 @@
<Message ID="FilterAvi">Avi файли (*.avi)|*.avi|All Files (*.*)|*.*</Message>
<Message ID="FilterPalette">Файли палiтр (*.pal)|*.pal|All Files (*.*)|*.*</Message>
<Message ID="FilterRom">Всі підтримувані формати (*.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 (*.*)|*.*</Message>
<Message ID="FilterRomIps">Всі підтримувані формати (*.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 (*.*)|*.*</Message>
<Message ID="FilterRomIps">Всі підтримувані формати (*.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 (*.*)|*.*</Message>
<Message ID="FilterTest">Test files (*.mtp)|*.mtp|All (*.*)|*.*</Message>
<Message ID="FilterCheat">Всі підтримувані формати (*.cht, *.xml)|*.cht;*.xml</Message>
@ -554,7 +554,7 @@
<Message ID="HDNesTooltip">Дана опція дозволяє використовувати HD packs для емулятора HDNes якщо вони знайдени.&#xA;&#xA;HD Packs повинні бути поміщені в папку "HdPacks" в папці з ім'ям збігається з ім'ям ROM.&#xA;наприклад: HD Pack для MyRom.nes повинні лежати в "HdPacks\MyRom\hires.txt".&#xA;&#xA;Зауваження: Підтримка HD Packs не закінчена і має ряд обмежень.</Message>
<Message ID="MesenUpToDate">Ви використовуєте останню версію Mesen</Message>
<Message ID="PatchAndReset">Пропатчити і скинути поточну гру?</Message>
<Message ID="SelectRomIps">Будь ласка, оберіть ROM відповідний IPS.</Message>
<Message ID="SelectRomIps">Будь ласка, оберіть ROM відповідний IPS/UPS.</Message>
<Message ID="UnableToDownload">Неможливо завантажити файл. Перевірте ваше з'єднання з інтернетом і спробуйте ще раз.&#xA;&#xA;Детально:&#xA;{0}</Message>
<Message ID="UnableToStartMissingDependencies">Mesen could not launch because it was unable to load MesenCore.dll due to missing dependencies.</Message>
<Message ID="UnableToStartMissingFiles">Mesen не може запуститися через відсутні файли.&#xA;&#xA;Помилка: MesenCore.dll не знайдений.</Message>

View file

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

View file

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

View file

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

View file

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

View file

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

99
Utilities/UpsPatcher.cpp Normal file
View file

@ -0,0 +1,99 @@
#include "stdafx.h"
#include <assert.h>
#include <cstring>
#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<uint8_t> UpsPatcher::PatchBuffer(string upsFilepath, vector<uint8_t> 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<uint8_t> 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;
}

12
Utilities/UpsPatcher.h Normal file
View file

@ -0,0 +1,12 @@
#pragma once
#include "stdafx.h"
class UpsPatcher
{
private:
static uint64_t UpsPatcher::ReadBase128Number(ifstream &file);
public:
static vector<uint8_t> PatchBuffer(string upsFilepath, vector<uint8_t> input);
};

View file

@ -354,6 +354,7 @@
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="Timer.h" />
<ClInclude Include="UpsPatcher.h" />
<ClInclude Include="UTF8Util.h" />
<ClInclude Include="xBRZ\config.h" />
<ClInclude Include="xBRZ\xbrz.h" />
@ -491,6 +492,7 @@
<ClCompile Include="SZReader.cpp" />
<ClCompile Include="Timer.cpp" />
<ClCompile Include="UPnPPortMapper.cpp" />
<ClCompile Include="UpsPatcher.cpp" />
<ClCompile Include="UTF8Util.cpp" />
<ClCompile Include="xBRZ\xbrz.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>

View file

@ -143,6 +143,9 @@
<ClInclude Include="StringUtilities.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="UpsPatcher.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
@ -250,5 +253,8 @@
<ClCompile Include="CamstudioCodec.cpp">
<Filter>Avi</Filter>
</ClCompile>
<ClCompile Include="UpsPatcher.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>