diff --git a/BizHawk.Emulation.Cores/CoreInventory.cs b/BizHawk.Emulation.Cores/CoreInventory.cs index 2c08e760e1..d356269e45 100644 --- a/BizHawk.Emulation.Cores/CoreInventory.cs +++ b/BizHawk.Emulation.Cores/CoreInventory.cs @@ -1,10 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Reflection; using BizHawk.Emulation.Common; -using BizHawk.Emulation.DiscSystem; namespace BizHawk.Emulation.Cores { @@ -13,56 +11,66 @@ namespace BizHawk.Emulation.Cores /// public class CoreInventory { + private readonly Dictionary> _systems = new Dictionary>(); + public class Core { - public readonly string Name; - public readonly Type Type; - public readonly ConstructorInfo CTor; + // expected names and types of the parameters + private static readonly Dictionary ParamTypes = new Dictionary(); - public Core(string Name, Type Type, ConstructorInfo CTor) + // map parameter names to locations in the constructor + private readonly Dictionary _paramMap = new Dictionary(); + + static Core() { - this.Name = Name; - this.Type = Type; - this.CTor = CTor; + var pp = typeof(Core).GetMethod("Create")?.GetParameters(); + if (pp != null) + { + foreach (var p in pp) + { + ParamTypes.Add(p.Name.ToLowerInvariant(), p.ParameterType); + } + } + } + + public Core(string name, Type type, ConstructorInfo ctor) + { + Name = name; + Type = type; + CTor = ctor; var pp = CTor.GetParameters(); for (int i = 0; i < pp.Length ; i++) { var p = pp[i]; - string pname = p.Name.ToLowerInvariant(); - Type expectedtype; - if (!paramtypes.TryGetValue(pname, out expectedtype)) + string pName = p.Name.ToLowerInvariant(); + if (!ParamTypes.TryGetValue(pName, out _)) + { throw new InvalidOperationException($"Unexpected parameter name {p.Name} in constructor for {Type}"); + } - // disabling the typecheck here doesn't really hurt anything, because the Invoke call will still catch any forbidden casts + // disabling the type check here doesn't really hurt anything, because the Invoke call will still catch any forbidden casts // it does allow us to write "MySettingsType settings" instead of "object settings" - // if (expectedtype != p.ParameterType) + // if (expectedType != p.ParameterType) // throw new InvalidOperationException($"Unexpected type mismatch in parameter {p.Name} in constructor for {Type}"); - parammap.Add(pname, i); + _paramMap.Add(pName, i); } } - // map parameter names to locations in the constructor - private readonly Dictionary parammap = new Dictionary(); - // expected names and types of the parameters - private static readonly Dictionary paramtypes = new Dictionary(); + public string Name { get; } + public Type Type { get; } + public ConstructorInfo CTor { get; } - static Core() + private void Bp(object[] parameters, string name, object value) { - var pp = typeof(Core).GetMethod("Create").GetParameters(); - foreach (var p in pp) - paramtypes.Add(p.Name.ToLowerInvariant(), p.ParameterType); - } - - void bp(object[] parameters, string name, object value) - { - int i; - if (parammap.TryGetValue(name, out i)) + if (_paramMap.TryGetValue(name, out var i)) + { parameters[i] = value; + } } /// - /// instatiate an emulator core + /// Instantiate an emulator core /// public IEmulator Create ( @@ -72,34 +80,31 @@ namespace BizHawk.Emulation.Cores byte[] file, bool deterministic, object settings, - object syncsettings + object syncSettings ) { - object[] o = new object[parammap.Count]; - bp(o, "comm", comm); - bp(o, "game", game); - bp(o, "rom", rom); - bp(o, "file", file); - bp(o, "deterministic", deterministic); - bp(o, "settings", settings); - bp(o, "syncsettings", syncsettings); + object[] o = new object[_paramMap.Count]; + Bp(o, "comm", comm); + Bp(o, "game", game); + Bp(o, "rom", rom); + Bp(o, "file", file); + Bp(o, "deterministic", deterministic); + Bp(o, "settings", settings); + Bp(o, "syncsettings", syncSettings); return (IEmulator)CTor.Invoke(o); } } - private readonly Dictionary> systems = new Dictionary>(); - - - private void ProcessConstructor(Type type, string system, CoreAttribute coreattr, ConstructorInfo cons) + private void ProcessConstructor(Type type, string system, CoreAttribute coreAttr, ConstructorInfo cons) { - Core core = new Core(coreattr.CoreName, type, cons); - List ss; - if (!systems.TryGetValue(system, out ss)) + Core core = new Core(coreAttr.CoreName, type, cons); + if (!_systems.TryGetValue(system, out var ss)) { ss = new List(); - systems.Add(system, ss); + _systems.Add(system, ss); } + ss.Add(core); } @@ -110,48 +115,38 @@ namespace BizHawk.Emulation.Cores { get { - List ss = systems[system]; + List ss = _systems[system]; if (ss.Count != 1) + { throw new InvalidOperationException("Ambiguous core selection!"); + } + return ss[0]; } } /// - /// find a core matching a particular game.system with a particular coreattributes.name + /// find a core matching a particular game.system with a particular CoreAttributes.Name /// public Core this[string system, string core] { get { - List ss = systems[system]; + List ss = _systems[system]; foreach (Core c in ss) { if (c.Name == core) + { return c; + } } + throw new InvalidOperationException("No such core!"); } } /// - /// find an exact core type. slow lookup. - /// - public Core FindByType(Type type) - { - foreach (List cc in systems.Values) - { - foreach (Core c in cc) - { - if (c.Type == type) - return c; - } - } - throw new InvalidOperationException("No such core!"); - } - - /// - /// create a core inventory, collecting all IEmulators from some assembilies + /// create a core inventory, collecting all IEmulators from some assemblies /// public CoreInventory(IEnumerable assys) { @@ -161,8 +156,8 @@ namespace BizHawk.Emulation.Cores { if (!typ.IsAbstract && typ.GetInterfaces().Contains(typeof(IEmulator))) { - var coreattr = typ.GetCustomAttributes(typeof(CoreAttribute), false); - if (coreattr.Length != 1) + var coreAttr = typ.GetCustomAttributes(typeof(CoreAttribute), false); + if (coreAttr.Length != 1) throw new InvalidOperationException($"{nameof(IEmulator)} {typ} without {nameof(CoreAttribute)}s!"); var cons = typ.GetConstructors(BindingFlags.Public | BindingFlags.Instance) .Where(c => c.GetCustomAttributes(typeof(CoreConstructorAttribute), false).Length > 0); @@ -170,7 +165,7 @@ namespace BizHawk.Emulation.Cores { foreach (string system in ((CoreConstructorAttribute)con.GetCustomAttributes(typeof(CoreConstructorAttribute), false)[0]).Systems) { - ProcessConstructor(typ, system, (CoreAttribute)coreattr[0], con); + ProcessConstructor(typ, system, (CoreAttribute)coreAttr[0], con); } } } @@ -184,11 +179,13 @@ namespace BizHawk.Emulation.Cores [AttributeUsage(AttributeTargets.Constructor)] public class CoreConstructorAttribute : Attribute { - public IEnumerable Systems { get { return _systems; } } private readonly List _systems = new List(); - public CoreConstructorAttribute(params string[] Systems) + + public CoreConstructorAttribute(params string[] systems) { - _systems.AddRange(Systems); + _systems.AddRange(systems); } + + public IEnumerable Systems => _systems; } } diff --git a/BizHawk.sln.DotSettings b/BizHawk.sln.DotSettings index c32f594f99..47528f4054 100644 --- a/BizHawk.sln.DotSettings +++ b/BizHawk.sln.DotSettings @@ -187,6 +187,8 @@ True True True + True + True True True True