diff --git a/src/BizHawk.Client.Common/RomLoader.cs b/src/BizHawk.Client.Common/RomLoader.cs index 57c0e69cbb..b4132773b4 100644 --- a/src/BizHawk.Client.Common/RomLoader.cs +++ b/src/BizHawk.Client.Common/RomLoader.cs @@ -121,29 +121,6 @@ namespace BizHawk.Client.Common public List Discs { get; set; } = new List(); } - private T MakeCore(CoreLoadParametersShort clps) - where T : IEmulator - { - // TODO: Lots of stuff - var ctor = typeof(T) - .GetConstructors() - .Select(c => new { c, p = c.GetParameters() }) - .Where(a => a.p.Length == 1) - .Select(a => new { a.c, p = a.p[0] }) - .Where(a => a.p.ParameterType.IsGenericType && a.p.ParameterType.GetGenericTypeDefinition() == typeof(CoreLoadParameters<,>)) - .Single(); - - var clp = (dynamic)Activator.CreateInstance(ctor.p.ParameterType); - clp.Comm = clps.Comm; - clp.Game = clps.Game; - clp.Roms = clps.Roms; - clp.Discs = clps.Discs; - clp.DeterministicEmulationRequested = Deterministic; - clp.Settings = (dynamic)GetCoreSettings(typeof(T), ctor.p.ParameterType.GetGenericArguments()[0]); - clp.SyncSettings = (dynamic)GetCoreSyncSettings(typeof(T), ctor.p.ParameterType.GetGenericArguments()[1]); - return (T)ctor.c.Invoke(new[] { clp }); - } - // For not throwing errors but simply outputting information to the screen public Action MessageCallback { get; set; } @@ -286,20 +263,13 @@ namespace BizHawk.Client.Common private bool LoadDisc(string path, CoreComm nextComm, HawkFile file, string ext, out IEmulator nextEmulator, out GameInfo game) { - //--- load the disc in a context which will let us abort if it's going to take too long - var discMountJob = new DiscMountJob { IN_FromPath = path, IN_SlowLoadAbortThreshold = 8 }; - discMountJob.Run(); - - if (discMountJob.OUT_SlowLoadAborted) + var disc = DiscExtensions.CreateAnyType(path, str => DoLoadErrorCallback(str, "???", LoadErrorType.DiscError)); + if (disc == null) { - DoLoadErrorCallback("This disc would take too long to load. Run it through DiscoHawk first, or find a new rip because this one is probably junk", "", LoadErrorType.DiscError); - nextEmulator = null; game = null; + nextEmulator = null; return false; } - if (discMountJob.OUT_ErrorLevel) throw new InvalidOperationException($"\r\n{discMountJob.OUT_Log}"); - - var disc = discMountJob.OUT_Disc; // TODO - use more sophisticated IDer var discType = new DiscIdentifier(disc).DetectDiscType(); @@ -361,26 +331,6 @@ namespace BizHawk.Client.Common } } - TEmulator MakeCoreFromCds(GameInfo g) - where TEmulator : IEmulator - { - var clps = new CoreLoadParametersShort - { - Comm = nextComm, - Game = g, - Discs = - { - new DiscAsset - { - DiscData = disc, - DiscType = new DiscIdentifier(disc).DetectDiscType(), - DiscName = Path.GetFileNameWithoutExtension(path) - } - }, - }; - return MakeCore(clps); - } - var cip = new CoreInventoryParameters(this) { Comm = nextComm, @@ -564,97 +514,39 @@ namespace BizHawk.Client.Common var xmlGame = XmlGame.Create(file); // if load fails, are we supposed to retry as a bsnes XML???????? game = xmlGame.GI; - List DiscsFromXml(string systemId, DiscType diskType) + var system = game.System; + var cip = new CoreInventoryParameters(this) { - return xmlGame - .AssetFullPaths + Comm = nextComm, + Game = game, + Roms = xmlGame.Assets + .Where(kvp => !Disc.IsValidExtension(kvp.Key)) + .Select(kvp => (IRomAsset)new RomAsset + { + RomData = kvp.Value, + FileData = kvp.Value, // TODO: Hope no one needed anything special here + Extension = Path.GetExtension(kvp.Key), + Game = Database.GetGameInfo(kvp.Value, Path.GetFileName(kvp.Key)) + }) + .ToList(), + Discs = xmlGame.AssetFullPaths .Where(path => Disc.IsValidExtension(Path.GetExtension(path))) .Select(path => new - { - d = diskType.Create(path, str => DoLoadErrorCallback(str, systemId, LoadErrorType.DiscError)), - p = path, - }) + { + d = DiscExtensions.CreateAnyType(path, str => DoLoadErrorCallback(str, system, LoadErrorType.DiscError)), + p = path, + }) .Where(a => a.d != null) .Select(a => (IDiscAsset)new DiscAsset { DiscData = a.d, - DiscType = diskType, + DiscType = new DiscIdentifier(a.d).DetectDiscType(), DiscName = Path.GetFileNameWithoutExtension(a.p) }) - .ToList(); - } - - TEmulator MakeCoreFromXml(GameInfo g, DiscType? type = null, string systemId = null) - where TEmulator : IEmulator - { - var clps = new CoreLoadParametersShort - { - Comm = nextComm, - Game = g, - Roms = xmlGame.Assets - .Where(kvp => !Disc.IsValidExtension(kvp.Key)) - .Select(kvp => (IRomAsset)new RomAsset - { - RomData = kvp.Value, - FileData = kvp.Value, // TODO: Hope no one needed anything special here - Extension = Path.GetExtension(kvp.Key), - Game = Database.GetGameInfo(kvp.Value, Path.GetFileName(kvp.Key)) - }) - .ToList(), - Discs = type.HasValue ? DiscsFromXml(systemId, type.Value) : new List(), - }; - return MakeCore(clps); - } - - switch (game.System) - { - case "GB": - case "DGB": - if (_config.PreferredCores["GB"] == CoreNames.GbHawk) - { - nextEmulator = MakeCoreFromXml(game); - return true; - } - else - { - nextEmulator = MakeCoreFromXml(game); - return true; - } - case "GB3x": - nextEmulator = MakeCoreFromXml(game); - return true; - case "GB4x": - nextEmulator = MakeCoreFromXml(game); - return true; - case "AppleII": - nextEmulator = MakeCoreFromXml(game); - return true; - case "C64": - nextEmulator = MakeCoreFromXml(game); - return true; - case "ZXSpectrum": - nextEmulator = MakeCoreFromXml(game); - return true; - case "AmstradCPC": - nextEmulator = MakeCoreFromXml(game); - return true; - case "PSX": - nextEmulator = MakeCoreFromXml(game, DiscType.SonyPSX, "PSX"); - return true; - case "SAT": - nextEmulator = MakeCoreFromXml(game, DiscType.SegaSaturn, "SAT"); - return true; - case "PCFX": - nextEmulator = MakeCoreFromXml(game, DiscType.PCFX, "PCFX"); - return true; - case "GEN": - nextEmulator = MakeCoreFromXml(game, DiscType.MegaCD, "GEN"); - return true; - case "Game Gear": - nextEmulator = MakeCoreFromXml(game); - return true; - } - return false; + .ToList(), + }; + nextEmulator = MakeCoreFromCoreInventory(cip); + return true; } catch (Exception ex) { diff --git a/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.cs b/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.cs index cf1511c18a..45229b346e 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.cs @@ -21,15 +21,10 @@ namespace BizHawk.Emulation.Cores.Computers.AppleII AppleIIController.BoolButtons.AddRange(ExtraButtons); } + [CoreConstructor("AppleII")] public AppleII(CoreLoadParameters lp) - : this(lp.Comm, lp.Roms.First().RomData, lp.Settings) { _romSet = lp.Roms.Select(r => r.RomData).ToList(); - } - - [CoreConstructor("AppleII")] - public AppleII(CoreComm comm, byte[] rom, Settings settings) - { var ser = new BasicServiceProvider(this); ServiceProvider = ser; @@ -38,13 +33,11 @@ namespace BizHawk.Emulation.Cores.Computers.AppleII Header = "6502: PC, opcode, register (A, X, Y, P, SP, Cy), flags (NVTBDIZC)" }; - _disk1 = rom; - // TODO: Doesn't this add the first rom twice in the case of multirom? - _romSet.Add(rom); + _disk1 = _romSet[0]; - _appleIIRom = comm.CoreFileProvider.GetFirmware( + _appleIIRom = lp.Comm.CoreFileProvider.GetFirmware( SystemId, "AppleIIe", true, "The Apple IIe BIOS firmware is required"); - _diskIIRom = comm.CoreFileProvider.GetFirmware( + _diskIIRom = lp.Comm.CoreFileProvider.GetFirmware( SystemId, "DiskII", true, "The DiskII firmware is required"); _machine = new Components(_appleIIRom, _diskIIRom); @@ -58,7 +51,7 @@ namespace BizHawk.Emulation.Cores.Computers.AppleII SetCallbacks(); SetupMemoryDomains(); - PutSettings(settings ?? new Settings()); + PutSettings(lp.Settings ?? new Settings()); } private static readonly ControllerDefinition AppleIIController; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.cs index d75cdd5b7d..8d711f2f78 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.cs @@ -1,4 +1,5 @@ -using BizHawk.Emulation.Common; +using System; +using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink { @@ -29,9 +30,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink public bool do_frame_fill; - //[CoreConstructor("GB", "GBC")] + [CoreConstructor("DGB")] public GBHawkLink(CoreLoadParameters lp) { + if (lp.Roms.Count != 2) + throw new InvalidOperationException("Wrong number of roms"); + var ser = new BasicServiceProvider(this); ServiceProvider = ser; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.cs index 7234f4faa6..1239a7b493 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.cs @@ -1,4 +1,5 @@ -using BizHawk.Emulation.Common; +using System; +using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink3x { @@ -29,9 +30,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink3x public bool do_frame_fill; - //[CoreConstructor("GB", "GBC")] + [CoreConstructor("GB3x")] public GBHawkLink3x(CoreLoadParameters lp) { + if (lp.Roms.Count != 3) + throw new InvalidOperationException("Wrong number of roms"); + var ser = new BasicServiceProvider(this); ServiceProvider = ser; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.cs index c6736d5b9d..2412e5f5f3 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.cs @@ -1,4 +1,5 @@ -using BizHawk.Emulation.Common; +using System; +using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink4x { @@ -50,9 +51,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink4x public bool do_frame_fill; - //[CoreConstructor("GB", "GBC")] + [CoreConstructor("GB4x")] public GBHawkLink4x(CoreLoadParameters lp) { + if (lp.Roms.Count != 4) + throw new InvalidOperationException("Wrong number of roms"); + var ser = new BasicServiceProvider(this); Link4xSettings = (GBLink4xSettings)lp.Settings ?? new GBLink4xSettings(); diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.cs index bd04723101..ba6a497423 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.cs @@ -1,4 +1,5 @@ -using BizHawk.Emulation.Common; +using System; +using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Nintendo.Gameboy { @@ -11,8 +12,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy public partial class GambatteLink : IEmulator, IVideoProvider, ISoundProvider, IInputPollable, ISaveRam, IStatable, ILinkable, IBoardInfo, IRomInfo, IDebuggable, ISettable, ICodeDataLogger { + [CoreConstructor("DGB")] public GambatteLink(CoreLoadParameters lp) { + if (lp.Roms.Count != 2) + throw new InvalidOperationException("Wrong number of roms"); + ServiceProvider = new BasicServiceProvider(this); GambatteLinkSettings linkSettings = (GambatteLinkSettings)lp.Settings ?? new GambatteLinkSettings(); GambatteLinkSyncSettings linkSyncSettings = (GambatteLinkSyncSettings)lp.SyncSettings ?? new GambatteLinkSyncSettings(); diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.cs index 837da86650..82bb60a7de 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.cs @@ -1,4 +1,5 @@ -using BizHawk.Emulation.Common; +using System; +using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Sega.MasterSystem; namespace BizHawk.Emulation.Cores.Sega.GGHawkLink @@ -25,8 +26,13 @@ namespace BizHawk.Emulation.Cores.Sega.GGHawkLink private bool do_r_next = false; + // TODO: Are there really xml games in the wild with this SystemId? + [CoreConstructor("Game Gear")] public GGHawkLink(CoreLoadParameters lp) { + if (lp.Roms.Count != 2) + throw new InvalidOperationException("Wrong number of roms"); + var ser = new BasicServiceProvider(this); linkSettings = (GGLinkSettings)lp.Settings ?? new GGLinkSettings(); diff --git a/src/BizHawk.Emulation.DiscSystem/DiscExtensions.cs b/src/BizHawk.Emulation.DiscSystem/DiscExtensions.cs index 98aa45c001..492db30baa 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscExtensions.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscExtensions.cs @@ -4,7 +4,16 @@ namespace BizHawk.Emulation.DiscSystem { public static class DiscExtensions { + public static Disc CreateAnyType(string path, Action errorCallback) + { + return CreateImpl(null, path, errorCallback); + } public static Disc Create(this DiscType type, string path, Action errorCallback) + { + return CreateImpl(type, path, errorCallback); + } + + private static Disc CreateImpl(DiscType? type, string path, Action errorCallback) { //--- load the disc in a context which will let us abort if it's going to take too long var discMountJob = new DiscMountJob { IN_FromPath = path, IN_SlowLoadAbortThreshold = 8 }; @@ -24,7 +33,7 @@ namespace BizHawk.Emulation.DiscSystem var discType = new DiscIdentifier(disc).DetectDiscType(); - if (discType != type) + if (type.HasValue && discType != type) { errorCallback($"Not a {type} disc"); return null;