Add and use FirmwareID struct
decided not to propogate to cores yet, left TODOs in Emulation.Common.Extensions
This commit is contained in:
parent
35f317a887
commit
10ed0872a4
|
@ -36,33 +36,29 @@ namespace BizHawk.Client.Common
|
|||
public string GetRetroSystemPath(IGameInfo game)
|
||||
=> _pathEntries.RetroSystemAbsolutePath(game);
|
||||
|
||||
private void FirmwareWarn(string sysID, string firmwareID, bool required, string msg = null)
|
||||
private void FirmwareWarn(FirmwareID id, bool required, string msg = null)
|
||||
{
|
||||
if (required)
|
||||
{
|
||||
var fullMsg = $"Couldn't find required firmware \"{sysID}:{firmwareID}\". This is fatal{(msg != null ? $": {msg}" : ".")}";
|
||||
var fullMsg = $"Couldn't find required firmware \"{id.System}:{id.Firmware}\". This is fatal{(msg != null ? $": {msg}" : ".")}";
|
||||
throw new MissingFirmwareException(fullMsg);
|
||||
}
|
||||
|
||||
if (msg != null)
|
||||
{
|
||||
var fullMsg = $"Couldn't find firmware \"{sysID}:{firmwareID}\". Will attempt to continue: {msg}";
|
||||
var fullMsg = $"Couldn't find firmware \"{id.System}:{id.Firmware}\". Will attempt to continue: {msg}";
|
||||
_showWarning(fullMsg);
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] GetFirmwareWithPath(string sysId, string firmwareId, bool required, string msg, out string path)
|
||||
private byte[] GetFirmwareWithPath(FirmwareID id, bool required, string msg, out string path)
|
||||
{
|
||||
var firmwarePath = _firmwareManager.Request(
|
||||
_pathEntries,
|
||||
_firmwareUserSpecifications,
|
||||
sysId,
|
||||
firmwareId);
|
||||
var firmwarePath = _firmwareManager.Request(_pathEntries, _firmwareUserSpecifications, id);
|
||||
|
||||
if (firmwarePath == null || !File.Exists(firmwarePath))
|
||||
{
|
||||
path = null;
|
||||
FirmwareWarn(sysId, firmwareId, required, msg);
|
||||
FirmwareWarn(id, required, msg);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -75,19 +71,19 @@ namespace BizHawk.Client.Common
|
|||
catch (IOException)
|
||||
{
|
||||
path = null;
|
||||
FirmwareWarn(sysId, firmwareId, required, msg);
|
||||
FirmwareWarn(id, required, msg);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <exception cref="MissingFirmwareException">not found and <paramref name="required"/> is true</exception>
|
||||
public byte[] GetFirmware(string sysId, string firmwareId, bool required, string msg = null)
|
||||
=> GetFirmwareWithPath(sysId, firmwareId, required, msg, out _);
|
||||
public byte[] GetFirmware(FirmwareID id, bool required, string msg = null)
|
||||
=> GetFirmwareWithPath(id, required, msg, out _);
|
||||
|
||||
/// <exception cref="MissingFirmwareException">not found and <paramref name="required"/> is true</exception>
|
||||
public byte[] GetFirmwareWithGameInfo(string sysId, string firmwareId, bool required, out GameInfo gi, string msg = null)
|
||||
public byte[] GetFirmwareWithGameInfo(FirmwareID id, bool required, out GameInfo gi, string msg = null)
|
||||
{
|
||||
byte[] ret = GetFirmwareWithPath(sysId, firmwareId, required, msg, out var path);
|
||||
var ret = GetFirmwareWithPath(id, required, msg, out var path);
|
||||
gi = ret != null && path != null
|
||||
? Database.GetGameInfo(ret, path)
|
||||
: null;
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Client.Common
|
||||
{
|
||||
public sealed class FirmwareEventArgs
|
||||
{
|
||||
public string FirmwareId { get; set; }
|
||||
|
||||
public string Hash { get; set; }
|
||||
|
||||
public long Size { get; set; }
|
||||
public FirmwareID ID { get; set; }
|
||||
|
||||
public string SystemId { get; set; }
|
||||
public long Size { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
public class FirmwareManager
|
||||
{
|
||||
private static readonly FirmwareID NDS_FIRMWARE = new("NDS", "firmware");
|
||||
|
||||
public List<FirmwareEventArgs> RecentlyServed { get; } = new List<FirmwareEventArgs>();
|
||||
|
||||
private readonly Dictionary<FirmwareRecord, ResolutionInfo> _resolutionDictionary = new();
|
||||
|
@ -30,12 +32,12 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
|
||||
// Requests the specified firmware. tries really hard to scan and resolve as necessary
|
||||
public string Request(PathEntryCollection pathEntries, IDictionary<string, string> userSpecifications, string sysId, string firmwareId)
|
||||
public string Request(PathEntryCollection pathEntries, IDictionary<string, string> userSpecifications, FirmwareID id)
|
||||
{
|
||||
var resolved = Resolve(
|
||||
pathEntries,
|
||||
userSpecifications,
|
||||
FirmwareDatabase.FirmwareRecords.FirstOrDefault(fr => fr.FirmwareId == firmwareId && fr.SystemId == sysId));
|
||||
FirmwareDatabase.FirmwareRecords.FirstOrDefault(fr => fr.ID == id));
|
||||
if (resolved == null)
|
||||
{
|
||||
return null;
|
||||
|
@ -43,8 +45,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
RecentlyServed.Add(new FirmwareEventArgs
|
||||
{
|
||||
SystemId = sysId,
|
||||
FirmwareId = firmwareId,
|
||||
ID = id,
|
||||
Hash = resolved.Hash,
|
||||
Size = resolved.Size
|
||||
});
|
||||
|
@ -150,11 +151,8 @@ namespace BizHawk.Client.Common
|
|||
_resolutionDictionary.Remove(fr);
|
||||
|
||||
// get all options for this firmware (in order)
|
||||
var fr1 = fr;
|
||||
var options = FirmwareDatabase.FirmwareOptions
|
||||
.Where(fo => fo.SystemId == fr1.SystemId
|
||||
&& fo.FirmwareId == fr1.FirmwareId
|
||||
&& fo.IsAcceptableOrIdeal);
|
||||
var id = fr.ID;
|
||||
var options = FirmwareDatabase.FirmwareOptions.Where(fo => fo.ID == id && fo.IsAcceptableOrIdeal);
|
||||
|
||||
// try each option
|
||||
foreach (var fo in options)
|
||||
|
@ -182,7 +180,7 @@ namespace BizHawk.Client.Common
|
|||
foreach (var fr in FirmwareDatabase.FirmwareRecords)
|
||||
{
|
||||
// do we have a user specification for this firmware record?
|
||||
if (userSpecifications.TryGetValue(fr.ConfigKey, out var userSpec))
|
||||
if (userSpecifications.TryGetValue(fr.ID.ConfigKey, out var userSpec))
|
||||
{
|
||||
// flag it as user specified
|
||||
if (!_resolutionDictionary.TryGetValue(fr, out ResolutionInfo ri))
|
||||
|
@ -205,12 +203,10 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
|
||||
// compute its hash
|
||||
RealFirmwareFile rff;
|
||||
// NDS's firmware file contains user settings; these are over-written by sync settings, so we shouldn't allow them to impact the hash
|
||||
if (fr.SystemId == "NDS" && fr.FirmwareId == "firmware")
|
||||
rff = reader.Read(new FileInfo(Emulation.Cores.Consoles.Nintendo.NDS.MelonDS.CreateModifiedFirmware(userSpec)));
|
||||
else
|
||||
rff = reader.Read(fi);
|
||||
var rff = reader.Read(fr.ID == NDS_FIRMWARE
|
||||
? new FileInfo(Emulation.Cores.Consoles.Nintendo.NDS.MelonDS.CreateModifiedFirmware(userSpec))
|
||||
: fi);
|
||||
ri.Size = fi.Length;
|
||||
ri.Hash = rff.Hash;
|
||||
|
||||
|
@ -220,7 +216,7 @@ namespace BizHawk.Client.Common
|
|||
ri.KnownFirmwareFile = ff;
|
||||
|
||||
// if the known firmware file is for a different firmware, flag it so we can show a warning
|
||||
if (FirmwareDatabase.FirmwareOptions.Any(fo => fo.Hash == rff.Hash && fo.ConfigKey != fr.ConfigKey))
|
||||
if (FirmwareDatabase.FirmwareOptions.Any(fo => fo.Hash == rff.Hash && fo.ID != fr.ID))
|
||||
{
|
||||
ri.KnownMismatching = true;
|
||||
}
|
||||
|
|
|
@ -239,7 +239,7 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
foreach (var firmware in firmwareManager.RecentlyServed)
|
||||
{
|
||||
var key = $"{firmware.SystemId}_Firmware_{firmware.FirmwareId}";
|
||||
var key = $"{firmware.ID.System}_Firmware_{firmware.ID.Firmware}";
|
||||
|
||||
if (!movie.HeaderEntries.ContainsKey(key))
|
||||
{
|
||||
|
|
|
@ -3854,7 +3854,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
Console.WriteLine("Active Firmwares:");
|
||||
foreach (var f in FirmwareManager.RecentlyServed)
|
||||
{
|
||||
Console.WriteLine(" {0} : {1}", f.FirmwareId, f.Hash);
|
||||
Console.WriteLine($" {f.ID} : {f.Hash}");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -177,8 +177,8 @@ namespace BizHawk.Client.EmuHawk
|
|||
ImageIndex = IdUnsure,
|
||||
ToolTipText = null
|
||||
};
|
||||
lvi.SubItems.Add(fr.SystemId);
|
||||
lvi.SubItems.Add(fr.FirmwareId);
|
||||
lvi.SubItems.Add(fr.ID.System);
|
||||
lvi.SubItems.Add(fr.ID.Firmware);
|
||||
lvi.SubItems.Add(fr.Descr);
|
||||
lvi.SubItems.Add(""); // resolved with
|
||||
lvi.SubItems.Add(""); // location
|
||||
|
@ -189,15 +189,15 @@ namespace BizHawk.Client.EmuHawk
|
|||
lvFirmwares.Items.Add(lvi);
|
||||
|
||||
// build the groups in the ListView as we go:
|
||||
if (!groups.ContainsKey(fr.SystemId))
|
||||
if (!groups.ContainsKey(fr.ID.System))
|
||||
{
|
||||
if (!SystemGroupNames.TryGetValue(fr.SystemId, out var name))
|
||||
if (!SystemGroupNames.TryGetValue(fr.ID.System, out var name))
|
||||
name = "FIX ME (FirmwaresConfig.cs)";
|
||||
lvFirmwares.Groups.Add(fr.SystemId, name);
|
||||
lvFirmwares.Groups.Add(fr.ID.System, name);
|
||||
var lvg = lvFirmwares.Groups[lvFirmwares.Groups.Count - 1];
|
||||
groups[fr.SystemId] = lvg;
|
||||
groups[fr.ID.System] = lvg;
|
||||
}
|
||||
lvi.Group = groups[fr.SystemId];
|
||||
lvi.Group = groups[fr.ID.System];
|
||||
}
|
||||
|
||||
// now that we have some items in the ListView, we can size some columns to sensible widths
|
||||
|
@ -496,7 +496,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
}
|
||||
}
|
||||
|
||||
_firmwareUserSpecifications[fr.ConfigKey] = filePath;
|
||||
_firmwareUserSpecifications[fr.ID.ConfigKey] = filePath;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -515,7 +515,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
foreach (ListViewItem lvi in lvFirmwares.SelectedItems)
|
||||
{
|
||||
var fr = (FirmwareRecord) lvi.Tag;
|
||||
_firmwareUserSpecifications.Remove(fr.ConfigKey);
|
||||
_firmwareUserSpecifications.Remove(fr.ID.ConfigKey);
|
||||
}
|
||||
|
||||
DoScan();
|
||||
|
@ -527,16 +527,13 @@ namespace BizHawk.Client.EmuHawk
|
|||
var fr = (FirmwareRecord) lvi.Tag;
|
||||
|
||||
// get all options for this firmware (in order)
|
||||
var options =
|
||||
from fo in FirmwareDatabase.FirmwareOptions
|
||||
where fo.SystemId == fr.SystemId && fo.FirmwareId == fr.FirmwareId
|
||||
select fo;
|
||||
var options = FirmwareDatabase.FirmwareOptions.Where(fo => fo.ID == fr.ID);
|
||||
|
||||
var fciDialog = new FirmwaresConfigInfo
|
||||
{
|
||||
lblFirmware =
|
||||
{
|
||||
Text = $"{fr.SystemId} : {fr.FirmwareId} ({fr.Descr})"
|
||||
Text = $"{fr.ID.System} : {fr.ID.Firmware} ({fr.Descr})"
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -41,8 +41,7 @@ namespace BizHawk.Emulation.Common
|
|||
void Option(string systemId, string id, FirmwareFile ff, FirmwareOptionStatus status = FirmwareOptionStatus.Acceptable)
|
||||
=> options.Add(new FirmwareOption
|
||||
{
|
||||
SystemId = systemId,
|
||||
FirmwareId = id,
|
||||
ID = new(systemId, id),
|
||||
Hash = ff.Hash,
|
||||
Status = ff.Bad ? FirmwareOptionStatus.Bad : status,
|
||||
Size = ff.Size
|
||||
|
@ -51,8 +50,7 @@ namespace BizHawk.Emulation.Common
|
|||
void Firmware(string systemId, string id, string desc)
|
||||
=> records.Add(new FirmwareRecord
|
||||
{
|
||||
SystemId = systemId,
|
||||
FirmwareId = id,
|
||||
ID = new(systemId, id),
|
||||
Descr = desc
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
#nullable enable
|
||||
|
||||
namespace BizHawk.Emulation.Common
|
||||
{
|
||||
public readonly struct FirmwareID
|
||||
{
|
||||
public static bool operator ==(FirmwareID a, FirmwareID b) => a.Firmware == b.Firmware && a.System == b.System;
|
||||
|
||||
public static bool operator !=(FirmwareID a, FirmwareID b) => a.Firmware != b.Firmware || a.System != b.System;
|
||||
|
||||
public string ConfigKey => $"{System}+{Firmware}";
|
||||
|
||||
public readonly string Firmware;
|
||||
|
||||
public readonly string System;
|
||||
|
||||
public FirmwareID(string system, string firmware)
|
||||
{
|
||||
System = system;
|
||||
Firmware = firmware;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj) => obj is FirmwareID other
|
||||
&& other.Firmware == Firmware && other.System == System;
|
||||
|
||||
public override int GetHashCode() => (System, Firmware).GetHashCode();
|
||||
|
||||
public override string ToString() => ConfigKey;
|
||||
}
|
||||
}
|
|
@ -2,18 +2,14 @@ namespace BizHawk.Emulation.Common
|
|||
{
|
||||
public sealed class FirmwareOption
|
||||
{
|
||||
public string ConfigKey => $"{SystemId}+{FirmwareId}";
|
||||
|
||||
public string FirmwareId { get; set; }
|
||||
|
||||
public string Hash { get; set; }
|
||||
|
||||
public FirmwareID ID { get; set; }
|
||||
|
||||
public bool IsAcceptableOrIdeal => Status == FirmwareOptionStatus.Ideal || Status == FirmwareOptionStatus.Acceptable;
|
||||
|
||||
public long Size { get; set; }
|
||||
|
||||
public FirmwareOptionStatus Status { get; set; }
|
||||
|
||||
public string SystemId { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,12 +2,8 @@ namespace BizHawk.Emulation.Common
|
|||
{
|
||||
public sealed class FirmwareRecord
|
||||
{
|
||||
public string ConfigKey => $"{SystemId}+{FirmwareId}";
|
||||
|
||||
public string Descr { get; set; }
|
||||
|
||||
public string FirmwareId { get; set; }
|
||||
|
||||
public string SystemId { get; set; }
|
||||
public FirmwareID ID { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -446,5 +446,18 @@ namespace BizHawk.Emulation.Common
|
|||
.AddAxis(string.Format(nameFormat, "Z"), rangeAll, neutralAll);
|
||||
|
||||
public static AxisSpec With(this in AxisSpec spec, Range<int> range, int neutral) => new AxisSpec(range, neutral, spec.IsReversed, spec.Constraint);
|
||||
|
||||
/// <summary>Get a firmware as a byte array</summary>
|
||||
/// <param name="sysId">the core systemID</param>
|
||||
/// <param name="firmwareId">the firmware id</param>
|
||||
/// <param name="required">if true, result is guaranteed to be valid; else null is possible if not found</param>
|
||||
/// <param name="msg">message to show if fail to get</param>
|
||||
/// <remarks>TODO inline (only change is wrapping strings in <see cref="FirmwareID"/> ctor, these IDs should probably be consts in each core's class)</remarks>
|
||||
public static byte[] GetFirmware(this ICoreFileProvider cfp, string sysId, string firmwareId, bool required, string msg = null)
|
||||
=> cfp.GetFirmware(new(system: sysId, firmware: firmwareId), required: required, msg: msg);
|
||||
|
||||
/// <remarks>TODO inline (only change is wrapping strings in <see cref="FirmwareID"/> ctor, these IDs should probably be consts in each core's class)</remarks>
|
||||
public static byte[] GetFirmwareWithGameInfo(this ICoreFileProvider cfp, string sysId, string firmwareId, bool required, out GameInfo gi, string msg = null)
|
||||
=> cfp.GetFirmwareWithGameInfo(new(system: sysId, firmware: firmwareId), required: required, out gi, msg: msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,12 +23,11 @@
|
|||
/// <summary>
|
||||
/// Get a firmware as a byte array
|
||||
/// </summary>
|
||||
/// <param name="sysId">the core systemID</param>
|
||||
/// <param name="firmwareId">the firmware id</param>
|
||||
/// <param name="id">the firmware id</param>
|
||||
/// <param name="required">if true, result is guaranteed to be valid; else null is possible if not found</param>
|
||||
/// <param name="msg">message to show if fail to get</param>
|
||||
byte[] GetFirmware(string sysId, string firmwareId, bool required, string msg = null);
|
||||
byte[] GetFirmware(FirmwareID id, bool required, string msg = null);
|
||||
|
||||
byte[] GetFirmwareWithGameInfo(string sysId, string firmwareId, bool required, out GameInfo gi, string msg = null);
|
||||
byte[] GetFirmwareWithGameInfo(FirmwareID id, bool required, out GameInfo gi, string msg = null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace BizHawk.Tests.Emulation.Common
|
|||
[TestMethod]
|
||||
public void CheckFilesInOptions()
|
||||
{
|
||||
foreach (var fo in FirmwareDatabase.FirmwareOptions) Assert.IsTrue(FirmwareDatabase.FirmwareFilesByHash.ContainsKey(fo.Hash), $"option {fo.ConfigKey} references unknown file {fo.Hash}");
|
||||
foreach (var fo in FirmwareDatabase.FirmwareOptions) Assert.IsTrue(FirmwareDatabase.FirmwareFilesByHash.ContainsKey(fo.Hash), $"option {fo.ID} references unknown file {fo.Hash}");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
|
Loading…
Reference in New Issue