mirror of
https://github.com/SourMesen/Mesen-S.git
synced 2024-06-23 06:41:55 -04:00
UI: Added prompt for firmware files when loading a game that requires one
This commit is contained in:
parent
25968c48b5
commit
aa5e26855c
59
Core/BiosHelper.h
Normal file
59
Core/BiosHelper.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "Console.h"
|
||||
#include "NotificationManager.h"
|
||||
#include "../Utilities/FolderUtilities.h"
|
||||
|
||||
struct MissingBiosMessage
|
||||
{
|
||||
const char* Filename;
|
||||
CoprocessorType BiosType;
|
||||
uint32_t Size;
|
||||
};
|
||||
|
||||
class BiosHelper
|
||||
{
|
||||
private:
|
||||
static bool AttemptLoadDspBios(string combinedFilename, string splitFilenameProgram, string splitFilenameData, vector<uint8_t> &programRom, vector<uint8_t> &dataRom, uint32_t programSize, uint32_t dataSize)
|
||||
{
|
||||
VirtualFile combinedBios(FolderUtilities::CombinePath(FolderUtilities::GetBiosFolder(), combinedFilename));
|
||||
if(combinedBios.GetSize() == programSize + dataSize) {
|
||||
vector<uint8_t> biosData;
|
||||
combinedBios.ReadFile(biosData);
|
||||
programRom.insert(programRom.end(), biosData.begin(), biosData.begin() + programSize);
|
||||
dataRom.insert(dataRom.end(), biosData.begin() + programSize, biosData.end());
|
||||
return true;
|
||||
} else {
|
||||
VirtualFile splitBiosProg(FolderUtilities::CombinePath(FolderUtilities::GetBiosFolder(), splitFilenameProgram));
|
||||
VirtualFile splitBiosData(FolderUtilities::CombinePath(FolderUtilities::GetBiosFolder(), splitFilenameData));
|
||||
|
||||
if(splitBiosProg.GetSize() == programSize && splitBiosData.GetSize() == dataSize) {
|
||||
splitBiosProg.ReadFile(programRom);
|
||||
splitBiosData.ReadFile(dataRom);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public:
|
||||
static bool LoadDspBios(Console *console, CoprocessorType coprocessorType, string combinedFilename, string splitFilenameProgram, string splitFilenameData, vector<uint8_t> &programRom, vector<uint8_t> &dataRom, uint32_t programSize = 0x1800, uint32_t dataSize = 0x800)
|
||||
{
|
||||
if(AttemptLoadDspBios(combinedFilename, splitFilenameProgram, splitFilenameData, programRom, dataRom, programSize, dataSize)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
MissingBiosMessage msg;
|
||||
msg.Filename = combinedFilename.c_str();
|
||||
msg.BiosType = coprocessorType;
|
||||
msg.Size = programSize + dataSize;
|
||||
console->GetNotificationManager()->SendNotification(ConsoleNotificationType::MissingBios, &msg);
|
||||
|
||||
//Try again in case the user selected a valid bios file
|
||||
if(AttemptLoadDspBios(combinedFilename, splitFilenameProgram, splitFilenameData, programRom, dataRom, programSize, dataSize)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
MessageManager::DisplayMessage("Error", "Could not find BIOS file for DSP: " + combinedFilename);
|
||||
return false;
|
||||
}
|
||||
};
|
|
@ -51,6 +51,7 @@
|
|||
<ClInclude Include="BaseRenderer.h" />
|
||||
<ClInclude Include="BaseSoundManager.h" />
|
||||
<ClInclude Include="BaseVideoFilter.h" />
|
||||
<ClInclude Include="BiosHelper.h" />
|
||||
<ClInclude Include="blargg_common.h" />
|
||||
<ClInclude Include="blargg_config.h" />
|
||||
<ClInclude Include="blargg_endian.h" />
|
||||
|
|
|
@ -302,6 +302,9 @@
|
|||
<ClInclude Include="NecDspTypes.h">
|
||||
<Filter>SNES\Coprocessors</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="BiosHelper.h">
|
||||
<Filter>Misc</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp" />
|
||||
|
|
|
@ -17,7 +17,8 @@ enum class ConsoleNotificationType
|
|||
EmulationStopped = 11,
|
||||
BeforeEmulationStop = 12,
|
||||
ViewerRefresh = 13,
|
||||
EventViewerRefresh = 14
|
||||
EventViewerRefresh = 14,
|
||||
MissingBios = 15
|
||||
};
|
||||
|
||||
class INotificationListener
|
||||
|
|
|
@ -2,11 +2,13 @@
|
|||
#include "NecDsp.h"
|
||||
#include "MemoryManager.h"
|
||||
#include "Console.h"
|
||||
#include "NotificationManager.h"
|
||||
#include "BaseCartridge.h"
|
||||
#include "CartTypes.h"
|
||||
#include "MessageManager.h"
|
||||
#include "EmuSettings.h"
|
||||
#include "RamHandler.h"
|
||||
#include "BiosHelper.h"
|
||||
#include "../Utilities/FolderUtilities.h"
|
||||
|
||||
NecDsp::NecDsp(CoprocessorType type, Console* console, vector<uint8_t> &programRom, vector<uint8_t> &dataRom)
|
||||
|
@ -71,43 +73,19 @@ NecDsp::NecDsp(CoprocessorType type, Console* console, vector<uint8_t> &programR
|
|||
}
|
||||
}
|
||||
|
||||
bool NecDsp::LoadBios(string combinedFilename, string splitFilenameProgram, string splitFilenameData, vector<uint8_t> &programRom, vector<uint8_t> &dataRom, uint32_t programSize = 0x1800, uint32_t dataSize = 0x800)
|
||||
{
|
||||
VirtualFile combinedBios(FolderUtilities::CombinePath(FolderUtilities::GetBiosFolder(), combinedFilename));
|
||||
if(combinedBios.GetSize() == programSize+dataSize) {
|
||||
vector<uint8_t> biosData;
|
||||
combinedBios.ReadFile(biosData);
|
||||
programRom.insert(programRom.end(), biosData.begin(), biosData.begin() + programSize);
|
||||
dataRom.insert(dataRom.end(), biosData.begin() + programSize, biosData.end());
|
||||
return true;
|
||||
} else {
|
||||
VirtualFile splitBiosProg(FolderUtilities::CombinePath(FolderUtilities::GetBiosFolder(), splitFilenameProgram));
|
||||
VirtualFile splitBiosData(FolderUtilities::CombinePath(FolderUtilities::GetBiosFolder(), splitFilenameData));
|
||||
|
||||
if(splitBiosProg.GetSize() == programSize && splitBiosData.GetSize() == dataSize) {
|
||||
splitBiosProg.ReadFile(programRom);
|
||||
splitBiosData.ReadFile(dataRom);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
MessageManager::DisplayMessage("Error", "Could not find BIOS file for DSP: " + combinedFilename);
|
||||
return false;
|
||||
}
|
||||
|
||||
NecDsp* NecDsp::InitCoprocessor(CoprocessorType type, Console *console)
|
||||
{
|
||||
bool biosLoaded = false;
|
||||
vector<uint8_t> programRom;
|
||||
vector<uint8_t> dataRom;
|
||||
switch(type) {
|
||||
case CoprocessorType::DSP1: biosLoaded = LoadBios("dsp1.rom", "dsp1.program.rom", "dsp1.data.rom", programRom, dataRom); break;
|
||||
case CoprocessorType::DSP1B: biosLoaded = LoadBios("dsp1b.rom", "dsp1b.program.rom", "dsp1b.data.rom", programRom, dataRom); break;
|
||||
case CoprocessorType::DSP2: biosLoaded = LoadBios("dsp2.rom", "dsp2.program.rom", "dsp2.data.rom", programRom, dataRom); break;
|
||||
case CoprocessorType::DSP3: biosLoaded = LoadBios("dsp3.rom", "dsp3.program.rom", "dsp3.data.rom", programRom, dataRom); break;
|
||||
case CoprocessorType::DSP4: biosLoaded = LoadBios("dsp4.rom", "dsp4.program.rom", "dsp4.data.rom", programRom, dataRom); break;
|
||||
case CoprocessorType::ST010: biosLoaded = LoadBios("st010.rom", "st010.program.rom", "st010.data.rom", programRom, dataRom, 0xC000, 0x1000); break;
|
||||
case CoprocessorType::ST011: biosLoaded = LoadBios("st011.rom", "st011.program.rom", "st011.data.rom", programRom, dataRom, 0xC000, 0x1000); break;
|
||||
case CoprocessorType::DSP1: biosLoaded = BiosHelper::LoadDspBios(console, type, "dsp1.rom", "dsp1.program.rom", "dsp1.data.rom", programRom, dataRom); break;
|
||||
case CoprocessorType::DSP1B: biosLoaded = BiosHelper::LoadDspBios(console, type, "dsp1b.rom", "dsp1b.program.rom", "dsp1b.data.rom", programRom, dataRom); break;
|
||||
case CoprocessorType::DSP2: biosLoaded = BiosHelper::LoadDspBios(console, type, "dsp2.rom", "dsp2.program.rom", "dsp2.data.rom", programRom, dataRom); break;
|
||||
case CoprocessorType::DSP3: biosLoaded = BiosHelper::LoadDspBios(console, type, "dsp3.rom", "dsp3.program.rom", "dsp3.data.rom", programRom, dataRom); break;
|
||||
case CoprocessorType::DSP4: biosLoaded = BiosHelper::LoadDspBios(console, type, "dsp4.rom", "dsp4.program.rom", "dsp4.data.rom", programRom, dataRom); break;
|
||||
case CoprocessorType::ST010: biosLoaded = BiosHelper::LoadDspBios(console, type, "st010.rom", "st010.program.rom", "st010.data.rom", programRom, dataRom, 0xC000, 0x1000); break;
|
||||
case CoprocessorType::ST011: biosLoaded = BiosHelper::LoadDspBios(console, type, "st011.rom", "st011.program.rom", "st011.data.rom", programRom, dataRom, 0xC000, 0x1000); break;
|
||||
}
|
||||
|
||||
if(!biosLoaded) {
|
||||
|
|
|
@ -48,7 +48,7 @@ private:
|
|||
void Load(uint8_t dest, uint16_t value);
|
||||
uint16_t GetSourceValue(uint8_t source);
|
||||
|
||||
static bool LoadBios(string combinedFilename, string splitFilenameProgram, string splitFilenameData, vector<uint8_t> &programRom, vector<uint8_t> &dataRom, uint32_t programSize, uint32_t dataSize);
|
||||
static bool LoadBios(Console *console, string combinedFilename, string splitFilenameProgram, string splitFilenameData, vector<uint8_t> &programRom, vector<uint8_t> &dataRom, uint32_t programSize, uint32_t dataSize);
|
||||
|
||||
NecDsp(CoprocessorType type, Console* console, vector<uint8_t> &programRom, vector<uint8_t> &dataRom);
|
||||
|
||||
|
|
|
@ -211,6 +211,7 @@ namespace Mesen.GUI.Config
|
|||
public static string WaveFolder { get { return GetFolder(DefaultWaveFolder, Config.Preferences.WaveFolder, Config.Preferences.OverrideWaveFolder); } }
|
||||
|
||||
public static string DebuggerFolder { get { return GetFolder(Path.Combine(ConfigManager.HomeFolder, "Debugger"), null, false); } }
|
||||
public static string BiosFolder { get { return GetFolder(Path.Combine(ConfigManager.HomeFolder, "Bios"), null, false); } }
|
||||
public static string DownloadFolder { get { return GetFolder(Path.Combine(ConfigManager.HomeFolder, "Downloads"), null, false); } }
|
||||
public static string BackupFolder { get { return GetFolder(Path.Combine(ConfigManager.HomeFolder, "Backups"), null, false); } }
|
||||
public static string TestFolder { get { return GetFolder(Path.Combine(ConfigManager.HomeFolder, "Tests"), null, false); } }
|
||||
|
|
|
@ -851,9 +851,9 @@ namespace Mesen.GUI.Debugger.Integration
|
|||
message += Environment.NewLine + file;
|
||||
}
|
||||
}
|
||||
MessageBox.Show(message, "Mesen", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
MessageBox.Show(message, "Mesen-S", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
} else {
|
||||
MessageBox.Show($"Import completed with {labelCount} labels imported.", "Mesen", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
MessageBox.Show($"Import completed with {labelCount} labels imported.", "Mesen-S", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -689,6 +689,9 @@
|
|||
<Message ID="ClearHistory">Clear History</Message>
|
||||
<Message ID="LastFolderUsed">Last Folder Used</Message>
|
||||
|
||||
<Message ID="BiosNotFound">This game requires a firmware file for the {0} chip.

 Filename: {1}
 Size: {2} bytes

Would you like to select it now?</Message>
|
||||
<Message ID="BiosMismatch">The selected file does not match the firmware required for this chip ({0}).

Firmware SHA-256:
{1}

Selected file's SHA-256:
{2}

Would you like to use this file anyway?</Message>
|
||||
|
||||
<Message ID="MouseModeEnabled">Mouse mode enabled - press ESC or pause to release the cursor.</Message>
|
||||
<Message ID="BandaiMicrophone">Bandai Microphone</Message>
|
||||
<Message ID="DatachBarcodeReader">Datach Barcode Reader</Message>
|
||||
|
|
|
@ -15,20 +15,20 @@ namespace Mesen.GUI.Forms
|
|||
|
||||
if(resourceText.StartsWith("[[")) {
|
||||
if(args != null && args.Length > 0) {
|
||||
return MessageBox.Show(string.Format("Critical error (" + text + ") {0}", args), "Mesen", buttons, icon);
|
||||
return MessageBox.Show(string.Format("Critical error (" + text + ") {0}", args), "Mesen-S", buttons, icon);
|
||||
} else {
|
||||
return MessageBox.Show(string.Format("Critical error (" + text + ")"), "Mesen", buttons, icon);
|
||||
return MessageBox.Show(string.Format("Critical error (" + text + ")"), "Mesen-S", buttons, icon);
|
||||
}
|
||||
} else {
|
||||
Form mainForm = Application.OpenForms.Count > 0 ? Application.OpenForms[0] : null;
|
||||
if(mainForm?.InvokeRequired == true) {
|
||||
DialogResult result = DialogResult.Cancel;
|
||||
mainForm.Invoke((Action)(() => {
|
||||
result = MessageBox.Show(mainForm, ResourceHelper.GetMessage(text, args), "Mesen", buttons, icon);
|
||||
result = MessageBox.Show(mainForm, ResourceHelper.GetMessage(text, args), "Mesen-S", buttons, icon);
|
||||
}));
|
||||
return result;
|
||||
} else {
|
||||
return MessageBox.Show(ResourceHelper.GetMessage(text, args), "Mesen", buttons, icon);
|
||||
return MessageBox.Show(ResourceHelper.GetMessage(text, args), "Mesen-S", buttons, icon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ using System.Diagnostics;
|
|||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -166,6 +167,13 @@ namespace Mesen.GUI.Forms
|
|||
_shortcuts.ExecuteShortcut((EmulatorShortcut)e.Parameter);
|
||||
}));
|
||||
break;
|
||||
|
||||
case ConsoleNotificationType.MissingBios:
|
||||
this.Invoke((Action)(() => {
|
||||
MissingBiosMessage msg = (MissingBiosMessage)Marshal.PtrToStructure(e.Parameter, typeof(MissingBiosMessage));
|
||||
BiosHelper.RequestBiosFile(msg);
|
||||
}));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -154,4 +154,34 @@ namespace Mesen.GUI
|
|||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
|
||||
public byte[] Checksum;
|
||||
}
|
||||
|
||||
public enum CoprocessorType
|
||||
{
|
||||
None,
|
||||
DSP1,
|
||||
DSP1B,
|
||||
DSP2,
|
||||
DSP3,
|
||||
DSP4,
|
||||
GSU1,
|
||||
GSU2,
|
||||
MarioChip,
|
||||
OBC1,
|
||||
SA1,
|
||||
DD1,
|
||||
RTC,
|
||||
Satellaview,
|
||||
SPC7110,
|
||||
ST010,
|
||||
ST011,
|
||||
ST018,
|
||||
CX4
|
||||
}
|
||||
|
||||
public struct MissingBiosMessage
|
||||
{
|
||||
public IntPtr Filename;
|
||||
public CoprocessorType BiosType;
|
||||
public UInt32 Size;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,5 +62,6 @@ namespace Mesen.GUI
|
|||
BeforeEmulationStop = 12,
|
||||
ViewerRefresh = 13,
|
||||
EventViewerRefresh = 14,
|
||||
MissingBios = 15
|
||||
}
|
||||
}
|
||||
|
|
|
@ -812,6 +812,7 @@
|
|||
<Compile Include="RuntimeChecker.cs" />
|
||||
<Compile Include="SingleInstance.cs" />
|
||||
<Compile Include="Utilities\ArchiveHelper.cs" />
|
||||
<Compile Include="Utilities\BiosHelper.cs" />
|
||||
<Compile Include="Utilities\CommandLineHelper.cs" />
|
||||
<Compile Include="Utilities\FolderHelper.cs" />
|
||||
<Compile Include="Utilities\HexConverter.cs" />
|
||||
|
|
66
UI/Utilities/BiosHelper.cs
Normal file
66
UI/Utilities/BiosHelper.cs
Normal file
|
@ -0,0 +1,66 @@
|
|||
using Mesen.GUI.Config;
|
||||
using Mesen.GUI.Forms;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Mesen.GUI.Utilities
|
||||
{
|
||||
public static class BiosHelper
|
||||
{
|
||||
private static string GetFileHash(string filename)
|
||||
{
|
||||
using(SHA256 sha256Hash = SHA256.Create()) {
|
||||
// ComputeHash - returns byte array
|
||||
byte[] bytes = sha256Hash.ComputeHash(File.ReadAllBytes(filename));
|
||||
|
||||
// Convert byte array to a string
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for(int i = 0; i < bytes.Length; i++) {
|
||||
builder.Append(bytes[i].ToString("X2"));
|
||||
}
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetExpectedHash(CoprocessorType type)
|
||||
{
|
||||
switch(type) {
|
||||
case CoprocessorType.CX4: return "AE8D4D1961B93421FF00B3CAA1D0F0CE7783E749772A3369C36B3DBF0D37EF18";
|
||||
case CoprocessorType.DSP1: return "91E87D11E1C30D172556BED2211CCE2EFA94BA595F58C5D264809EF4D363A97B";
|
||||
case CoprocessorType.DSP1B: return "D789CB3C36B05C0B23B6C6F23BE7AA37C6E78B6EE9CEAC8D2D2AA9D8C4D35FA9";
|
||||
case CoprocessorType.DSP2: return "03EF4EF26C9F701346708CB5D07847B5203CF1B0818BF2930ACD34510FFDD717";
|
||||
case CoprocessorType.DSP3: return "0971B08F396C32E61989D1067DDDF8E4B14649D548B2188F7C541B03D7C69E4E";
|
||||
case CoprocessorType.DSP4: return "752D03B2D74441E430B7F713001FA241F8BBCFC1A0D890ED4143F174DBE031DA";
|
||||
case CoprocessorType.ST010: return "FA9BCED838FEDEA11C6F6ACE33D1878024BDD0D02CC9485899D0BDD4015EC24C";
|
||||
case CoprocessorType.ST011: return "8B2B3F3F3E6E29F4D21D8BC736B400BC988B7D2214EBEE15643F01C1FEE2F364";
|
||||
case CoprocessorType.ST018: return "6DF209AB5D2524D1839C038BE400AE5EB20DAFC14A3771A3239CD9E8ACD53806";
|
||||
}
|
||||
throw new Exception("Unexpected coprocessor type");
|
||||
}
|
||||
|
||||
public static void RequestBiosFile(MissingBiosMessage msg)
|
||||
{
|
||||
string filename = Utf8Marshaler.GetStringFromIntPtr(msg.Filename);
|
||||
if(MesenMsgBox.Show("BiosNotFound", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, msg.BiosType.ToString(), filename, msg.Size.ToString()) == DialogResult.OK) {
|
||||
using(OpenFileDialog ofd = new OpenFileDialog()) {
|
||||
ofd.SetFilter(ResourceHelper.GetMessage("FilterAll"));
|
||||
if(ofd.ShowDialog(Application.OpenForms[0]) == DialogResult.OK) {
|
||||
if(GetFileHash(ofd.FileName) != GetExpectedHash(msg.BiosType)) {
|
||||
if(MesenMsgBox.Show("BiosMismatch", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning, msg.BiosType.ToString(), GetFileHash(ofd.FileName), GetExpectedHash(msg.BiosType)) != DialogResult.OK) {
|
||||
//Files don't match and user cancelled the action
|
||||
return;
|
||||
}
|
||||
}
|
||||
File.Copy(ofd.FileName, Path.Combine(ConfigManager.BiosFolder, filename));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue