refactor a bit of firmware loading code to get some slop out of MainForm.LoadRom()

This commit is contained in:
goyuken 2013-12-09 20:36:24 +00:00
parent ada517d433
commit 2a0217e06c
11 changed files with 139 additions and 119 deletions

View File

@ -365,6 +365,7 @@
<DependentUpon>MainForm.cs</DependentUpon>
<SubType>Form</SubType>
</Compile>
<Compile Include="MFEmuLoadHelper.cs" />
<Compile Include="movie\EditCommentsForm.cs">
<SubType>Form</SubType>
</Compile>

View File

@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using BizHawk.Emulation.Common;
using BizHawk.Client.Common;
using System.IO;
namespace BizHawk.Client.EmuHawk
{
class MFEmuLoadHelper : IEmuLoadHelper
{
IWin32Window parent;
FirmwareManager firmware;
public MFEmuLoadHelper(IWin32Window parent, FirmwareManager firmware)
{
this.parent = parent;
this.firmware = firmware;
}
public void ShowMessage(string msg)
{
MessageBox.Show(parent, msg, "Load Warning");
}
public byte[] GetFirmware(string sysID, string firmwareID, bool required, string msg = null)
{
byte[] ret = null;
string path = firmware.Request(sysID, firmwareID);
if (path != null && File.Exists(path))
{
try
{
ret = File.ReadAllBytes(path);
}
catch (IOException)
{
}
}
if (ret == null)
{
if (required)
{
string fullmsg = string.Format(
"Couldn't find required firmware \"{0}:{1}\". This is fatal{2}", sysID, firmwareID, msg != null ? ": " + msg : ".");
throw new Exception(fullmsg);
}
else
{
if (msg != null)
{
string fullmsg = string.Format(
"Couldn't find firmware \"{0}:{1}\". Will attempt to continue: {2}", sysID, firmwareID, msg);
ShowMessage(msg);
}
}
}
return ret;
}
}
}

View File

