From f2a47941058e0582c44014138911120ccce7d410 Mon Sep 17 00:00:00 2001 From: CasualPokePlayer <50538166+CasualPokePlayer@users.noreply.github.com> Date: Wed, 25 Oct 2023 22:50:17 -0700 Subject: [PATCH] Use source generation for SettingsUtil.SetDefaultValues --- .../AnalyzersCommon/RoslynUtils.cs | 4 +- .../BizHawk.SrcGen.SettingsUtil/.gitignore | 2 + .../BizHawk.SrcGen.SettingsUtil.csproj | 6 + .../DefaultSetterGenerator.cs | 117 ++++++++++++++++++ .../build_debug.sh | 1 + .../build_release.sh | 1 + References/BizHawk.SrcGen.SettingsUtil.dll | Bin 0 -> 12800 bytes src/BizHawk.Common/BizHawk.Common.csproj | 1 - src/BizHawk.Common/SettingsUtil.cs | 111 ----------------- .../Interfaces/Services/ISettable.cs | 11 ++ .../Arcades/MAME/MAME.ISettable.cs | 1 + .../BizHawk.Emulation.Cores.csproj | 1 + .../AmstradCPC/AmstradCPC.ISettable.cs | 2 + .../Computers/AppleII/AppleII.ISettable.cs | 2 + .../Computers/Commodore64/C64.ISettable.cs | 8 +- .../Computers/MSX/MSX.ISettable.cs | 2 + .../SinclairSpectrum/ZXSpectrum.ISettable.cs | 2 + .../Computers/TIC80/TIC80.ISettable.cs | 2 + .../Atari/2600/Atari2600.ISettable.cs | 2 + .../Atari/A7800Hawk/A7800Hawk.ISettable.cs | 57 ++------- .../Consoles/Atari/A7800Hawk/A7800Hawk.cs | 5 +- .../Atari/jaguar/VirtualJaguar.ISettable.cs | 2 + .../Fairchild/ChannelF/ChannelF.ISettable.cs | 2 + .../GCE/Vectrex/VectrexHawk.ISettable.cs | 1 + .../Magnavox/Odyssey2/O2Hawk.ISettable.cs | 2 + .../Consoles/Nintendo/3DS/Citra.ISettable.cs | 2 + .../Nintendo/Ares64/Ares64.ISettable.cs | 2 + .../Nintendo/GBA/MGBAHawk.ISettable.cs | 2 + .../Nintendo/GBHawk/GBHawk.ISettable.cs | 2 + .../GBHawkLink/GBHawkLink.ISettable.cs | 2 + .../GBHawkLink3x/GBHawkLink3x.ISettable.cs | 2 + .../GBHawkLink4x/GBHawkLink4x.ISettable.cs | 2 + .../Nintendo/Gameboy/Gambatte.ISettable.cs | 1 + .../Nintendo/NDS/MelonDS.ISettable.cs | 2 + .../Nintendo/QuickNES/QuickNES.ISettable.cs | 2 + .../Consoles/Nintendo/SNES9X/Snes9x.cs | 2 + .../Nintendo/SameBoy/SameBoy.ISettable.cs | 2 + .../Sega/GGHawkLink/GGHawkLink.ISettable.cs | 36 +++--- .../Consoles/Sega/PicoDrive/PicoDrive.cs | 1 + .../Consoles/Sega/gpgx64/GPGX.ISettable.cs | 2 + .../Consoles/Sony/PSX/Octoshock.cs | 1 + .../WonderSwan/WonderSwan.ISettable.cs | 7 +- 42 files changed, 229 insertions(+), 186 deletions(-) create mode 100644 ExternalProjects/BizHawk.SrcGen.SettingsUtil/.gitignore create mode 100644 ExternalProjects/BizHawk.SrcGen.SettingsUtil/BizHawk.SrcGen.SettingsUtil.csproj create mode 100644 ExternalProjects/BizHawk.SrcGen.SettingsUtil/DefaultSetterGenerator.cs create mode 100644 ExternalProjects/BizHawk.SrcGen.SettingsUtil/build_debug.sh create mode 100644 ExternalProjects/BizHawk.SrcGen.SettingsUtil/build_release.sh create mode 100644 References/BizHawk.SrcGen.SettingsUtil.dll delete mode 100644 src/BizHawk.Common/SettingsUtil.cs 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 0000000000000000000000000000000000000000..94a2b3fafaed891a13fb089a42e86478ea2d4c91 GIT binary patch literal 12800 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 - 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")]