mirror of
https://github.com/libretro/Mesen.git
synced 2025-01-21 08:14:27 +00:00
IPS support
This commit is contained in:
parent
b1bccc47ce
commit
78081d7c69
@ -31,13 +31,13 @@ void Console::Release()
|
||||
Console::Instance.reset(new Console());
|
||||
}
|
||||
|
||||
void Console::Initialize(string filename, stringstream *filestream)
|
||||
void Console::Initialize(string romFilename, stringstream *filestream, string ipsFilename)
|
||||
{
|
||||
MessageManager::SendNotification(ConsoleNotificationType::GameStopped);
|
||||
shared_ptr<BaseMapper> mapper = MapperFactory::InitializeFromFile(filename, filestream);
|
||||
shared_ptr<BaseMapper> mapper = MapperFactory::InitializeFromFile(romFilename, filestream, ipsFilename);
|
||||
|
||||
if(mapper) {
|
||||
_romFilepath = filename;
|
||||
_romFilepath = romFilename;
|
||||
|
||||
VideoDecoder::GetInstance()->StopThread();
|
||||
|
||||
@ -64,13 +64,20 @@ void Console::Initialize(string filename, stringstream *filestream)
|
||||
|
||||
VideoDecoder::GetInstance()->StartThread();
|
||||
|
||||
FolderUtilities::AddKnowGameFolder(FolderUtilities::GetFolderName(filename));
|
||||
MessageManager::DisplayMessage("Game loaded", FolderUtilities::GetFilename(filename, false));
|
||||
FolderUtilities::AddKnowGameFolder(FolderUtilities::GetFolderName(romFilename));
|
||||
MessageManager::DisplayMessage("Game loaded", FolderUtilities::GetFilename(romFilename, false));
|
||||
} else {
|
||||
MessageManager::DisplayMessage("Error", string("Could not load file: ") + FolderUtilities::GetFilename(filename, true));
|
||||
MessageManager::DisplayMessage("Error", string("Could not load file: ") + FolderUtilities::GetFilename(romFilename, true));
|
||||
}
|
||||
}
|
||||
|
||||
void Console::ApplyIpsPatch(string ipsFilename)
|
||||
{
|
||||
Console::Pause();
|
||||
Instance->Initialize(GetROMPath(), nullptr, ipsFilename);
|
||||
Console::Resume();
|
||||
}
|
||||
|
||||
void Console::LoadROM(string filepath, stringstream *filestream)
|
||||
{
|
||||
Console::Pause();
|
||||
|
@ -35,7 +35,7 @@ class Console
|
||||
bool _initialized = false;
|
||||
|
||||
void ResetComponents(bool softReset);
|
||||
void Initialize(string filename, stringstream *filestream = nullptr);
|
||||
void Initialize(string filename, stringstream *filestream = nullptr, string ipsFilename = "");
|
||||
void UpdateNesModel(double &frameDelay, bool showMessage);
|
||||
|
||||
public:
|
||||
@ -60,6 +60,7 @@ class Console
|
||||
|
||||
static void LoadROM(string filepath, stringstream *filestream = nullptr);
|
||||
static bool LoadROM(string romName, uint32_t crc32Hash);
|
||||
static void ApplyIpsPatch(string ipsFilename);
|
||||
static string FindMatchingRomInFolder(string folder, string romFilename, uint32_t crc32Hash);
|
||||
static string GetROMPath();
|
||||
|
||||
|
@ -48,11 +48,11 @@ BaseMapper* MapperFactory::GetMapperFromID(uint8_t mapperID)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
shared_ptr<BaseMapper> MapperFactory::InitializeFromFile(string filename, stringstream *filestream)
|
||||
shared_ptr<BaseMapper> MapperFactory::InitializeFromFile(string romFilename, stringstream *filestream, string ipsFilename)
|
||||
{
|
||||
ROMLoader loader;
|
||||
|
||||
if(loader.LoadFile(filename, filestream)) {
|
||||
if(loader.LoadFile(romFilename, filestream, ipsFilename)) {
|
||||
uint8_t mapperID = loader.GetMapperID();
|
||||
|
||||
shared_ptr<BaseMapper> mapper(GetMapperFromID(mapperID));
|
||||
|
@ -7,5 +7,5 @@ class MapperFactory
|
||||
static BaseMapper* GetMapperFromID(uint8_t mapperID);
|
||||
|
||||
public:
|
||||
static shared_ptr<BaseMapper> InitializeFromFile(string filename, stringstream *filestream);
|
||||
static shared_ptr<BaseMapper> InitializeFromFile(string romFilename, stringstream *filestream, string ipsFilename);
|
||||
};
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "../Utilities/FolderUtilities.h"
|
||||
#include "../Utilities/ZipReader.h"
|
||||
#include "../Utilities/CRC32.h"
|
||||
#include "../Utilities/IpsPatcher.h"
|
||||
|
||||
enum class MirroringType
|
||||
{
|
||||
@ -65,6 +66,7 @@ class ROMLoader
|
||||
uint8_t* _prgRAM = nullptr;
|
||||
uint8_t* _chrRAM = nullptr;
|
||||
uint32_t _crc32;
|
||||
string _ipsFilename;
|
||||
|
||||
bool LoadFromZip(stringstream &zipFile)
|
||||
{
|
||||
@ -128,6 +130,16 @@ class ROMLoader
|
||||
|
||||
bool LoadFromMemory(uint8_t* buffer, size_t length)
|
||||
{
|
||||
if(!_ipsFilename.empty()) {
|
||||
//Apply IPS patch
|
||||
uint8_t* patchedFile = nullptr;
|
||||
size_t patchedSize = 0;
|
||||
if(IpsPatcher::PatchBuffer(_ipsFilename, buffer, length, &patchedFile, patchedSize)) {
|
||||
buffer = patchedFile;
|
||||
length = patchedSize;
|
||||
}
|
||||
}
|
||||
|
||||
_crc32 = CRC32::GetCRC(buffer, length);
|
||||
if(memcmp(buffer, "NES", 3) == 0) {
|
||||
memcpy((char*)&_header, buffer, sizeof(NESHeader));
|
||||
@ -163,8 +175,10 @@ class ROMLoader
|
||||
}
|
||||
}
|
||||
|
||||
bool LoadFile(string filename, stringstream *filestream = nullptr)
|
||||
bool LoadFile(string filename, stringstream *filestream = nullptr, string ipsFilename = "")
|
||||
{
|
||||
_ipsFilename = ipsFilename;
|
||||
|
||||
stringstream ss;
|
||||
if(!filestream) {
|
||||
ifstream file(filename, ios::in | ios::binary);
|
||||
|
@ -21,6 +21,7 @@ namespace Mesen.GUI.Config
|
||||
public List<CheatInfo> Cheats;
|
||||
public List<ControllerInfo> Controllers;
|
||||
public bool ShowOnlyCheatsForCurrentGame;
|
||||
public bool AutoLoadIpsPatches;
|
||||
public NesModel Region;
|
||||
|
||||
public Configuration()
|
||||
|
55
GUI.NET/Forms/frmMain.Designer.cs
generated
55
GUI.NET/Forms/frmMain.Designer.cs
generated
@ -23,6 +23,7 @@
|
||||
if(_debugger != null) {
|
||||
_debugger.Close();
|
||||
}
|
||||
UpdateConfig();
|
||||
StopEmu();
|
||||
InteropEmu.Release();
|
||||
base.Dispose(disposing);
|
||||
@ -105,6 +106,8 @@
|
||||
this.mnuTestRecordMovie = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.dxViewer = new Mesen.GUI.Controls.DXViewer();
|
||||
this.mnuTestRecordTest = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuAutoLoadIpsPatches = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripMenuItem10 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.menuStrip.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
@ -141,49 +144,49 @@
|
||||
//
|
||||
this.mnuOpen.Name = "mnuOpen";
|
||||
this.mnuOpen.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O)));
|
||||
this.mnuOpen.Size = new System.Drawing.Size(146, 22);
|
||||
this.mnuOpen.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuOpen.Text = "Open";
|
||||
this.mnuOpen.Click += new System.EventHandler(this.mnuOpen_Click);
|
||||
//
|
||||
// toolStripMenuItem4
|
||||
//
|
||||
this.toolStripMenuItem4.Name = "toolStripMenuItem4";
|
||||
this.toolStripMenuItem4.Size = new System.Drawing.Size(143, 6);
|
||||
this.toolStripMenuItem4.Size = new System.Drawing.Size(149, 6);
|
||||
//
|
||||
// mnuSaveState
|
||||
//
|
||||
this.mnuSaveState.Name = "mnuSaveState";
|
||||
this.mnuSaveState.Size = new System.Drawing.Size(146, 22);
|
||||
this.mnuSaveState.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuSaveState.Text = "Save State";
|
||||
this.mnuSaveState.DropDownOpening += new System.EventHandler(this.mnuSaveState_DropDownOpening);
|
||||
//
|
||||
// mnuLoadState
|
||||
//
|
||||
this.mnuLoadState.Name = "mnuLoadState";
|
||||
this.mnuLoadState.Size = new System.Drawing.Size(146, 22);
|
||||
this.mnuLoadState.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuLoadState.Text = "Load State";
|
||||
this.mnuLoadState.DropDownOpening += new System.EventHandler(this.mnuLoadState_DropDownOpening);
|
||||
//
|
||||
// toolStripMenuItem7
|
||||
//
|
||||
this.toolStripMenuItem7.Name = "toolStripMenuItem7";
|
||||
this.toolStripMenuItem7.Size = new System.Drawing.Size(143, 6);
|
||||
this.toolStripMenuItem7.Size = new System.Drawing.Size(149, 6);
|
||||
//
|
||||
// mnuRecentFiles
|
||||
//
|
||||
this.mnuRecentFiles.Name = "mnuRecentFiles";
|
||||
this.mnuRecentFiles.Size = new System.Drawing.Size(146, 22);
|
||||
this.mnuRecentFiles.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuRecentFiles.Text = "Recent Files";
|
||||
//
|
||||
// toolStripMenuItem6
|
||||
//
|
||||
this.toolStripMenuItem6.Name = "toolStripMenuItem6";
|
||||
this.toolStripMenuItem6.Size = new System.Drawing.Size(143, 6);
|
||||
this.toolStripMenuItem6.Size = new System.Drawing.Size(149, 6);
|
||||
//
|
||||
// mnuExit
|
||||
//
|
||||
this.mnuExit.Name = "mnuExit";
|
||||
this.mnuExit.Size = new System.Drawing.Size(146, 22);
|
||||
this.mnuExit.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuExit.Text = "Exit";
|
||||
this.mnuExit.Click += new System.EventHandler(this.mnuExit_Click);
|
||||
//
|
||||
@ -202,7 +205,7 @@
|
||||
this.mnuPause.Enabled = false;
|
||||
this.mnuPause.Name = "mnuPause";
|
||||
this.mnuPause.ShortcutKeyDisplayString = "Esc";
|
||||
this.mnuPause.Size = new System.Drawing.Size(129, 22);
|
||||
this.mnuPause.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuPause.Text = "Pause";
|
||||
this.mnuPause.Click += new System.EventHandler(this.mnuPause_Click);
|
||||
//
|
||||
@ -210,7 +213,7 @@
|
||||
//
|
||||
this.mnuReset.Enabled = false;
|
||||
this.mnuReset.Name = "mnuReset";
|
||||
this.mnuReset.Size = new System.Drawing.Size(129, 22);
|
||||
this.mnuReset.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuReset.Text = "Reset";
|
||||
this.mnuReset.Click += new System.EventHandler(this.mnuReset_Click);
|
||||
//
|
||||
@ -218,7 +221,7 @@
|
||||
//
|
||||
this.mnuStop.Enabled = false;
|
||||
this.mnuStop.Name = "mnuStop";
|
||||
this.mnuStop.Size = new System.Drawing.Size(129, 22);
|
||||
this.mnuStop.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuStop.Text = "Stop";
|
||||
this.mnuStop.Click += new System.EventHandler(this.mnuStop_Click);
|
||||
//
|
||||
@ -227,6 +230,8 @@
|
||||
this.mnuOptions.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.mnuEmulationSpeed,
|
||||
this.mnuShowFPS,
|
||||
this.toolStripMenuItem10,
|
||||
this.mnuAutoLoadIpsPatches,
|
||||
this.toolStripMenuItem1,
|
||||
this.mnuAudioConfig,
|
||||
this.mnuInput,
|
||||
@ -250,7 +255,7 @@
|
||||
this.mnuEmuSpeedHalf,
|
||||
this.mnuEmuSpeedQuarter});
|
||||
this.mnuEmulationSpeed.Name = "mnuEmulationSpeed";
|
||||
this.mnuEmulationSpeed.Size = new System.Drawing.Size(163, 22);
|
||||
this.mnuEmulationSpeed.Size = new System.Drawing.Size(191, 22);
|
||||
this.mnuEmulationSpeed.Text = "Emulation Speed";
|
||||
//
|
||||
// mnuEmuSpeedNormal
|
||||
@ -328,26 +333,26 @@
|
||||
this.mnuShowFPS.CheckOnClick = true;
|
||||
this.mnuShowFPS.Name = "mnuShowFPS";
|
||||
this.mnuShowFPS.ShortcutKeys = System.Windows.Forms.Keys.F10;
|
||||
this.mnuShowFPS.Size = new System.Drawing.Size(163, 22);
|
||||
this.mnuShowFPS.Size = new System.Drawing.Size(191, 22);
|
||||
this.mnuShowFPS.Text = "Show FPS";
|
||||
this.mnuShowFPS.Click += new System.EventHandler(this.mnuShowFPS_Click);
|
||||
//
|
||||
// toolStripMenuItem1
|
||||
//
|
||||
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
|
||||
this.toolStripMenuItem1.Size = new System.Drawing.Size(160, 6);
|
||||
this.toolStripMenuItem1.Size = new System.Drawing.Size(188, 6);
|
||||
//
|
||||
// mnuAudioConfig
|
||||
//
|
||||
this.mnuAudioConfig.Name = "mnuAudioConfig";
|
||||
this.mnuAudioConfig.Size = new System.Drawing.Size(163, 22);
|
||||
this.mnuAudioConfig.Size = new System.Drawing.Size(191, 22);
|
||||
this.mnuAudioConfig.Text = "Audio";
|
||||
this.mnuAudioConfig.Click += new System.EventHandler(this.mnuAudioConfig_Click);
|
||||
//
|
||||
// mnuInput
|
||||
//
|
||||
this.mnuInput.Name = "mnuInput";
|
||||
this.mnuInput.Size = new System.Drawing.Size(163, 22);
|
||||
this.mnuInput.Size = new System.Drawing.Size(191, 22);
|
||||
this.mnuInput.Text = "Input";
|
||||
this.mnuInput.Click += new System.EventHandler(this.mnuInput_Click);
|
||||
//
|
||||
@ -358,7 +363,7 @@
|
||||
this.mnuRegionNtsc,
|
||||
this.mnuRegionPal});
|
||||
this.mnuRegion.Name = "mnuRegion";
|
||||
this.mnuRegion.Size = new System.Drawing.Size(163, 22);
|
||||
this.mnuRegion.Size = new System.Drawing.Size(191, 22);
|
||||
this.mnuRegion.Text = "Region";
|
||||
//
|
||||
// mnuRegionAuto
|
||||
@ -385,7 +390,7 @@
|
||||
// mnuVideoConfig
|
||||
//
|
||||
this.mnuVideoConfig.Name = "mnuVideoConfig";
|
||||
this.mnuVideoConfig.Size = new System.Drawing.Size(163, 22);
|
||||
this.mnuVideoConfig.Size = new System.Drawing.Size(191, 22);
|
||||
this.mnuVideoConfig.Text = "Video";
|
||||
this.mnuVideoConfig.Click += new System.EventHandler(this.mnuVideoConfig_Click);
|
||||
//
|
||||
@ -645,6 +650,18 @@
|
||||
this.mnuTestRecordTest.Text = "Test";
|
||||
this.mnuTestRecordTest.Click += new System.EventHandler(this.mnuTestRecordTest_Click);
|
||||
//
|
||||
// mnuAutoLoadIpsPatches
|
||||
//
|
||||
this.mnuAutoLoadIpsPatches.CheckOnClick = true;
|
||||
this.mnuAutoLoadIpsPatches.Name = "mnuAutoLoadIpsPatches";
|
||||
this.mnuAutoLoadIpsPatches.Size = new System.Drawing.Size(191, 22);
|
||||
this.mnuAutoLoadIpsPatches.Text = "Auto-load IPS patches";
|
||||
//
|
||||
// toolStripMenuItem10
|
||||
//
|
||||
this.toolStripMenuItem10.Name = "toolStripMenuItem10";
|
||||
this.toolStripMenuItem10.Size = new System.Drawing.Size(188, 6);
|
||||
//
|
||||
// frmMain
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
@ -734,6 +751,8 @@
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuTestStopRecording;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuTestRecordMovie;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuTestRecordTest;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem10;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuAutoLoadIpsPatches;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
@ -41,6 +42,8 @@ namespace Mesen.GUI.Forms
|
||||
InitializeEmulationSpeedMenu();
|
||||
|
||||
UpdateVideoSettings();
|
||||
this.mnuAutoLoadIpsPatches.Checked = ConfigManager.Config.AutoLoadIpsPatches;
|
||||
|
||||
InitializeEmu();
|
||||
|
||||
UpdateMenus();
|
||||
@ -60,7 +63,7 @@ namespace Mesen.GUI.Forms
|
||||
{
|
||||
InteropEmu.InitializeEmu(ConfigManager.HomeFolder, this.Handle, this.dxViewer.Handle);
|
||||
foreach(string romPath in ConfigManager.Config.RecentFiles) {
|
||||
InteropEmu.AddKnowGameFolder(System.IO.Path.GetDirectoryName(romPath).ToLowerInvariant());
|
||||
InteropEmu.AddKnowGameFolder(Path.GetDirectoryName(romPath).ToLowerInvariant());
|
||||
}
|
||||
|
||||
ConfigManager.Config.ApplyConfig();
|
||||
@ -139,8 +142,8 @@ namespace Mesen.GUI.Forms
|
||||
{
|
||||
SetEmulationSpeed((uint)(int)((ToolStripItem)sender).Tag);
|
||||
}
|
||||
|
||||
void UpdateEmulationFlags()
|
||||
|
||||
private void UpdateEmulationFlags()
|
||||
{
|
||||
ConfigManager.Config.VideoInfo.ShowFPS = mnuShowFPS.Checked;
|
||||
ConfigManager.ApplyChanges();
|
||||
@ -148,19 +151,25 @@ namespace Mesen.GUI.Forms
|
||||
VideoInfo.ApplyConfig();
|
||||
}
|
||||
|
||||
void UpdateVideoSettings()
|
||||
private void UpdateVideoSettings()
|
||||
{
|
||||
mnuShowFPS.Checked = ConfigManager.Config.VideoInfo.ShowFPS;
|
||||
UpdateEmulationSpeedMenu();
|
||||
dxViewer.Size = VideoInfo.GetViewerSize();
|
||||
}
|
||||
|
||||
void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
|
||||
private void UpdateConfig()
|
||||
{
|
||||
ConfigManager.Config.AutoLoadIpsPatches = this.mnuAutoLoadIpsPatches.Checked;
|
||||
ConfigManager.ApplyChanges();
|
||||
}
|
||||
|
||||
private void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
|
||||
{
|
||||
MessageBox.Show(e.Exception.ToString(), "Unexpected Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
|
||||
void _notifListener_OnNotification(InteropEmu.NotificationEventArgs e)
|
||||
private void _notifListener_OnNotification(InteropEmu.NotificationEventArgs e)
|
||||
{
|
||||
if(e.NotificationType == InteropEmu.ConsoleNotificationType.GameLoaded) {
|
||||
CheatInfo.ApplyCheats();
|
||||
@ -176,10 +185,43 @@ namespace Mesen.GUI.Forms
|
||||
private void mnuOpen_Click(object sender, EventArgs e)
|
||||
{
|
||||
OpenFileDialog ofd = new OpenFileDialog();
|
||||
ofd.Filter = "All supported formats (*.nes, *.zip)|*.NES;*.ZIP|NES Roms (*.nes)|*.NES|ZIP Archives (*.zip)|*.ZIP|All (*.*)|*.*";
|
||||
ofd.InitialDirectory = System.IO.Path.GetDirectoryName(ConfigManager.Config.RecentFiles[0]);
|
||||
ofd.Filter = "All supported formats (*.nes, *.zip, *.ips)|*.NES;*.ZIP;*.IPS|NES Roms (*.nes)|*.NES|ZIP Archives (*.zip)|*.ZIP|IPS Patches (*.ips)|*.IPS|All (*.*)|*.*";
|
||||
if(ConfigManager.Config.RecentFiles.Count > 0) {
|
||||
ofd.InitialDirectory = Path.GetDirectoryName(ConfigManager.Config.RecentFiles[0]);
|
||||
}
|
||||
if(ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
|
||||
LoadROM(ofd.FileName);
|
||||
if(Path.GetExtension(ofd.FileName).ToLowerInvariant() == ".ips") {
|
||||
string ipsFile = ofd.FileName;
|
||||
string romFile = Path.Combine(Path.GetDirectoryName(ofd.FileName), Path.GetFileNameWithoutExtension(ofd.FileName));
|
||||
|
||||
if(File.Exists(romFile+".nes") || File.Exists(romFile+".zip")) {
|
||||
LoadROM(romFile + (File.Exists(romFile+".nes") ? ".nes" : ".zip"));
|
||||
InteropEmu.ApplyIpsPatch(ipsFile);
|
||||
} else {
|
||||
if(_emuThread == null) {
|
||||
if(MessageBox.Show("Please select a ROM matching the IPS patch file.", string.Empty, MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.OK) {
|
||||
ofd.Filter = "All supported formats (*.nes, *.zip)|*.NES;*.ZIP|NES Roms (*.nes)|*.NES|ZIP Archives (*.zip)|*.ZIP|All (*.*)|*.*";
|
||||
if(ConfigManager.Config.RecentFiles.Count > 0) {
|
||||
ofd.InitialDirectory = Path.GetDirectoryName(ConfigManager.Config.RecentFiles[0]);
|
||||
}
|
||||
if(ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
|
||||
LoadROM(ofd.FileName);
|
||||
}
|
||||
InteropEmu.ApplyIpsPatch(ipsFile);
|
||||
}
|
||||
} else if(MessageBox.Show("Patch and reset the current game?", string.Empty, MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.OK) {
|
||||
InteropEmu.ApplyIpsPatch(ipsFile);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LoadROM(ofd.FileName);
|
||||
if(this.mnuAutoLoadIpsPatches.Checked) {
|
||||
string ipsFile = Path.Combine(Path.GetDirectoryName(ofd.FileName), Path.GetFileNameWithoutExtension(ofd.FileName)) + ".ips";
|
||||
if(File.Exists(ipsFile)) {
|
||||
InteropEmu.ApplyIpsPatch(ipsFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,7 +238,7 @@ namespace Mesen.GUI.Forms
|
||||
if(this.InvokeRequired) {
|
||||
this.BeginInvoke((MethodInvoker)(() => this.UpdateMenus()));
|
||||
} else {
|
||||
string romFilename = System.IO.Path.GetFileNameWithoutExtension(InteropEmu.GetROMPath());
|
||||
string romFilename = Path.GetFileNameWithoutExtension(InteropEmu.GetROMPath());
|
||||
if(string.IsNullOrWhiteSpace(romFilename)) {
|
||||
this.Text = "Mesen";
|
||||
} else {
|
||||
@ -249,7 +291,7 @@ namespace Mesen.GUI.Forms
|
||||
mnuRecentFiles.DropDownItems.Clear();
|
||||
foreach(string filepath in ConfigManager.Config.RecentFiles) {
|
||||
ToolStripMenuItem tsmi = new ToolStripMenuItem();
|
||||
tsmi.Text = System.IO.Path.GetFileName(filepath);
|
||||
tsmi.Text = Path.GetFileName(filepath);
|
||||
tsmi.Click += (object sender, EventArgs args) => {
|
||||
LoadROM(filepath);
|
||||
};
|
||||
@ -445,7 +487,7 @@ namespace Mesen.GUI.Forms
|
||||
SaveFileDialog sfd = new SaveFileDialog();
|
||||
sfd.Filter = "Movie files (*.mmo)|*.mmo|All (*.*)|*.*";
|
||||
sfd.InitialDirectory = ConfigManager.MovieFolder;
|
||||
sfd.FileName = System.IO.Path.GetFileNameWithoutExtension(InteropEmu.GetROMPath()) + ".mmo";
|
||||
sfd.FileName = Path.GetFileNameWithoutExtension(InteropEmu.GetROMPath()) + ".mmo";
|
||||
if(sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
|
||||
InteropEmu.MovieRecord(sfd.FileName, resetEmu);
|
||||
}
|
||||
@ -493,9 +535,9 @@ namespace Mesen.GUI.Forms
|
||||
bool result = InteropEmu.RomTestRun(filename);
|
||||
|
||||
if(result) {
|
||||
passedTests.Add(System.IO.Path.GetFileNameWithoutExtension(filename));
|
||||
passedTests.Add(Path.GetFileNameWithoutExtension(filename));
|
||||
} else {
|
||||
failedTests.Add(System.IO.Path.GetFileNameWithoutExtension(filename));
|
||||
failedTests.Add(Path.GetFileNameWithoutExtension(filename));
|
||||
}
|
||||
}
|
||||
|
||||
@ -539,7 +581,7 @@ namespace Mesen.GUI.Forms
|
||||
SaveFileDialog sfd = new SaveFileDialog();
|
||||
sfd.Filter = "Test files (*.mtp)|*.mtp|All (*.*)|*.*";
|
||||
sfd.InitialDirectory = ConfigManager.TestFolder;
|
||||
sfd.FileName = System.IO.Path.GetFileNameWithoutExtension(InteropEmu.GetROMPath()) + ".mtp";
|
||||
sfd.FileName = Path.GetFileNameWithoutExtension(InteropEmu.GetROMPath()) + ".mtp";
|
||||
if(sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
|
||||
InteropEmu.RomTestRecord(sfd.FileName, resetEmu);
|
||||
}
|
||||
@ -554,7 +596,7 @@ namespace Mesen.GUI.Forms
|
||||
SaveFileDialog sfd = new SaveFileDialog();
|
||||
sfd.Filter = "Test files (*.mtp)|*.mtp|All (*.*)|*.*";
|
||||
sfd.InitialDirectory = ConfigManager.TestFolder;
|
||||
sfd.FileName = System.IO.Path.GetFileNameWithoutExtension(ofd.FileName) + ".mtp";
|
||||
sfd.FileName = Path.GetFileNameWithoutExtension(ofd.FileName) + ".mtp";
|
||||
if(sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
|
||||
InteropEmu.RomTestRecordFromMovie(sfd.FileName, ofd.FileName);
|
||||
}
|
||||
@ -571,7 +613,7 @@ namespace Mesen.GUI.Forms
|
||||
SaveFileDialog sfd = new SaveFileDialog();
|
||||
sfd.Filter = "Test files (*.mtp)|*.mtp|All (*.*)|*.*";
|
||||
sfd.InitialDirectory = ConfigManager.TestFolder;
|
||||
sfd.FileName = System.IO.Path.GetFileNameWithoutExtension(ofd.FileName) + ".mtp";
|
||||
sfd.FileName = Path.GetFileNameWithoutExtension(ofd.FileName) + ".mtp";
|
||||
if(sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
|
||||
InteropEmu.RomTestRecordFromTest(sfd.FileName, ofd.FileName);
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ namespace Mesen.GUI
|
||||
[DllImport(DLLPath)] public static extern void Release();
|
||||
|
||||
[DllImport(DLLPath)] public static extern void LoadROM([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string filename);
|
||||
[DllImport(DLLPath)] public static extern void ApplyIpsPatch([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string filename);
|
||||
[DllImport(DLLPath)] public static extern void AddKnowGameFolder([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string folder);
|
||||
|
||||
[DllImport(DLLPath)] public static extern void AddKeyMappings(int port, KeyMapping mapping);
|
||||
|
@ -62,6 +62,7 @@ namespace InteropEmu {
|
||||
}
|
||||
|
||||
DllExport void __stdcall LoadROM(char* filename) { Console::LoadROM(filename); }
|
||||
DllExport void __stdcall ApplyIpsPatch(char* filename) { Console::ApplyIpsPatch(filename); }
|
||||
DllExport void __stdcall AddKnowGameFolder(char* folder) { FolderUtilities::AddKnowGameFolder(folder); }
|
||||
|
||||
DllExport void __stdcall AddKeyMappings(uint32_t port, KeyMapping mapping) { _inputDevices[port]->AddKeyMappings(mapping); }
|
||||
|
113
Utilities/IpsPatcher.cpp
Normal file
113
Utilities/IpsPatcher.cpp
Normal file
@ -0,0 +1,113 @@
|
||||
#include "stdafx.h"
|
||||
#include "IpsPatcher.h"
|
||||
|
||||
class IpsRecord
|
||||
{
|
||||
public:
|
||||
uint32_t Address = 0;
|
||||
uint16_t Length = 0;
|
||||
uint8_t* Replacement = nullptr;
|
||||
|
||||
//For RLE records (when length == 0)
|
||||
uint16_t RepeatCount = 0;
|
||||
uint8_t Value = 0;
|
||||
|
||||
bool ReadRecord(ifstream &ipsFile)
|
||||
{
|
||||
uint8_t buffer[3];
|
||||
|
||||
ipsFile.read((char*)buffer, 3);
|
||||
if(memcmp(buffer, "EOF", 3) == 0) {
|
||||
//EOF reached
|
||||
return false;
|
||||
} else {
|
||||
Address = buffer[2] | (buffer[1] << 8) | (buffer[0] << 16);
|
||||
|
||||
ipsFile.read((char*)buffer, 2);
|
||||
Length = buffer[1] | (buffer[0] << 8);
|
||||
|
||||
if(Length == 0) {
|
||||
//RLE record
|
||||
ipsFile.read((char*)buffer, 3);
|
||||
RepeatCount = buffer[1] | (buffer[0] << 8);
|
||||
Value = buffer[2];
|
||||
} else {
|
||||
Replacement = new uint8_t[Length];
|
||||
ipsFile.read((char*)Replacement, Length);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
~IpsRecord()
|
||||
{
|
||||
if(Replacement != nullptr) {
|
||||
delete[] Replacement;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
bool IpsPatcher::PatchBuffer(string ipsFilepath, uint8_t* inputBuffer, size_t inputBufferSize, uint8_t** outputBuffer, size_t &outputBufferSize)
|
||||
{
|
||||
ifstream ipsFile(ipsFilepath, std::ios::in | std::ios::binary);
|
||||
|
||||
if(ipsFile) {
|
||||
char header[5];
|
||||
ipsFile.read((char*)&header, 5);
|
||||
if(memcmp((char*)&header, "PATCH", 5) != 0) {
|
||||
//Invalid ips file
|
||||
return false;
|
||||
}
|
||||
|
||||
vector<IpsRecord*> records;
|
||||
int32_t truncateOffset = -1;
|
||||
size_t maxOutputSize = inputBufferSize;
|
||||
while(!ipsFile.eof()) {
|
||||
IpsRecord *record = new IpsRecord();
|
||||
if(record->ReadRecord(ipsFile)) {
|
||||
if(record->Address + record->Length + record->RepeatCount > maxOutputSize) {
|
||||
maxOutputSize = record->Address + record->Length + record->RepeatCount;
|
||||
}
|
||||
records.push_back(record);
|
||||
} else {
|
||||
//EOF, try to read truncate offset record if it exists
|
||||
uint8_t buffer[3];
|
||||
ipsFile.read((char*)buffer, 3);
|
||||
if(!ipsFile.eof()) {
|
||||
truncateOffset = buffer[2] | (buffer[1] << 8) | (buffer[0] << 16);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
outputBufferSize = maxOutputSize;
|
||||
uint8_t *output = new uint8_t[outputBufferSize];
|
||||
memset(output, 0, outputBufferSize);
|
||||
memcpy(output, inputBuffer, inputBufferSize);
|
||||
|
||||
for(IpsRecord *record : records) {
|
||||
if(record->Length == 0) {
|
||||
memset(output+record->Address, record->Value, record->RepeatCount);
|
||||
} else {
|
||||
memcpy(output+record->Address, record->Replacement, record->Length);
|
||||
}
|
||||
|
||||
delete record;
|
||||
}
|
||||
|
||||
if(truncateOffset != -1 && (int32_t)outputBufferSize > truncateOffset) {
|
||||
uint8_t* truncatedOutput = new uint8_t[truncateOffset];
|
||||
memcpy(truncatedOutput, output, truncateOffset);
|
||||
delete[] output;
|
||||
*outputBuffer = truncatedOutput;
|
||||
} else {
|
||||
*outputBuffer = output;
|
||||
}
|
||||
|
||||
ipsFile.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
9
Utilities/IpsPatcher.h
Normal file
9
Utilities/IpsPatcher.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
class IpsPatcher
|
||||
{
|
||||
public:
|
||||
static bool PatchBuffer(string ipsFilepath, uint8_t* inputBuffer, size_t inputBufferSize, uint8_t** outputBuffer, size_t &outputBufferSize);
|
||||
};
|
@ -230,6 +230,7 @@
|
||||
<ItemGroup>
|
||||
<ClInclude Include="CRC32.h" />
|
||||
<ClInclude Include="FolderUtilities.h" />
|
||||
<ClInclude Include="IpsPatcher.h" />
|
||||
<ClInclude Include="md5.h" />
|
||||
<ClInclude Include="miniz.h" />
|
||||
<ClInclude Include="AutoResetEvent.h" />
|
||||
@ -247,6 +248,7 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="CRC32.cpp" />
|
||||
<ClCompile Include="FolderUtilities.cpp" />
|
||||
<ClCompile Include="IpsPatcher.cpp" />
|
||||
<ClCompile Include="md5.cpp" />
|
||||
<ClCompile Include="miniz.cpp" />
|
||||
<ClCompile Include="PNGHelper.cpp" />
|
||||
|
@ -56,6 +56,9 @@
|
||||
<ClInclude Include="ZipReader.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="IpsPatcher.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
@ -100,5 +103,8 @@
|
||||
<ClCompile Include="ZipReader.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="IpsPatcher.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
Loading…
x
Reference in New Issue
Block a user