@ -63,6 +63,7 @@ namespace BizHawk.Client.EmuHawk
{
GlobalWin.MainForm = this;
Global.FirmwareManager = new FirmwareManager();
EmuLoadHelper = new MFEmuLoadHelper(this, Global.FirmwareManager);
Global.MovieSession = new MovieSession
{
Movie = new Movie(),
@ -918,6 +919,8 @@ namespace BizHawk.Client.EmuHawk
private readonly SaveSlotManager _stateSlots = new SaveSlotManager();
private readonly Dictionary<string, string> _snesPrepared = new Dictionary<string, string>();
private IEmuLoadHelper EmuLoadHelper;
//avi/wav state
private IVideoWriter _currAviWriter;
private ISoundProvider _aviSoundInput;
@ -3032,13 +3035,7 @@ namespace BizHawk.Client.EmuHawk
{
case "SAT":
{
string biosPath = Global.FirmwareManager.Request("SAT", "J");
if (!File.Exists(biosPath))
{
MessageBox.Show("Saturn BIOS not found. Please check firmware configurations.");
return false;
}
var saturn = new Yabause(nextComm, disc, File.ReadAllBytes(biosPath), Global.Config.SaturnUseGL);
var saturn = new Yabause(nextComm, disc, EmuLoadHelper, Global.Config.SaturnUseGL);
nextEmulator = saturn;
SaturnSetPrefs(saturn);
}
@ -3199,23 +3196,7 @@ namespace BizHawk.Client.EmuHawk
break;
case "NES":
{
//TODO - move into nes core
var biosPath = nextComm.CoreFileProvider.PathFirmware("NES", "Bios_FDS");
byte[] bios = null;
if (File.Exists(biosPath))
{
bios = File.ReadAllBytes(biosPath);
// ines header + 24KB of garbage + actual bios + 8KB of garbage
if (bios.Length == 40976)
{
MessageBox.Show(this, "Your FDS BIOS is a bad dump. BizHawk will attempt to use it, but no guarantees! You should find a new one.");
var tmp = new byte[8192];
Buffer.BlockCopy(bios, 16 + 8192 * 3, tmp, 0, 8192);
bios = tmp;
}
}
var nes = new NES(nextComm, game, rom.FileData, bios, Global.MovieSession.Movie.Header.BoardProperties)
var nes = new NES(nextComm, game, rom.FileData, EmuLoadHelper, Global.MovieSession.Movie.Header.BoardProperties)
{
SoundOn = Global.Config.SoundEnabled,
NTSC_FirstDrawLine = Global.Config.NTSC_NESTopLine,
@ -3264,40 +3245,23 @@ namespace BizHawk.Client.EmuHawk
}
else
{
var sgbromPath = Global.FirmwareManager.Request("SNES", "Rom_SGB");
byte[] sgbrom;
try
{
if (File.Exists(sgbromPath))
{
sgbrom = File.ReadAllBytes(sgbromPath);
}
else
{
MessageBox.Show("Couldn't open sgb.sfc from the configured SNES firmwares path, which is:\n\n" + sgbromPath + "\n\nPlease make sure it is available and try again.\n\nWe're going to disable SGB for now; please re-enable it when you've set up the file.");
Global.Config.GB_AsSGB = false;
game.System = "GB";
goto RETRY;
}
}
catch (Exception)
{
// failed to load SGB bios. to avoid catch-22, disable SGB mode
Global.Config.GB_AsSGB = false;
throw;
}
if (sgbrom != null)
{
game.System = "SNES";
game.AddOption("SGB");
nextComm.SNES_ExePath = SNES_Prepare(Global.Config.SNESProfile);
var snes = new LibsnesCore(nextComm);
nextEmulator = snes;
game.FirmwareHash = Util.BytesToHexString(System.Security.Cryptography.SHA1.Create().ComputeHash(sgbrom));
snes.Load(game, rom.FileData, sgbrom, deterministicemulation, null);
snes.Load(game, rom.FileData, EmuLoadHelper, deterministicemulation, null);
}
catch
{
// failed to load SGB bios. to avoid catch-22, disable SGB mode
EmuLoadHelper.ShowMessage("Failed to load a GB rom in SGB mode. Disabling SGB Mode.");
Global.Config.GB_AsSGB = false;
throw;
}
}
//}
break;
case "Coleco":
var colbiosPath = Global.FirmwareManager.Request("Coleco", "Bios");
@ -3332,56 +3296,9 @@ namespace BizHawk.Client.EmuHawk
}
break;
case "A78":
var ntsc_biospath = Global.FirmwareManager.Request("A78", "Bios_NTSC");
var pal_biospath = Global.FirmwareManager.Request("A78", "Bios_PAL");
var hsbiospath = Global.FirmwareManager.Request("A78", "Bios_HSC");
var ntscfile = ntsc_biospath != null ? new FileInfo(ntsc_biospath) : null;
var palfile = pal_biospath != null ? new FileInfo(pal_biospath) : null;
var hsfile = hsbiospath != null ? new FileInfo(hsbiospath) : null;
byte[] NTSC_BIOS7800 = null;
byte[] PAL_BIOS7800 = null;
byte[] HighScoreBIOS = null;
if (ntscfile == null || !ntscfile.Exists)
{
MessageBox.Show("Unable to find the required Atari 7800 BIOS file - \n" + ntsc_biospath + "\nIf the selected game requires it, it may crash", "Unable to load BIOS", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
NTSC_BIOS7800 = File.ReadAllBytes(ntsc_biospath);
}
if (palfile == null || !palfile.Exists)
{
MessageBox.Show("Unable to find the required Atari 7800 BIOS file - \n" + pal_biospath + "\nIf the selected game requires it, it may crash", "Unable to load BIOS", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
PAL_BIOS7800 = File.ReadAllBytes(pal_biospath);
}
if (hsfile == null || !hsfile.Exists)
{
MessageBox.Show("Unable to find the required Atari 7800 BIOS file - \n" + hsbiospath + "\nIf the selected game requires it, it may crash", "Unable to load BIOS", MessageBoxButtons.OK, MessageBoxIcon.Error);
//throw new Exception();
}
else
{
HighScoreBIOS = File.ReadAllBytes(hsbiospath);
}
var gamedbpath = Path.Combine(PathManager.GetExeDirectoryAbsolute(), "gamedb", "EMU7800.csv");
try
{
var a78 = new Atari7800(nextComm, game, rom.RomData, NTSC_BIOS7800, PAL_BIOS7800, HighScoreBIOS, gamedbpath);
nextEmulator = a78;
}
catch (InvalidDataException ex)
{
MessageBox.Show(ex.Message, "Region specific bios missing", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
var a78 = new Atari7800(nextComm, game, rom.RomData, EmuLoadHelper, gamedbpath);
nextEmulator = a78;
break;
case "C64":
C64 c64 = new C64(nextComm, game, rom.RomData, rom.Extension);
@ -3391,21 +3308,9 @@ namespace BizHawk.Client.EmuHawk
case "GBA":
if (VersionInfo.INTERIM)
{
var gbabiospath = Global.FirmwareManager.Request("GBA", "Bios");
byte[] gbabios;
if (File.Exists(gbabiospath))
{
gbabios = File.ReadAllBytes(gbabiospath);
}
else
{
MessageBox.Show("Unable to find the required GBA BIOS file - \n" + gbabiospath, "Unable to load BIOS", MessageBoxButtons.OK, MessageBoxIcon.Error);
throw new Exception();
}
GBA gba = new GBA(nextComm);
//var gba = new GarboDev.GbaManager(nextComm);
gba.Load(rom.RomData, gbabios);
gba.Load(rom.RomData, EmuLoadHelper);
nextEmulator = gba;
}
break;

View File

@ -56,6 +56,15 @@ namespace BizHawk.Common
}
}
public static string Hash_SHA1(byte[] data)
{
using (var sha1 = System.Security.Cryptography.SHA1.Create())
{
sha1.TransformFinalBlock(data, 0, data.Length);
return BytesToHexString(sha1.Hash);
}
}
public static bool IsPowerOfTwo(int x)
{
if (x == 0) return true;

View File

@ -92,6 +92,7 @@
<Compile Include="Interfaces\IController.cs" />
<Compile Include="Interfaces\ICoreFileProvider.cs" />
<Compile Include="Interfaces\IEmulator.cs" />
<Compile Include="Interfaces\IEmuLoadHelper.cs" />
<Compile Include="Interfaces\ISoundProvider.cs" />
<Compile Include="Interfaces\ISyncSoundProvider.cs" />
<Compile Include="Interfaces\IVideoProvider.cs" />

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BizHawk.Emulation.Common
{
/// <summary>
/// some methods that an emulation core might want to have access to during its load sequence
/// </summary>
public interface IEmuLoadHelper
{
void ShowMessage(string msg);
byte[] GetFirmware(string sysID, string firmwareID, bool required, string msg = null);
}
}

View File

@ -177,10 +177,13 @@ namespace BizHawk.Emulation.Cores.Atari.Atari7800
}
}
public Atari7800(CoreComm comm, GameInfo game, byte[] rom, byte[] ntsc_bios, byte[] pal_bios, byte[] highscoreBIOS, string GameDBfn)
public Atari7800(CoreComm comm, GameInfo game, byte[] rom, IEmuLoadHelper EmuLoadHelper, string GameDBfn)
{
CoreComm = comm;
byte[] highscoreBIOS = EmuLoadHelper.GetFirmware("A78", "Bios_HSC", false, "Some functions may not work without the high score BIOS.");
byte[] pal_bios = EmuLoadHelper.GetFirmware("A78", "Bios_PAL", false, "The game will not run if the correct region BIOS is not available.");
byte[] ntsc_bios = EmuLoadHelper.GetFirmware("A78", "Bios_NTSC", false, "The game will not run if the correct region BIOS is not available.");
if (EMU7800.Win.GameProgramLibrary.EMU7800DB == null)
{
EMU7800.Win.GameProgramLibrary.EMU7800DB = new EMU7800.Win.GameProgramLibrary(new StreamReader(GameDBfn));

View File

@ -43,12 +43,14 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
comm.NominalHeight = 160;
}
public void Load(byte[] rom, byte[] bios)
public void Load(byte[] rom, IEmuLoadHelper EmuLoadHelper)
{
byte[] bios = EmuLoadHelper.GetFirmware("GBA", "Bios", true, "GBA bios file is mandatory.");
if (bios.Length != 16384)
throw new Exception("GBA bios must be exactly 16384 bytes!");
throw new InvalidDataException("GBA bios must be exactly 16384 bytes!");
if (rom.Length > 32 * 1024 * 1024)
throw new Exception("Rom is too big!");
throw new InvalidDataException("Rom file is too big! No GBA game is larger than 32MB");
Init();
LibMeteor.libmeteor_hardreset();
LibMeteor.libmeteor_loadbios(bios, (uint)bios.Length);

View File

@ -15,8 +15,17 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
static readonly bool USE_DATABASE = true;
public RomStatus RomStatus;
public NES(CoreComm comm, GameInfo game, byte[] rom, byte[] fdsbios = null, Dictionary<string, string> boardProperties = null)
public NES(CoreComm comm, GameInfo game, byte[] rom, IEmuLoadHelper EmuLoadHelper, Dictionary<string, string> boardProperties = null)
{
byte[] fdsbios = EmuLoadHelper.GetFirmware("NES", "Bios_FDS", false);
if (fdsbios != null && fdsbios.Length == 40976)
{
EmuLoadHelper.ShowMessage("Your FDS BIOS is a bad dump. BizHawk will attempt to use it, but no guarantees! You should find a new one.");
var tmp = new byte[8192];
Buffer.BlockCopy(fdsbios, 16 + 8192 * 3, tmp, 0, 8192);
fdsbios = tmp;
}
if (boardProperties != null)
{
InitialMapperRegisterValues.Set(boardProperties);

View File

@ -254,8 +254,15 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
LibsnesApi.snes_trace_t tracecb;
LibsnesApi.snes_audio_sample_t soundcb;
public void Load(GameInfo game, byte[] romData, byte[] sgbRomData, bool DeterministicEmulation, byte[] xmlData)
public void Load(GameInfo game, byte[] romData, IEmuLoadHelper EmuLoadHelper, bool DeterministicEmulation, byte[] xmlData)
{
byte[] sgbRomData = null;
if (game["SGB"])
{
sgbRomData = EmuLoadHelper.GetFirmware("SNES", "Rom_SGB", true, "SGB Rom is required for SGB emulation.");
game.FirmwareHash = Util.Hash_SHA1(sgbRomData);
}
ScanlineHookManager = new MyScanlineHookManager(this);
api.CMD_init();

View File

@ -41,8 +41,9 @@ namespace BizHawk.Emulation.Cores.Sega.Saturn
LibYabause.InputCallback InputCallbackH;
public Yabause(CoreComm CoreComm, DiscSystem.Disc CD, byte[] bios, bool GL = false)
public Yabause(CoreComm CoreComm, DiscSystem.Disc CD, IEmuLoadHelper EmuLoadHelper, bool GL)
{
byte[] bios = EmuLoadHelper.GetFirmware("SAT", "J", true, "Saturn BIOS is required.");
CoreComm.RomStatusDetails = string.Format("Disk partial hash:{0}", CD.GetHash());
this.CoreComm = CoreComm;
this.CD = CD;