diff --git a/ExternalProjects/AnalyzersCommon/RoslynUtils.cs b/ExternalProjects/AnalyzersCommon/RoslynUtils.cs index cc8b60d094..7d3e3fea55 100644 --- a/ExternalProjects/AnalyzersCommon/RoslynUtils.cs +++ b/ExternalProjects/AnalyzersCommon/RoslynUtils.cs @@ -1,9 +1,9 @@ -namespace BizHawk.Analyzers; - using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +namespace BizHawk.Analyzers; + public static class RoslynUtils { public static SyntaxNode? EnclosingTypeDeclarationSyntax(this CSharpSyntaxNode node) diff --git a/ExternalProjects/BizHawk.SrcGen.SettingsUtil/.gitignore b/ExternalProjects/BizHawk.SrcGen.SettingsUtil/.gitignore new file mode 100644 index 0000000000..4c7473dedd --- /dev/null +++ b/ExternalProjects/BizHawk.SrcGen.SettingsUtil/.gitignore @@ -0,0 +1,2 @@ +/bin +/obj diff --git a/ExternalProjects/BizHawk.SrcGen.SettingsUtil/BizHawk.SrcGen.SettingsUtil.csproj b/ExternalProjects/BizHawk.SrcGen.SettingsUtil/BizHawk.SrcGen.SettingsUtil.csproj new file mode 100644 index 0000000000..46dbd2596a --- /dev/null +++ b/ExternalProjects/BizHawk.SrcGen.SettingsUtil/BizHawk.SrcGen.SettingsUtil.csproj @@ -0,0 +1,6 @@ + + + netstandard2.0 + + + diff --git a/ExternalProjects/BizHawk.SrcGen.SettingsUtil/DefaultSetterGenerator.cs b/ExternalProjects/BizHawk.SrcGen.SettingsUtil/DefaultSetterGenerator.cs new file mode 100644 index 0000000000..77151014e5 --- /dev/null +++ b/ExternalProjects/BizHawk.SrcGen.SettingsUtil/DefaultSetterGenerator.cs @@ -0,0 +1,117 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Text; + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace BizHawk.SrcGen.SettingsUtil; + +[Generator] +public class DefaultSetterGenerator : ISourceGenerator +{ + public class SyntaxReceiver : ISyntaxContextReceiver + { + public readonly List<(ClassDeclarationSyntax, SemanticModel)> ClassDeclarations = new(); + + public void OnVisitSyntaxNode(GeneratorSyntaxContext context) + { + if (context.Node is ClassDeclarationSyntax cds) + { + ClassDeclarations.Add((cds, context.SemanticModel)); + } + } + } + + public void Initialize(GeneratorInitializationContext context) + => context.RegisterForSyntaxNotifications(() => new SyntaxReceiver()); + + private static void CreateDefaultSetter(StringBuilder source, INamespaceOrTypeSymbol symbol) + { + var props = symbol + .GetMembers() + .Where(m => m.Kind == SymbolKind.Property) + .ToImmutableArray(); + + source.Append($@" + public static void SetDefaultValues({symbol} settings) + {{"); + + foreach (var prop in props) + { + var defaultValueAttribute = prop + .GetAttributes() + .FirstOrDefault( + a => a.AttributeClass?.Name == "DefaultValueAttribute"); + + var ctorArgs = defaultValueAttribute?.ConstructorArguments; + if (!ctorArgs.HasValue) + { + continue; + } + + switch (ctorArgs.Value.Length) + { + case 1: + // this single arg is just the value assigned to the default value + var arg = ctorArgs.Value[0]; + // a bit lame, but it'll work + // TODO: do we even want to handle arrays? do we even have any arrays in default values??? + var converionStr = arg.Kind == TypedConstantKind.Array + ? $"new {arg.Type} " // new T[] + : ""; // do we need a cast (i.e. (T)) here? probably not? + source.Append($@" + settings.{prop.Name} = {converionStr}{arg.ToCSharpString()};"); + break; + case 2: + // first arg is the type, the second arg is a string which converts it + source.Append($@" + settings.{prop.Name} = ({ctorArgs.Value[0].Value})System.ComponentModel.TypeDescriptor + .GetConverter({ctorArgs.Value[0].ToCSharpString()}) + .ConvertFromInvariantString({ctorArgs.Value[1].ToCSharpString()});"); + break; + } + } + + source.Append(@" + } +"); + } + + public void Execute(GeneratorExecutionContext context) + { + if (context.SyntaxContextReceiver is not SyntaxReceiver syntaxReceiver) + { + return; + } + + // Generated source code + var source = new StringBuilder(@" +namespace BizHawk.Common +{ + public static partial class SettingsUtil + {"); + + foreach (var (cds, semanticModel) in syntaxReceiver.ClassDeclarations) + { + if (cds.AttributeLists.SelectMany(e => e.Attributes) + .Any(e => e.Name.NormalizeWhitespace().ToFullString() == "CoreSettings")) + { + var symbol = semanticModel.GetDeclaredSymbol(cds); + if (symbol is not null) // probably never happens? + { + CreateDefaultSetter(source, symbol); + } + } + } + + source.Append(@" + } +}"); + + // Add the source code to the compilation + context.AddSource("DefaultSetters.g.cs", source.ToString()); + } +} diff --git a/ExternalProjects/BizHawk.SrcGen.SettingsUtil/build_debug.sh b/ExternalProjects/BizHawk.SrcGen.SettingsUtil/build_debug.sh new file mode 100644 index 0000000000..c2127aded1 --- /dev/null +++ b/ExternalProjects/BizHawk.SrcGen.SettingsUtil/build_debug.sh @@ -0,0 +1 @@ +../.build_debug.sh \ No newline at end of file diff --git a/ExternalProjects/BizHawk.SrcGen.SettingsUtil/build_release.sh b/ExternalProjects/BizHawk.SrcGen.SettingsUtil/build_release.sh new file mode 100644 index 0000000000..801b8e5998 --- /dev/null +++ b/ExternalProjects/BizHawk.SrcGen.SettingsUtil/build_release.sh @@ -0,0 +1 @@ +../.build_release.sh \ No newline at end of file diff --git a/References/BizHawk.SrcGen.SettingsUtil.dll b/References/BizHawk.SrcGen.SettingsUtil.dll new file mode 100644 index 0000000000..94a2b3fafa Binary files /dev/null and b/References/BizHawk.SrcGen.SettingsUtil.dll differ diff --git a/src/BizHawk.Common/BizHawk.Common.csproj b/src/BizHawk.Common/BizHawk.Common.csproj index ded33e3352..57addcbe31 100644 --- a/src/BizHawk.Common/BizHawk.Common.csproj +++ b/src/BizHawk.Common/BizHawk.Common.csproj @@ -10,7 +10,6 @@ - diff --git a/src/BizHawk.Common/SettingsUtil.cs b/src/BizHawk.Common/SettingsUtil.cs deleted file mode 100644 index 25176ac761..0000000000 --- a/src/BizHawk.Common/SettingsUtil.cs +++ /dev/null @@ -1,111 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Reflection.Emit; -using System.Collections.Concurrent; -using System.ComponentModel; - -using BizHawk.Common.CollectionExtensions; - -namespace BizHawk.Common -{ - public static class SettingsUtil - { - private sealed class DefaultValueSetter - { - public readonly Action SetDefaultValues; - - public readonly object[] DefaultValues; - - public DefaultValueSetter(Action setDefaultValues, object[] defaultValues) - { - SetDefaultValues = setDefaultValues; - DefaultValues = defaultValues; - } - } - - - private static readonly IDictionary DefaultValueSetters = new ConcurrentDictionary(); - - /// - /// set all properties (not fields!) of obj with a DefaultValueAttribute to that value - /// - /// the obj to act on - public static void SetDefaultValues(T obj) - where T : notnull - { - var f = DefaultValueSetters.GetValueOrPut(typeof(T), CreateSetter); - f.SetDefaultValues(obj, f.DefaultValues); - } - - private static readonly Dictionary IntTypes = new Dictionary - { - { typeof(byte), OpCodes.Conv_U1 }, - { typeof(sbyte), OpCodes.Conv_I1 }, - { typeof(ushort), OpCodes.Conv_U2 }, - { typeof(short), OpCodes.Conv_I2 }, - { typeof(uint), OpCodes.Conv_U4 }, - { typeof(int), OpCodes.Conv_I4 }, - { typeof(ulong), OpCodes.Conv_U8 }, - { typeof(long), OpCodes.Conv_I8 }, - { typeof(UIntPtr), OpCodes.Conv_U }, - { typeof(IntPtr), OpCodes.Conv_I }, - }; - - private static DefaultValueSetter CreateSetter(Type t) - { - var dyn = new DynamicMethod($"SetDefaultValues_{t.Name}", null, new[] { typeof(object), typeof(object[]) }, false); - var il = dyn.GetILGenerator(); - List DefaultValues = new List(); - - il.Emit(OpCodes.Ldarg_0); // arg0: object to set properties of - il.Emit(OpCodes.Castclass, t); // cast to appropriate type - - foreach (var prop in t.GetProperties()) - { - if (!prop.CanWrite) - continue; - MethodInfo method = prop.GetSetMethod(true); - foreach (object attr in prop.GetCustomAttributes(true)) - { - if (attr is DefaultValueAttribute dvAttr) - { - var value = dvAttr.Value; - Type desiredType = method.GetParameters()[0].ParameterType; - Type sourceType = value.GetType(); - - int idx = DefaultValues.Count; - DefaultValues.Add(value); - - il.Emit(OpCodes.Dup); // object to act on - il.Emit(OpCodes.Ldarg_1); // arg1: array of default values - il.Emit(OpCodes.Ldc_I4, idx); // load index - il.Emit(OpCodes.Ldelem, typeof(object)); // get default value at appropriate index - - // cast to the expected type of the set method - if (desiredType.IsAssignableFrom(sourceType)) - { - il.Emit(OpCodes.Unbox_Any, desiredType); - } - else if (IntTypes.ContainsKey(sourceType) && IntTypes.TryGetValue(desiredType, out var desiredOpcode)) - { - il.Emit(OpCodes.Unbox_Any, sourceType); - il.Emit(desiredOpcode); - } - else - { - throw new InvalidOperationException($"Default value assignment will fail for {t.Name}.{prop.Name}"); - } - il.Emit(OpCodes.Callvirt, method); - } - } - } - il.Emit(OpCodes.Pop); - il.Emit(OpCodes.Ret); - return new DefaultValueSetter( - (Action) dyn.CreateDelegate(typeof(Action)), - DefaultValues.ToArray() - ); - } - } -} diff --git a/src/BizHawk.Emulation.Common/Interfaces/Services/ISettable.cs b/src/BizHawk.Emulation.Common/Interfaces/Services/ISettable.cs index 6e94136209..55b95b34c1 100644 --- a/src/BizHawk.Emulation.Common/Interfaces/Services/ISettable.cs +++ b/src/BizHawk.Emulation.Common/Interfaces/Services/ISettable.cs @@ -16,6 +16,8 @@ namespace BizHawk.Emulation.Common /// The Type of the object that represent regular settings (settings that can be changed during the lifespan of a core instance /// The Type of the object that represents sync settings (settings that can not change during the lifespan of the core and are required for movie sync public interface ISettable : IEmulatorService + where TSettings : class, new() + where TSync : class, new() { // in addition to these methods, it's expected that the constructor or Load() method // will take a Settings and SyncSettings object to set the initial state of the core @@ -54,6 +56,15 @@ namespace BizHawk.Emulation.Common PutSettingsDirtyBits PutSyncSettings(TSync o); } + /// + /// Place this attribute for TSettings and TSync classes which use System.ComponentModel.DefaultValue + /// Classes with this attribute will have a BizHawk.Common.SettingsUtil.SetDefaultValues(T) function generated + /// + [AttributeUsage(AttributeTargets.Class)] + public class CoreSettings : Attribute + { + } + //note: this is a bit of a frail API. If a frontend wants a new flag, cores won't know to yea or nay it //this could be solved by adding a KnownSettingsDirtyBits on the settings interface //or, in a pinch, the same thing could be done with THESE flags, so that the interface doesn't diff --git a/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.ISettable.cs b/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.ISettable.cs index 36b76190ec..b9ad515d5c 100644 --- a/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.ISettable.cs @@ -29,6 +29,7 @@ namespace BizHawk.Emulation.Cores.Arcades.MAME return ret ? PutSettingsDirtyBits.RebootCore : PutSettingsDirtyBits.None; } + [CoreSettings] public class MAMERTCSettings { [DisplayName("Initial Time")] diff --git a/src/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/src/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj index b83e6d60cd..a01440c01a 100644 --- a/src/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj +++ b/src/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj @@ -11,6 +11,7 @@ + diff --git a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/AmstradCPC.ISettable.cs b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/AmstradCPC.ISettable.cs index 0d50bdd4b0..a8ca51e56c 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/AmstradCPC.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/AmstradCPC.ISettable.cs @@ -52,6 +52,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC return ret ? PutSettingsDirtyBits.RebootCore : PutSettingsDirtyBits.None; } + [CoreSettings] public class AmstradCPCSettings { [DisplayName("AY-3-8912 Panning Config")] @@ -85,6 +86,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC } } + [CoreSettings] public class AmstradCPCSyncSettings { [DisplayName("Deterministic Emulation")] diff --git a/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.ISettable.cs b/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.ISettable.cs index ffa5a4a42a..ba5a9519d3 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.ISettable.cs @@ -11,6 +11,7 @@ namespace BizHawk.Emulation.Cores.Computers.AppleII private Settings _settings; private SyncSettings _syncSettings; + [CoreSettings] public class Settings { [DisplayName("Monochrome")] @@ -25,6 +26,7 @@ namespace BizHawk.Emulation.Cores.Computers.AppleII => (Settings)MemberwiseClone(); } + [CoreSettings] public class SyncSettings { [DisplayName("Initial Time")] diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/C64.ISettable.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/C64.ISettable.cs index 4c9342c848..65203ab17e 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/C64.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/C64.ISettable.cs @@ -1,4 +1,6 @@ using System.ComponentModel; + +using BizHawk.Common; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Computers.Commodore64 @@ -31,6 +33,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64 internal C64Settings Settings { get; private set; } internal C64SyncSettings SyncSettings { get; private set; } + [CoreSettings] public class C64Settings { [DisplayName("Border type")] @@ -50,10 +53,11 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64 public C64Settings() { - BizHawk.Common.SettingsUtil.SetDefaultValues(this); + SettingsUtil.SetDefaultValues(this); } } + [CoreSettings] public class C64SyncSettings { [DisplayName("VIC type")] @@ -93,7 +97,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64 public C64SyncSettings() { - BizHawk.Common.SettingsUtil.SetDefaultValues(this); + SettingsUtil.SetDefaultValues(this); } } diff --git a/src/BizHawk.Emulation.Cores/Computers/MSX/MSX.ISettable.cs b/src/BizHawk.Emulation.Cores/Computers/MSX/MSX.ISettable.cs index 3a2983a1ac..e98f1bc583 100644 --- a/src/BizHawk.Emulation.Cores/Computers/MSX/MSX.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Computers/MSX/MSX.ISettable.cs @@ -33,6 +33,7 @@ namespace BizHawk.Emulation.Cores.Computers.MSX internal MSXSettings Settings { get; private set; } internal MSXSyncSettings SyncSettings { get; private set; } + [CoreSettings] public class MSXSettings { // graphics settings @@ -62,6 +63,7 @@ namespace BizHawk.Emulation.Cores.Computers.MSX } } + [CoreSettings] public class MSXSyncSettings { public enum ContrType diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.ISettable.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.ISettable.cs index 9abfb46c29..e3964f319a 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.ISettable.cs @@ -49,6 +49,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum return ret ? PutSettingsDirtyBits.RebootCore : PutSettingsDirtyBits.None; } + [CoreSettings] public class ZXSpectrumSettings { [DisplayName("AY-3-8912 Panning Config")] @@ -97,6 +98,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum } } + [CoreSettings] public class ZXSpectrumSyncSettings { [DisplayName("Deterministic Emulation")] diff --git a/src/BizHawk.Emulation.Cores/Computers/TIC80/TIC80.ISettable.cs b/src/BizHawk.Emulation.Cores/Computers/TIC80/TIC80.ISettable.cs index 2f224e51b7..6f978c12a4 100644 --- a/src/BizHawk.Emulation.Cores/Computers/TIC80/TIC80.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Computers/TIC80/TIC80.ISettable.cs @@ -30,6 +30,7 @@ namespace BizHawk.Emulation.Cores.Computers.TIC80 return ret ? PutSettingsDirtyBits.RebootCore : PutSettingsDirtyBits.None; } + [CoreSettings] public class TIC80Settings { [DisplayName("Crop")] @@ -44,6 +45,7 @@ namespace BizHawk.Emulation.Cores.Computers.TIC80 => (TIC80Settings)MemberwiseClone(); } + [CoreSettings] public class TIC80SyncSettings { [DisplayName("Gamepad 1 Enable")] diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.ISettable.cs index 73d1425071..342545632c 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.ISettable.cs @@ -42,6 +42,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600 internal A2600Settings Settings { get; private set; } internal A2600SyncSettings SyncSettings { get; private set; } + [CoreSettings] public class A2600Settings { [JsonIgnore] @@ -147,6 +148,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600 } } + [CoreSettings] public class A2600SyncSettings { [DefaultValue(Atari2600ControllerTypes.Joystick)] diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.ISettable.cs index 9ae394fe54..7968740280 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.ISettable.cs @@ -6,59 +6,33 @@ using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Atari.A7800Hawk { - public partial class A7800Hawk : IEmulator, ISettable + public partial class A7800Hawk : IEmulator, ISettable { - public A7800Settings GetSettings() - { - return _settings.Clone(); - } + public object GetSettings() + => null; public A7800SyncSettings GetSyncSettings() - { - return _syncSettings.Clone(); - } + => _syncSettings.Clone(); - public PutSettingsDirtyBits PutSettings(A7800Settings o) - { - _settings = o; - return PutSettingsDirtyBits.None; - } + public PutSettingsDirtyBits PutSettings(object o) + => PutSettingsDirtyBits.None; public PutSettingsDirtyBits PutSyncSettings(A7800SyncSettings o) { - bool ret = A7800SyncSettings.NeedsReboot(_syncSettings, o); + var ret = A7800SyncSettings.NeedsReboot(_syncSettings, o); _syncSettings = o; return ret ? PutSettingsDirtyBits.RebootCore : PutSettingsDirtyBits.None; } - private A7800Settings _settings = new A7800Settings(); - public A7800SyncSettings _syncSettings = new A7800SyncSettings(); - - public class A7800Settings - { - public A7800Settings Clone() - { - return (A7800Settings)MemberwiseClone(); - } - - public A7800Settings() - { - SettingsUtil.SetDefaultValues(this); - } - } + public A7800SyncSettings _syncSettings = new(); public class A7800SyncSettings { private string _port1 = A7800HawkControllerDeck.DefaultControllerName; private string _port2 = A7800HawkControllerDeck.DefaultControllerName; - private string _Filter = "None"; [JsonIgnore] - public string Filter - { - get => _Filter; - set => _Filter = value; - } + public string Filter { get; set; } = "None"; [JsonIgnore] public string Port1 @@ -91,19 +65,10 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk } public A7800SyncSettings Clone() - { - return (A7800SyncSettings)MemberwiseClone(); - } - - public A7800SyncSettings() - { - SettingsUtil.SetDefaultValues(this); - } + => (A7800SyncSettings)MemberwiseClone(); public static bool NeedsReboot(A7800SyncSettings x, A7800SyncSettings y) - { - return !DeepEquality.DeepEquals(x, y); - } + => !DeepEquality.DeepEquals(x, y); } } } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.cs index 38eca51957..8657a83690 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.cs @@ -10,7 +10,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk [Core(CoreNames.A7800Hawk, "")] [ServiceNotApplicable(new[] { typeof(IDriveLight), typeof(ISettable<,>) })] public partial class A7800Hawk : IEmulator, ISaveRam, IDebuggable, IInputPollable, - IRegionable, IBoardInfo, ISettable + IRegionable, IBoardInfo, ISettable { internal static class RomChecksums { @@ -76,7 +76,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk } [CoreConstructor(VSystemID.Raw.A78)] - public A7800Hawk(CoreComm comm, byte[] rom, A7800Hawk.A7800Settings settings, A7800Hawk.A7800SyncSettings syncSettings) + public A7800Hawk(CoreComm comm, byte[] rom, A7800SyncSettings syncSettings) { var ser = new BasicServiceProvider(this); @@ -94,7 +94,6 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk _blip.SetRates(1789773, 44100); - _settings = settings ?? new A7800Settings(); _syncSettings = syncSettings ?? new A7800SyncSettings(); _controllerDeck = new A7800HawkControllerDeck(_syncSettings.Port1, _syncSettings.Port2); diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/jaguar/VirtualJaguar.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/jaguar/VirtualJaguar.ISettable.cs index cffcd096ec..ec6323a199 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/jaguar/VirtualJaguar.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/jaguar/VirtualJaguar.ISettable.cs @@ -30,6 +30,7 @@ namespace BizHawk.Emulation.Cores.Atari.Jaguar return ret ? PutSettingsDirtyBits.RebootCore : PutSettingsDirtyBits.None; } + [CoreSettings] public class VirtualJaguarSettings { [DisplayName("Trace M68K (CPU)")] @@ -54,6 +55,7 @@ namespace BizHawk.Emulation.Cores.Atari.Jaguar => (VirtualJaguarSettings)MemberwiseClone(); } + [CoreSettings] public class VirtualJaguarSyncSettings { [DisplayName("Player 1 Connected")] diff --git a/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.ISettable.cs index cbb0ff2eed..d8167229c3 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.ISettable.cs @@ -32,6 +32,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF return ret ? PutSettingsDirtyBits.RebootCore : PutSettingsDirtyBits.None; } + [CoreSettings] public class ChannelFSettings { [DisplayName("Default Background Color")] @@ -50,6 +51,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF } } + [CoreSettings] public class ChannelFSyncSettings { [DisplayName("Deterministic Emulation")] diff --git a/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/VectrexHawk.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/VectrexHawk.ISettable.cs index d99bef72d9..8c41a7c071 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/VectrexHawk.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/VectrexHawk.ISettable.cs @@ -32,6 +32,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Vectrex private object _settings = new object(); public VectrexSyncSettings _syncSettings = new VectrexSyncSettings(); + [CoreSettings] public class VectrexSyncSettings { [JsonIgnore] diff --git a/src/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.ISettable.cs index 51326205d1..93bd7120cb 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.ISettable.cs @@ -32,6 +32,7 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk public O2Settings _settings = new O2Settings(); public O2SyncSettings _syncSettings = new O2SyncSettings(); + [CoreSettings] public class O2Settings { [DisplayName("Display Characters")] @@ -70,6 +71,7 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk } } + [CoreSettings] public class O2SyncSettings { [DisplayName("Use G7400 Enhanemants")] diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Citra.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Citra.ISettable.cs index 633f6229d2..557fa5c667 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Citra.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Citra.ISettable.cs @@ -109,6 +109,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.N3DS return ret ? PutSettingsDirtyBits.RebootCore : PutSettingsDirtyBits.None; } + [CoreSettings] public class CitraSettings { [DisplayName("Resolution Scale Factor")] @@ -240,6 +241,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.N3DS => SettingsUtil.SetDefaultValues(this); } + [CoreSettings] public class CitraSyncSettings { [DisplayName("Use CPU JIT")] diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Ares64/Ares64.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Ares64/Ares64.ISettable.cs index 5b1dba6b9d..d12f60b73e 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Ares64/Ares64.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Ares64/Ares64.ISettable.cs @@ -30,6 +30,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Ares64 return ret ? PutSettingsDirtyBits.RebootCore : PutSettingsDirtyBits.None; } + [CoreSettings] public class Ares64Settings { [DisplayName("Deinterlacer")] @@ -50,6 +51,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Ares64 => (Ares64Settings)MemberwiseClone(); } + [CoreSettings] public class Ares64SyncSettings { [DisplayName("Initial Time")] diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.ISettable.cs index 5074345317..9dd1f027da 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.ISettable.cs @@ -55,6 +55,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA private Settings _settings; + [CoreSettings] public class Settings { [DisplayName("Display BG Layer 0")] @@ -143,6 +144,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA private SyncSettings _syncSettings; + [CoreSettings] public class SyncSettings { [DisplayName("Skip BIOS")] diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.ISettable.cs index 93956de7a6..f272bc7dbf 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.ISettable.cs @@ -37,6 +37,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk public GBSettings _settings = new GBSettings(); public GBSyncSettings _syncSettings = new GBSyncSettings(); + [CoreSettings] public class GBSettings { public enum PaletteType @@ -82,6 +83,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk } } + [CoreSettings] public class GBSyncSettings { public enum ConsoleModeType diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.ISettable.cs index 2841f97cd2..394316e1ee 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.ISettable.cs @@ -30,6 +30,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink private GBLinkSettings linkSettings = new GBLinkSettings(); public GBLinkSyncSettings linkSyncSettings = new GBLinkSyncSettings(); + [CoreSettings] public class GBLinkSettings { [DisplayName("Color Mode")] @@ -71,6 +72,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink public GBLinkSettings() => SettingsUtil.SetDefaultValues(this); } + [CoreSettings] public class GBLinkSyncSettings { [DisplayName("Console Mode L")] diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.ISettable.cs index 08713f3a97..92afbc6032 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.ISettable.cs @@ -30,6 +30,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink3x private GBLink3xSettings Link3xSettings = new GBLink3xSettings(); private GBLink3xSyncSettings Link3xSyncSettings = new GBLink3xSyncSettings(); + [CoreSettings] public class GBLink3xSettings { [DisplayName("Color Mode")] @@ -65,6 +66,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink3x public GBLink3xSettings() => SettingsUtil.SetDefaultValues(this); } + [CoreSettings] public class GBLink3xSyncSettings { [DisplayName("Console Mode L")] diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.ISettable.cs index 344ac2f324..339f9195e1 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.ISettable.cs @@ -30,6 +30,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink4x private GBLink4xSettings Link4xSettings = new GBLink4xSettings(); public GBLink4xSyncSettings Link4xSyncSettings = new GBLink4xSyncSettings(); + [CoreSettings] public class GBLink4xSettings { [DisplayName("Color Mode A")] @@ -71,6 +72,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink4x public GBLink4xSettings() => SettingsUtil.SetDefaultValues(this); } + [CoreSettings] public class GBLink4xSyncSettings { [DisplayName("Console Mode A")] diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ISettable.cs index a4f7f5c4b9..e80f937d92 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ISettable.cs @@ -97,6 +97,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy } } + [CoreSettings] public class GambatteSyncSettings { [DisplayName("Use official Nintendo BootROM")] diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.ISettable.cs index f314c6a8b6..26b3dca570 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.ISettable.cs @@ -122,6 +122,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS Rotate270, } + [CoreSettings] public class NDSSettings { [DisplayName("Screen Layout")] @@ -226,6 +227,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS private static readonly DateTime minDate = new(2000, 1, 1); private static readonly DateTime maxDate = new(2099, 12, 31, 23, 59, 59); + [CoreSettings] public class NDSSyncSettings { public enum ThreeDeeRendererType : int diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.ISettable.cs index 8e617aaaba..8a16ab337b 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.ISettable.cs @@ -50,6 +50,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES /// private QuickNESSyncSettings _syncSettingsNext; + [CoreSettings] public class QuickNESSettings { [DefaultValue(8)] @@ -150,6 +151,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES } } + [CoreSettings] public class QuickNESSyncSettings { [DefaultValue(true)] diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES9X/Snes9x.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES9X/Snes9x.cs index ebaee20a3d..84df8694b5 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES9X/Snes9x.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES9X/Snes9x.cs @@ -149,6 +149,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES9X return ret ? PutSettingsDirtyBits.RebootCore : PutSettingsDirtyBits.None; } + [CoreSettings] public class Settings { [DefaultValue(true)] @@ -234,6 +235,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES9X } } + [CoreSettings] public class SyncSettings { [DefaultValue(LibSnes9x.LeftPortDevice.Joypad)] diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.ISettable.cs index 952701aec0..2ab9a6ff88 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.ISettable.cs @@ -45,6 +45,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Sameboy return ret ? PutSettingsDirtyBits.RebootCore : PutSettingsDirtyBits.None; } + [CoreSettings] public class SameboySettings { public enum GBPaletteType : uint @@ -192,6 +193,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Sameboy => _customPal = (int[])pal.Clone(); } + [CoreSettings] public class SameboySyncSettings { [DisplayName("Use official BIOS")] diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.ISettable.cs index ef73861f28..96311e17ca 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.ISettable.cs @@ -1,4 +1,5 @@ using System.ComponentModel; + using BizHawk.Common; using BizHawk.Emulation.Common; @@ -7,14 +8,10 @@ namespace BizHawk.Emulation.Cores.Sega.GGHawkLink public partial class GGHawkLink : IEmulator, IStatable, ISettable { public GGLinkSettings GetSettings() - { - return linkSettings.Clone(); - } + => linkSettings.Clone(); public GGLinkSyncSettings GetSyncSettings() - { - return linkSyncSettings.Clone(); - } + => linkSyncSettings.Clone(); public PutSettingsDirtyBits PutSettings(GGLinkSettings o) { @@ -24,14 +21,15 @@ namespace BizHawk.Emulation.Cores.Sega.GGHawkLink public PutSettingsDirtyBits PutSyncSettings(GGLinkSyncSettings o) { - bool ret = GGLinkSyncSettings.NeedsReboot(linkSyncSettings, o); + var ret = GGLinkSyncSettings.NeedsReboot(linkSyncSettings, o); linkSyncSettings = o; return ret ? PutSettingsDirtyBits.RebootCore : PutSettingsDirtyBits.None; } - private GGLinkSettings linkSettings = new GGLinkSettings(); - public GGLinkSyncSettings linkSyncSettings = new GGLinkSyncSettings(); + private GGLinkSettings linkSettings = new(); + public GGLinkSyncSettings linkSyncSettings = new(); + [CoreSettings] public class GGLinkSettings { public enum AudioSrc @@ -46,29 +44,29 @@ namespace BizHawk.Emulation.Cores.Sega.GGHawkLink [DefaultValue(AudioSrc.Left)] public AudioSrc AudioSet { get; set; } + public GGLinkSettings() + => SettingsUtil.SetDefaultValues(this); + public GGLinkSettings Clone() - { - return (GGLinkSettings)MemberwiseClone(); - } + => (GGLinkSettings)MemberwiseClone(); } + [CoreSettings] public class GGLinkSyncSettings { - [DisplayName("Use Existing SaveRAM")] [Description("When true, existing SaveRAM will be loaded at boot up")] [DefaultValue(true)] public bool Use_SRAM { get; set; } + public GGLinkSyncSettings() + => SettingsUtil.SetDefaultValues(this); + public GGLinkSyncSettings Clone() - { - return (GGLinkSyncSettings)MemberwiseClone(); - } + => (GGLinkSyncSettings)MemberwiseClone(); public static bool NeedsReboot(GGLinkSyncSettings x, GGLinkSyncSettings y) - { - return !DeepEquality.DeepEquals(x, y); - } + => !DeepEquality.DeepEquals(x, y); } } } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/PicoDrive.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/PicoDrive.cs index d768bd9f01..f6f79c05ad 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/PicoDrive.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/PicoDrive.cs @@ -179,6 +179,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive _core.SetCDReadCallback(_cdcallback); } + [CoreSettings] public class SyncSettings { [DefaultValue(LibPicoDrive.Region.Auto)] diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ISettable.cs index da2c9cded4..a697b48be8 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ISettable.cs @@ -116,6 +116,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx private GPGXSyncSettings _syncSettings; private GPGXSettings _settings; + [CoreSettings] public class GPGXSettings { [DeepEqualsIgnore] @@ -239,6 +240,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx } + [CoreSettings] public class GPGXSyncSettings { [DisplayName("Use Six Button Controllers")] diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.cs b/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.cs index daa47e8d35..d6d681a21e 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.cs @@ -1142,6 +1142,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSX BobOffset } + [CoreSettings] public class Settings { [DisplayName("Determine Lag from GPU Frames")] diff --git a/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.ISettable.cs index a7da8d0797..c0c5e0d76f 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.ISettable.cs @@ -1,9 +1,10 @@ using System; -using BizHawk.Emulation.Common; using System.ComponentModel; -using BizHawk.Common; using System.Drawing; +using BizHawk.Common; +using BizHawk.Emulation.Common; + namespace BizHawk.Emulation.Cores.WonderSwan { partial class WonderSwan : ISettable @@ -11,6 +12,7 @@ namespace BizHawk.Emulation.Cores.WonderSwan private Settings _settings; private SyncSettings _syncSettings; + [CoreSettings] public class Settings { [DisplayName("Background Layer")] @@ -83,6 +85,7 @@ namespace BizHawk.Emulation.Cores.WonderSwan } } + [CoreSettings] public class SyncSettings { [DisplayName("Initial Time")]