Allow `ControllerDefinition`s to be made immutable

This commit is contained in:
YoshiRulz 2021-12-05 04:16:53 +10:00 committed by James Groom
parent 15a03a26e8
commit 0719d6f9df
58 changed files with 163 additions and 57 deletions

View File

@ -16,7 +16,8 @@ namespace BizHawk.Client.Common
BoolButtons = { "Up", "Down", "Left", "Right", "Start", "Select", "B", "A", "Y", "X", "L", "R", "LidOpen", "LidClose", "Touch", "Power" }, BoolButtons = { "Up", "Down", "Left", "Right", "Start", "Select", "B", "A", "Y", "X", "L", "R", "LidOpen", "LidClose", "Touch", "Power" },
}.AddXYPair("Touch {0}", AxisPairOrientation.RightAndUp, 0.RangeTo(255), 128, 0.RangeTo(191), 96) //TODO verify direction against hardware }.AddXYPair("Touch {0}", AxisPairOrientation.RightAndUp, 0.RangeTo(255), 128, 0.RangeTo(191), 96) //TODO verify direction against hardware
.AddAxis("Mic Input", 0.RangeTo(2047), 0) .AddAxis("Mic Input", 0.RangeTo(2047), 0)
.AddAxis("GBA Light Sensor", 0.RangeTo(10), 0); .AddAxis("GBA Light Sensor", 0.RangeTo(10), 0)
.MakeImmutable();
protected override void RunImport() protected override void RunImport()
{ {

View File

@ -269,6 +269,7 @@ namespace BizHawk.Client.Common
//TODO FDS //TODO FDS
def.BoolButtons.Add("Reset"); def.BoolButtons.Add("Reset");
def.BoolButtons.Add("Power"); def.BoolButtons.Add("Power");
def.MakeImmutable();
return deck; return deck;
} }
} }

View File

@ -299,7 +299,7 @@ namespace BizHawk.Client.Common.movie.import
=> new(new ControllerDefinition("Gameboy Controller") => new(new ControllerDefinition("Gameboy Controller")
{ {
BoolButtons = { "Up", "Down", "Left", "Right", "Start", "Select", "B", "A", "Power" } BoolButtons = { "Up", "Down", "Left", "Right", "Start", "Select", "B", "A", "Power" }
}); }.MakeImmutable());
private static SimpleController GbaController() private static SimpleController GbaController()
=> new(MGBAHawk.GBAController); => new(MGBAHawk.GBAController);

View File

@ -106,7 +106,7 @@ namespace BizHawk.Client.Common.movie.import
{ {
"Reset", "Power", "Previous Disk", "Next Disk", "P1 Left", "P1 Right", "P1 Up", "P1 Down", "P1 Start", "P1 A", "P1 B", "P1 C", "P1 X", "P1 Y", "P1 Z", "P1 L", "P1 R" "Reset", "Power", "Previous Disk", "Next Disk", "P1 Left", "P1 Right", "P1 Up", "P1 Down", "P1 Start", "P1 A", "P1 B", "P1 C", "P1 X", "P1 Y", "P1 Z", "P1 L", "P1 R"
} }
}); }.MakeImmutable());
// Split up the sections of the frame. // Split up the sections of the frame.
var sections = line.Split(new[] { "|" }, StringSplitOptions.RemoveEmptyEntries); var sections = line.Split(new[] { "|" }, StringSplitOptions.RemoveEmptyEntries);

View File

@ -2104,7 +2104,7 @@ namespace BizHawk.Client.EmuHawk
Controller controls = new(new ControllerDefinition("Emulator Frontend Controls") Controller controls = new(new ControllerDefinition("Emulator Frontend Controls")
{ {
BoolButtons = Config.HotkeyBindings.Select(static x => x.DisplayName).ToList(), BoolButtons = Config.HotkeyBindings.Select(static x => x.DisplayName).ToList(),
}); }.MakeImmutable());
foreach (var b in Config.HotkeyBindings) foreach (var b in Config.HotkeyBindings)
{ {

View File

@ -101,8 +101,8 @@ namespace BizHawk.Client.EmuHawk
private void LoadToPanel<TBindValue>( private void LoadToPanel<TBindValue>(
Control dest, Control dest,
string controllerName, string controllerName,
IReadOnlyCollection<string> controllerButtons, IList<string> controllerButtons,
Dictionary<string,string> categoryLabels, IDictionary<string, string> categoryLabels,
IDictionary<string, Dictionary<string, TBindValue>> settingsBlock, IDictionary<string, Dictionary<string, TBindValue>> settingsBlock,
TBindValue defaultValue, TBindValue defaultValue,
PanelCreator<TBindValue> createPanel PanelCreator<TBindValue> createPanel

View File

@ -85,7 +85,7 @@ namespace BizHawk.Client.EmuHawk
} }
} }
_controller = _movieSession.GenerateMovieController(d); _controller = _movieSession.GenerateMovieController(d.MakeImmutable());
} }
public string Name { get; set; } public string Name { get; set; }
@ -118,7 +118,7 @@ namespace BizHawk.Client.EmuHawk
} }
} }
var newController = _movieSession.GenerateMovieController(d); var newController = _movieSession.GenerateMovieController(d.MakeImmutable());
var logGenerator = _movieSession.Movie.LogGeneratorInstance(newController); var logGenerator = _movieSession.Movie.LogGeneratorInstance(newController);
logGenerator.GenerateLogEntry(); // Reference and create all buttons. logGenerator.GenerateLogEntry(); // Reference and create all buttons.

View File

@ -1,13 +1,17 @@
using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
namespace BizHawk.Emulation.Common namespace BizHawk.Emulation.Common
{ {
public sealed class AxisDict : IReadOnlyDictionary<string, AxisSpec> public sealed class AxisDict : IReadOnlyDictionary<string, AxisSpec>
{ {
private readonly IList<string> _keys = new List<string>(); private IList<string> _keys = new List<string>();
private readonly IDictionary<string, AxisSpec> _specs = new Dictionary<string, AxisSpec>(); private bool _mutable = true;
private IDictionary<string, AxisSpec> _specs = new Dictionary<string, AxisSpec>();
public int Count => _keys.Count; public int Count => _keys.Count;
@ -22,11 +26,16 @@ namespace BizHawk.Emulation.Common
public AxisSpec this[string index] public AxisSpec this[string index]
{ {
get => _specs[index]; get => _specs[index];
set => _specs[index] = value; set
{
AssertMutable();
_specs[index] = value;
}
} }
public void Add(string key, AxisSpec value) public void Add(string key, AxisSpec value)
{ {
AssertMutable();
_keys.Add(key); _keys.Add(key);
_specs.Add(key, value); _specs.Add(key, value);
if (value.Constraint != null) HasContraints = true; if (value.Constraint != null) HasContraints = true;
@ -34,8 +43,15 @@ namespace BizHawk.Emulation.Common
public void Add(KeyValuePair<string, AxisSpec> item) => Add(item.Key, item.Value); public void Add(KeyValuePair<string, AxisSpec> item) => Add(item.Key, item.Value);
private void AssertMutable()
{
const string ERR_MSG = "this " + nameof(AxisDict) + " has been built and sealed and may not be mutated";
if (!_mutable) throw new InvalidOperationException(ERR_MSG);
}
public void Clear() public void Clear()
{ {
AssertMutable();
_keys.Clear(); _keys.Clear();
_specs.Clear(); _specs.Clear();
HasContraints = false; HasContraints = false;
@ -49,6 +65,13 @@ namespace BizHawk.Emulation.Common
public int IndexOf(string key) => _keys.IndexOf(key); public int IndexOf(string key) => _keys.IndexOf(key);
public void MakeImmutable()
{
_mutable = false;
_keys = _keys.ToImmutableList();
_specs = _specs.ToImmutableDictionary();
}
public AxisSpec SpecAtIndex(int index) => this[_keys[index]]; public AxisSpec SpecAtIndex(int index) => this[_keys[index]];
public bool TryGetValue(string key, out AxisSpec value) => _specs.TryGetValue(key, out value); public bool TryGetValue(string key, out AxisSpec value) => _specs.TryGetValue(key, out value);

View File

@ -1,10 +1,13 @@
#nullable disable #nullable disable
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using BizHawk.Common; using BizHawk.Common;
using BizHawk.Common.CollectionExtensions;
namespace BizHawk.Emulation.Common namespace BizHawk.Emulation.Common
{ {
@ -14,6 +17,10 @@ namespace BizHawk.Emulation.Common
/// <seealso cref="IEmulator" /> /// <seealso cref="IEmulator" />
public class ControllerDefinition public class ControllerDefinition
{ {
private IList<string> _buttons = new List<string>();
private bool _mutable = true;
public readonly string Name; public readonly string Name;
public ControllerDefinition(string name) public ControllerDefinition(string name)
@ -26,22 +33,31 @@ namespace BizHawk.Emulation.Common
foreach (var kvp in copyFrom.Axes) Axes.Add(kvp); foreach (var kvp in copyFrom.Axes) Axes.Add(kvp);
HapticsChannels.AddRange(copyFrom.HapticsChannels); HapticsChannels.AddRange(copyFrom.HapticsChannels);
CategoryLabels = copyFrom.CategoryLabels; CategoryLabels = copyFrom.CategoryLabels;
MakeImmutable();
} }
/// <summary> /// <summary>
/// Gets or sets a list of all button types that have a boolean (on/off) value /// Gets or sets a list of all button types that have a boolean (on/off) value
/// </summary> /// </summary>
public List<string> BoolButtons { get; set; } = new List<string>(); public IList<string> BoolButtons
{
get => _buttons;
set
{
AssertMutable();
_buttons = value;
}
}
public readonly AxisDict Axes = new AxisDict(); public readonly AxisDict Axes = new AxisDict();
/// <summary>Contains names of virtual haptic feedback channels, e.g. <c>{ "P1 Mono" }</c>, <c>{ "P2 Left", "P2 Right" }</c>.</summary> /// <summary>Contains names of virtual haptic feedback channels, e.g. <c>{ "P1 Mono" }</c>, <c>{ "P2 Left", "P2 Right" }</c>.</summary>
public List<string> HapticsChannels { get; } = new(); public IList<string> HapticsChannels { get; private set; } = new List<string>();
/// <summary> /// <summary>
/// Gets the category labels. These labels provide a means of categorizing controls in various controller display and config screens /// Gets the category labels. These labels provide a means of categorizing controls in various controller display and config screens
/// </summary> /// </summary>
public Dictionary<string, string> CategoryLabels { get; } = new Dictionary<string, string>(); public IDictionary<string, string> CategoryLabels { get; private set; } = new Dictionary<string, string>();
public void ApplyAxisConstraints(string constraintClass, IDictionary<string, int> axes) public void ApplyAxisConstraints(string constraintClass, IDictionary<string, int> axes)
{ {
@ -88,6 +104,23 @@ namespace BizHawk.Emulation.Common
} }
} }
private void AssertMutable()
{
const string ERR_MSG = "this " + nameof(ControllerDefinition) + " has been built and sealed, and may not be mutated";
if (!_mutable) throw new InvalidOperationException(ERR_MSG);
}
/// <summary>permanently disables the ability to mutate this instance; returns this reference</summary>
public ControllerDefinition MakeImmutable()
{
BoolButtons = BoolButtons.ToImmutableList();
Axes.MakeImmutable();
HapticsChannels = HapticsChannels.ToImmutableList();
CategoryLabels = CategoryLabels.ToImmutableDictionary();
_mutable = false;
return this;
}
public int PlayerNumber(string buttonName) public int PlayerNumber(string buttonName)
{ {
var match = PlayerRegex.Match(buttonName); var match = PlayerRegex.Match(buttonName);

View File

@ -12,7 +12,7 @@ namespace BizHawk.Emulation.Common
/// <seealso cref="IController" /> /// <seealso cref="IController" />
public class NullController : IController public class NullController : IController
{ {
public ControllerDefinition Definition { get; } = new ControllerDefinition("Null Controller"); public ControllerDefinition Definition { get; } = new ControllerDefinition("Null Controller").MakeImmutable();
public bool IsPressed(string button) => false; public bool IsPressed(string button) => false;

View File

@ -7,6 +7,7 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="System.Collections.Immutable" Version="6.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<ProjectReference Include="$(ProjectDir)../BizHawk.BizInvoke/BizHawk.BizInvoke.csproj" /> <ProjectReference Include="$(ProjectDir)../BizHawk.BizInvoke/BizHawk.BizInvoke.csproj" />
<ProjectReference Include="$(ProjectDir)../BizHawk.Common/BizHawk.Common.csproj" /> <ProjectReference Include="$(ProjectDir)../BizHawk.Common/BizHawk.Common.csproj" />

View File

@ -23,6 +23,7 @@ namespace BizHawk.Emulation.Cores.Arcades.MAME
{ {
string inputFields = MameGetString(MAMELuaCommand.GetInputFields); string inputFields = MameGetString(MAMELuaCommand.GetInputFields);
string[] portFields = inputFields.Split(';'); string[] portFields = inputFields.Split(';');
MAMEController = new("MAME Controller");
MAMEController.BoolButtons.Clear(); MAMEController.BoolButtons.Clear();
_fieldsPorts.Clear(); _fieldsPorts.Clear();
@ -38,6 +39,8 @@ namespace BizHawk.Emulation.Cores.Arcades.MAME
MAMEController.BoolButtons.Add(field); MAMEController.BoolButtons.Add(field);
} }
} }
MAMEController.MakeImmutable();
} }
private void SendInput() private void SendInput()

View File

@ -90,7 +90,7 @@ namespace BizHawk.Emulation.Cores.Calculators
"STO", "LN", "LOG", "SQUARED", "NEG1", "MATH", "ALPHA", "STO", "LN", "LOG", "SQUARED", "NEG1", "MATH", "ALPHA",
"GRAPH", "TRACE", "ZOOM", "WINDOW", "Y", "2ND", "MODE", "DEL", "GRAPH", "TRACE", "ZOOM", "WINDOW", "Y", "2ND", "MODE", "DEL",
}, },
}; }.MakeImmutable();
private byte ReadMemory(ushort addr) private byte ReadMemory(ushort addr)
{ {

View File

@ -111,7 +111,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
definition.CategoryLabels[s] = "Amstrad Disk Drive"; definition.CategoryLabels[s] = "Amstrad Disk Drive";
} }
return definition; return definition.MakeImmutable();
} }
} }
} }

View File

@ -1,6 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using BizHawk.Common.CollectionExtensions;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
using Jellyfish.Virtu; using Jellyfish.Virtu;
@ -15,6 +16,7 @@ namespace BizHawk.Emulation.Cores.Computers.AppleII
AppleIIController = new("Apple IIe Keyboard"); AppleIIController = new("Apple IIe Keyboard");
AppleIIController.BoolButtons.AddRange(RealButtons); AppleIIController.BoolButtons.AddRange(RealButtons);
AppleIIController.BoolButtons.AddRange(ExtraButtons); AppleIIController.BoolButtons.AddRange(ExtraButtons);
AppleIIController.MakeImmutable();
} }
[CoreConstructor(VSystemID.Raw.AppleII)] [CoreConstructor(VSystemID.Raw.AppleII)]

View File

@ -150,7 +150,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
"Previous Disk", "Next Disk", "Previous Disk", "Next Disk",
"Power", "Reset" "Power", "Reset"
} }
}; }.MakeImmutable();
private Motherboard _board; private Motherboard _board;

View File

@ -22,7 +22,7 @@ namespace BizHawk.Emulation.Cores.Computers.MSX
"RET", "SEL", "BACK", "STOP", "TAB", "ESC", "F5", "F4", "RET", "SEL", "BACK", "STOP", "TAB", "ESC", "F5", "F4",
"RIGHT", "DOWN", "UP", "LEFT", "DEL", "INS", "HOME", "SPACE" "RIGHT", "DOWN", "UP", "LEFT", "DEL", "INS", "HOME", "SPACE"
} }
}; }.MakeImmutable();
public static readonly ControllerDefinition MSXControllerJS = new ControllerDefinition("MSX Controller Joystick") public static readonly ControllerDefinition MSXControllerJS = new ControllerDefinition("MSX Controller Joystick")
{ {
@ -32,6 +32,6 @@ namespace BizHawk.Emulation.Cores.Computers.MSX
"P1 Up", "P1 Down", "P1 Left", "P1 Right", "P1 B1", "P1 B2", "P1 Up", "P1 Down", "P1 Left", "P1 Right", "P1 B1", "P1 B2",
"P2 Up", "P2 Down", "P2 Left", "P2 Right", "P2 B1", "P2 B2" "P2 Up", "P2 Down", "P2 Left", "P2 Right", "P2 B1", "P2 B2"
} }
}; }.MakeImmutable();
} }
} }

View File

@ -120,7 +120,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
definition.CategoryLabels[s] = "+3 Disk Drive"; definition.CategoryLabels[s] = "+3 Disk Drive";
} }
return definition; return definition.MakeImmutable();
} }
} }
} }

View File

@ -28,6 +28,8 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
foreach (var kvp in Port1.Definition.Axes) Definition.Axes.Add(kvp); foreach (var kvp in Port1.Definition.Axes) Definition.Axes.Add(kvp);
foreach (var kvp in Port2.Definition.Axes) Definition.Axes.Add(kvp); foreach (var kvp in Port2.Definition.Axes) Definition.Axes.Add(kvp);
Definition.MakeImmutable();
} }
public byte ReadPort1(IController c) public byte ReadPort1(IController c)

View File

@ -117,7 +117,8 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
.Select(b => $"P{PortNum} " + b) .Select(b => $"P{PortNum} " + b)
.ToList() .ToList()
}.AddAxis($"P{PortNum} Paddle X 1", (-127).RangeTo(127), 0) }.AddAxis($"P{PortNum} Paddle X 1", (-127).RangeTo(127), 0)
.AddAxis($"P{PortNum} Paddle X 2", (-127).RangeTo(127), 0); .AddAxis($"P{PortNum} Paddle X 2", (-127).RangeTo(127), 0)
.MakeImmutable();
} }
public int PortNum { get; } public int PortNum { get; }
@ -233,7 +234,8 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
.Select(b => $"P{PortNum} " + b) .Select(b => $"P{PortNum} " + b)
.ToList() .ToList()
}.AddAxis($"P{PortNum} Wheel X 1", (-127).RangeTo(127), 0) }.AddAxis($"P{PortNum} Wheel X 1", (-127).RangeTo(127), 0)
.AddAxis($"P{PortNum} Wheel X 2", (-127).RangeTo(127), 0); .AddAxis($"P{PortNum} Wheel X 2", (-127).RangeTo(127), 0)
.MakeImmutable();
} }
public int PortNum { get; } public int PortNum { get; }

View File

@ -38,6 +38,8 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
foreach (var kvp in Port1.Definition.Axes) Definition.Axes.Add(kvp); foreach (var kvp in Port1.Definition.Axes) Definition.Axes.Add(kvp);
foreach (var kvp in Port2.Definition.Axes) Definition.Axes.Add(kvp); foreach (var kvp in Port2.Definition.Axes) Definition.Axes.Add(kvp);
Definition.MakeImmutable();
} }
public byte ReadPort1(IController c) public byte ReadPort1(IController c)

View File

@ -164,7 +164,7 @@ namespace BizHawk.Emulation.Cores.Atari.Lynx
private static readonly ControllerDefinition LynxTroller = new ControllerDefinition("Lynx Controller") private static readonly ControllerDefinition LynxTroller = new ControllerDefinition("Lynx Controller")
{ {
BoolButtons = { "Up", "Down", "Left", "Right", "A", "B", "Option 1", "Option 2", "Pause", "Power" }, BoolButtons = { "Up", "Down", "Left", "Right", "A", "B", "Option 1", "Option 2", "Pause", "Power" },
}; }.MakeImmutable();
public ControllerDefinition ControllerDefinition => LynxTroller; public ControllerDefinition ControllerDefinition => LynxTroller;

View File

@ -55,12 +55,13 @@ namespace BizHawk.Emulation.Cores.Consoles.Belogic
"P2 Up", "P2 Down", "P2 Left", "P2 Right", "P2 Select", "P2 Start", "P2 X", "P2 A", "P2 B", "P2 Y", "P2 L", "P2 R", "P2 Up", "P2 Down", "P2 Left", "P2 Right", "P2 Select", "P2 Start", "P2 X", "P2 A", "P2 B", "P2 Y", "P2 L", "P2 R",
"Power" "Power"
} }
}; }.MakeImmutable();
private static readonly ControllerDefinition Mouse = new ControllerDefinition("SNES Controller") private static readonly ControllerDefinition Mouse = new ControllerDefinition("SNES Controller")
{ {
BoolButtons = { "P1 Mouse Left", "P1 Mouse Right", "Power" } BoolButtons = { "P1 Mouse Left", "P1 Mouse Right", "Power" }
}.AddXYPair("P1 Mouse {0}", AxisPairOrientation.RightAndUp, (-127).RangeTo(127), 0); //TODO verify direction against hardware }.AddXYPair("P1 Mouse {0}", AxisPairOrientation.RightAndUp, (-127).RangeTo(127), 0) //TODO verify direction against hardware
.MakeImmutable();
private static readonly string[] PadBits = private static readonly string[] PadBits =
{ {

View File

@ -32,6 +32,8 @@ namespace BizHawk.Emulation.Cores.ColecoVision
foreach (var kvp in Port1.Definition.Axes) Definition.Axes.Add(kvp); foreach (var kvp in Port1.Definition.Axes) Definition.Axes.Add(kvp);
foreach (var kvp in Port2.Definition.Axes) Definition.Axes.Add(kvp); foreach (var kvp in Port2.Definition.Axes) Definition.Axes.Add(kvp);
Definition.MakeImmutable();
} }
public float wheel1; public float wheel1;

View File

@ -52,7 +52,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
definition.CategoryLabels[s] = "Console"; definition.CategoryLabels[s] = "Console";
} }
return definition; return definition.MakeImmutable();
} }
} }

View File

@ -33,6 +33,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Vectrex
foreach (var kvp in Port1.Definition.Axes) Definition.Axes.Add(kvp); foreach (var kvp in Port1.Definition.Axes) Definition.Axes.Add(kvp);
foreach (var kvp in Port2.Definition.Axes) Definition.Axes.Add(kvp); foreach (var kvp in Port2.Definition.Axes) Definition.Axes.Add(kvp);
Definition.MakeImmutable();
} }
public byte ReadPort1(IController c) public byte ReadPort1(IController c)

View File

@ -33,6 +33,8 @@ namespace BizHawk.Emulation.Cores.Intellivision
foreach (var kvp in Port1.Definition.Axes) Definition.Axes.Add(kvp); foreach (var kvp in Port1.Definition.Axes) Definition.Axes.Add(kvp);
foreach (var kvp in Port2.Definition.Axes) Definition.Axes.Add(kvp); foreach (var kvp in Port2.Definition.Axes) Definition.Axes.Add(kvp);
Definition.MakeImmutable();
} }
public byte ReadPort1(IController c) public byte ReadPort1(IController c)

View File

@ -60,6 +60,8 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk
} }
foreach (var kvp in Port1.Definition.Axes) Definition.Axes.Add(kvp); foreach (var kvp in Port1.Definition.Axes) Definition.Axes.Add(kvp);
Definition.MakeImmutable();
} }
public byte ReadPort1(IController c) public byte ReadPort1(IController c)

View File

@ -52,6 +52,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
// add buttons that the core itself will handle // add buttons that the core itself will handle
Definition.BoolButtons.Add("Reset"); Definition.BoolButtons.Add("Reset");
Definition.BoolButtons.Add("Power"); Definition.BoolButtons.Add("Power");
Definition.MakeImmutable();
} }
public void CoreInputPoll(IController controller) public void CoreInputPoll(IController controller)

View File

@ -265,6 +265,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
{ {
BoolButtons = { "Up", "Down", "Left", "Right", "Start", "Select", "B", "A", "L", "R", "Power" } BoolButtons = { "Up", "Down", "Left", "Right", "Start", "Select", "B", "A", "L", "R", "Power" }
}.AddXYZTriple("Tilt {0}", (-32767).RangeTo(32767), 0) }.AddXYZTriple("Tilt {0}", (-32767).RangeTo(32767), 0)
.AddAxis("Light Sensor", 0.RangeTo(255), 0); .AddAxis("Light Sensor", 0.RangeTo(255), 0)
.MakeImmutable();
} }
} }

View File

@ -23,6 +23,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
}; };
foreach (var kvp in Port1.Definition.Axes) Definition.Axes.Add(kvp); foreach (var kvp in Port1.Definition.Axes) Definition.Axes.Add(kvp);
Definition.MakeImmutable();
} }
public byte ReadPort1(IController c) public byte ReadPort1(IController c)

View File

@ -24,7 +24,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink
.Concat(Port2.Definition.BoolButtons) .Concat(Port2.Definition.BoolButtons)
.Concat(new[] { "Toggle Cable" } ) .Concat(new[] { "Toggle Cable" } )
.ToList() .ToList()
}; }.MakeImmutable();
} }
public byte ReadPort1(IController c) public byte ReadPort1(IController c)

View File

@ -30,7 +30,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink3x
.Concat(new[] { "Toggle Cable CR" } ) .Concat(new[] { "Toggle Cable CR" } )
.Concat(new[] { "Toggle Cable RL" } ) .Concat(new[] { "Toggle Cable RL" } )
.ToList() .ToList()
}; }.MakeImmutable();
} }
public byte ReadPort1(IController c) public byte ReadPort1(IController c)

View File

@ -35,7 +35,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink4x
.Concat(new[] { "Toggle Cable X" } ) .Concat(new[] { "Toggle Cable X" } )
.Concat(new[] { "Toggle Cable 4x" }) .Concat(new[] { "Toggle Cable 4x" })
.ToList() .ToList()
}; }.MakeImmutable();
} }
public byte ReadPort1(IController c) public byte ReadPort1(IController c)

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using BizHawk.Common; using BizHawk.Common;
using BizHawk.Common.CollectionExtensions;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy; using BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy;
@ -281,7 +282,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
{ {
ret.BoolButtons.AddRange(new[] { "Up", "Down", "Left", "Right", "Start", "Select", "B", "A", "Power" }); ret.BoolButtons.AddRange(new[] { "Up", "Down", "Left", "Right", "Start", "Select", "B", "A", "Power" });
} }
return ret; return ret.MakeImmutable();
} }
private LibGambatte.Buttons ControllerCallback() private LibGambatte.Buttons ControllerCallback()

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Linq; using System.Linq;
using BizHawk.Common.CollectionExtensions;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Nintendo.Gameboy namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
@ -153,7 +154,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
ret.BoolButtons.Add("Toggle Link Shift"); ret.BoolButtons.Add("Toggle Link Shift");
ret.BoolButtons.Add("Toggle Link Spacing"); ret.BoolButtons.Add("Toggle Link Spacing");
} }
return ret; return ret.MakeImmutable();
} }
private const int P1 = 0; private const int P1 = 0;

View File

@ -1,4 +1,5 @@
using BizHawk.Common; using BizHawk.Common;
using BizHawk.Common.CollectionExtensions;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Nintendo.N64 namespace BizHawk.Emulation.Cores.Nintendo.N64
@ -42,9 +43,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
if (hasRumblePak) def.HapticsChannels.Add($"P{player} Rumble Pak"); if (hasRumblePak) def.HapticsChannels.Add($"P{player} Rumble Pak");
} }
ControllerDefinition.BoolButtons.Clear(); ControllerDefinition = new("Nintendo 64 Controller");
ControllerDefinition.Axes.Clear();
ControllerDefinition.BoolButtons.AddRange(new[] { "Reset", "Power" }); ControllerDefinition.BoolButtons.AddRange(new[] { "Reset", "Power" });
for (var i = 0; i < 4; i++) for (var i = 0; i < 4; i++)
{ {
@ -56,6 +55,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
syncSettings.Controllers[i].PakType == N64SyncSettings.N64ControllerSettings.N64ControllerPakType.RUMBLE_PAK); syncSettings.Controllers[i].PakType == N64SyncSettings.N64ControllerSettings.N64ControllerPakType.RUMBLE_PAK);
} }
} }
ControllerDefinition.MakeImmutable();
} }
} }
} }

View File

@ -246,7 +246,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
public DisplayType Region => _display_type; public DisplayType Region => _display_type;
public ControllerDefinition ControllerDefinition { get; } = new("Nintendo 64 Controller"); public ControllerDefinition ControllerDefinition { get; private set; } = new("Nintendo 64 Controller");
public void ResetCounters() public void ResetCounters()
{ {

View File

@ -189,7 +189,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS
} }
}.AddXYPair("Touch {0}", AxisPairOrientation.RightAndUp, 0.RangeTo(255), 128, 0.RangeTo(191), 96) }.AddXYPair("Touch {0}", AxisPairOrientation.RightAndUp, 0.RangeTo(255), 128, 0.RangeTo(191), 96)
.AddAxis("Mic Volume", (0).RangeTo(100), 0) .AddAxis("Mic Volume", (0).RangeTo(100), 0)
.AddAxis("GBA Light Sensor", 0.RangeTo(10), 0); .AddAxis("GBA Light Sensor", 0.RangeTo(10), 0)
.MakeImmutable();
private LibMelonDS.Buttons GetButtons(IController c) private LibMelonDS.Buttons GetButtons(IController c)
{ {
LibMelonDS.Buttons b = 0; LibMelonDS.Buttons b = 0;

View File

@ -177,6 +177,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
ControllerDefinition.AddAxis("Reset Cycle", 0.RangeTo(500000), 0); ControllerDefinition.AddAxis("Reset Cycle", 0.RangeTo(500000), 0);
} }
ControllerDefinition.MakeImmutable();
// don't replace the magicSoundProvider on reset, as it's not needed // don't replace the magicSoundProvider on reset, as it's not needed
// if (magicSoundProvider != null) magicSoundProvider.Dispose(); // if (magicSoundProvider != null) magicSoundProvider.Dispose();

View File

@ -256,7 +256,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
"P1 Up", "P1 Down", "P1 Left", "P1 Right", "P1 Start", "P1 Select", "P1 B", "P1 A", "Reset", "Power", "P1 Up", "P1 Down", "P1 Left", "P1 Right", "P1 Start", "P1 Select", "P1 B", "P1 A", "Reset", "Power",
"P2 Up", "P2 Down", "P2 Left", "P2 Right", "P2 Start", "P2 Select", "P2 B", "P2 A" "P2 Up", "P2 Down", "P2 Left", "P2 Right", "P2 Start", "P2 Select", "P2 B", "P2 A"
} }
}; }.MakeImmutable();
public ControllerDefinition ControllerDefinition { get; private set; } public ControllerDefinition ControllerDefinition { get; private set; }

View File

@ -6,6 +6,7 @@ using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using BizHawk.Common; using BizHawk.Common;
using BizHawk.Common.CollectionExtensions;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Nintendo.NES; using BizHawk.Emulation.Cores.Nintendo.NES;
using BizHawk.BizInvoke; using BizHawk.BizInvoke;
@ -125,7 +126,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES
if (_syncSettings.LeftPortConnected && _syncSettings.RightPortConnected) if (_syncSettings.LeftPortConnected && _syncSettings.RightPortConnected)
def.BoolButtons.AddRange(PadP2.Select(p => p.Name)); def.BoolButtons.AddRange(PadP2.Select(p => p.Name));
def.BoolButtons.AddRange(new[] { "Reset", "Power" }); // console buttons def.BoolButtons.AddRange(new[] { "Reset", "Power" }); // console buttons
ControllerDefinition = def; ControllerDefinition = def.MakeImmutable();
} }
private struct PadEnt private struct PadEnt

View File

@ -69,6 +69,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
// add buttons that the core itself will handle // add buttons that the core itself will handle
Definition.BoolButtons.Add("Reset"); Definition.BoolButtons.Add("Reset");
Definition.BoolButtons.Add("Power"); Definition.BoolButtons.Add("Power");
Definition.MakeImmutable();
} }
public void NativeInit(LibsnesApi api) public void NativeInit(LibsnesApi api)

View File

@ -115,6 +115,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES9X
// add buttons that the core itself will handle // add buttons that the core itself will handle
_controllerDefinition.BoolButtons.Add("Reset"); _controllerDefinition.BoolButtons.Add("Reset");
_controllerDefinition.BoolButtons.Add("Power"); _controllerDefinition.BoolButtons.Add("Power");
_controllerDefinition.MakeImmutable();
} }
private void UpdateControls(IController c) private void UpdateControls(IController c)

View File

@ -40,7 +40,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.SubGBHawk
_tracer = new TraceBuffer(_GBCore.cpu.TraceHeader); _tracer = new TraceBuffer(_GBCore.cpu.TraceHeader);
ser.Register(_tracer); ser.Register(_tracer);
_GBCore.ControllerDefinition.AddAxis("Input Cycle", 0.RangeTo(70224), 70224); _GBCore.ControllerDefinition.AddAxis("Input Cycle", 0.RangeTo(70224), 70224)
.MakeImmutable();
} }
public GBHawk.GBHawk _GBCore; public GBHawk.GBHawk _GBCore;

View File

@ -110,7 +110,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.VB
.OrderBy(b => _buttonOrdinals[b]) .OrderBy(b => _buttonOrdinals[b])
.Concat(new[] { "Power" }) .Concat(new[] { "Power" })
.ToList() .ToList()
}; }.MakeImmutable();
public override ControllerDefinition ControllerDefinition => VirtualBoyController; public override ControllerDefinition ControllerDefinition => VirtualBoyController;

View File

@ -46,6 +46,7 @@ namespace BizHawk.Emulation.Cores.PCEngine
foreach (var kvp in _port3.Definition.Axes) Definition.Axes.Add(kvp); foreach (var kvp in _port3.Definition.Axes) Definition.Axes.Add(kvp);
foreach (var kvp in _port4.Definition.Axes) Definition.Axes.Add(kvp); foreach (var kvp in _port4.Definition.Axes) Definition.Axes.Add(kvp);
foreach (var kvp in _port5.Definition.Axes) Definition.Axes.Add(kvp); foreach (var kvp in _port5.Definition.Axes) Definition.Axes.Add(kvp);
Definition.MakeImmutable();
} }
private readonly IPort _port1; private readonly IPort _port1;

View File

@ -25,7 +25,7 @@ namespace BizHawk.Emulation.Cores.Sega.GGHawkLink
.Concat(Port2.Definition.BoolButtons) .Concat(Port2.Definition.BoolButtons)
.Concat(new[] { "Toggle Cable" } ) .Concat(new[] { "Toggle Cable" } )
.ToList() .ToList()
}; }.MakeImmutable();
} }
public byte ReadPort1(IController c) public byte ReadPort1(IController c)

View File

@ -131,7 +131,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive
"P2 Up", "P2 Down", "P2 Left", "P2 Right", "P2 A", "P2 B", "P2 C", "P2 Start", "P2 X", "P2 Y", "P2 Z", "P2 Mode", "P2 Up", "P2 Down", "P2 Left", "P2 Right", "P2 A", "P2 B", "P2 C", "P2 Start", "P2 X", "P2 Y", "P2 Z", "P2 Mode",
"Power", "Reset" "Power", "Reset"
} }
}; }.MakeImmutable();
private static readonly string[] ButtonOrders = private static readonly string[] ButtonOrders =
{ {

View File

@ -23,7 +23,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
BoolButtons = new[] { "Reset" } BoolButtons = new[] { "Reset" }
.Concat(Port1.Definition.BoolButtons) .Concat(Port1.Definition.BoolButtons)
.ToList() .ToList()
}; }.MakeImmutable();
} }
else else
{ {
@ -38,7 +38,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
.Concat(Port1.Definition.BoolButtons) .Concat(Port1.Definition.BoolButtons)
.Concat(Port2.Definition.BoolButtons) .Concat(Port2.Definition.BoolButtons)
.ToList() .ToList()
}; }.MakeImmutable();
} }
else else
{ {
@ -49,7 +49,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
.Concat(Port2.Definition.BoolButtons) .Concat(Port2.Definition.BoolButtons)
.Concat(KeyboardMap) .Concat(KeyboardMap)
.ToList() .ToList()
}; }.MakeImmutable();
} }
foreach (var kvp in Port1.Definition.Axes) Definition.Axes.Add(kvp); foreach (var kvp in Port1.Definition.Axes) Definition.Axes.Add(kvp);

View File

@ -235,6 +235,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
throw new Exception("Unknown Genesis control device! Something went wrong."); throw new Exception("Unknown Genesis control device! Something went wrong.");
} }
} }
ControllerDef.MakeImmutable();
} }
public void Convert(IController source, LibGPGX.InputData target) public void Convert(IController source, LibGPGX.InputData target)

View File

@ -163,7 +163,7 @@ namespace BizHawk.Emulation.Cores.Sony.PS2
{ "LEFT X", new AxisSpec(0.RangeTo(255), 128) }, { "LEFT X", new AxisSpec(0.RangeTo(255), 128) },
{ "LEFT Y", new AxisSpec(0.RangeTo(255), 128) }, { "LEFT Y", new AxisSpec(0.RangeTo(255), 128) },
} }
}; }.MakeImmutable();
public class DobieSyncSettings public class DobieSyncSettings
{ {

View File

@ -354,7 +354,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
definition.AddAxis("Disc Select", 0.RangeTo(1), 1); definition.AddAxis("Disc Select", 0.RangeTo(1), 1);
return definition; return definition.MakeImmutable();
} }
private void SetControllerButtons() private void SetControllerButtons()

View File

@ -61,7 +61,8 @@ namespace BizHawk.Emulation.Cores.WonderSwan
{ "P2 B", "Rotated" }, { "P2 B", "Rotated" },
{ "P2 A", "Rotated" }, { "P2 A", "Rotated" },
} }
}; }.MakeImmutable();
public ControllerDefinition ControllerDefinition => WonderSwanController; public ControllerDefinition ControllerDefinition => WonderSwanController;
private BizSwan.Buttons GetButtons(IController controller) private BizSwan.Buttons GetButtons(IController controller)

View File

@ -275,7 +275,7 @@ namespace BizHawk.Emulation.Cores.Libretro
definition.CategoryLabels[key] = "RetroKeyboard"; definition.CategoryLabels[key] = "RetroKeyboard";
} }
return definition; return definition.MakeImmutable();
} }
public ControllerDefinition ControllerDefinition { get; } public ControllerDefinition ControllerDefinition { get; }

View File

@ -263,7 +263,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
ret.BoolButtons.Add("Previous Disk"); ret.BoolButtons.Add("Previous Disk");
ret.BoolButtons.Add("Next Disk"); ret.BoolButtons.Add("Next Disk");
} }
Definition = ret; Definition = ret.MakeImmutable();
finalDevices.Add(null); finalDevices.Add(null);
Devices = finalDevices.ToArray(); Devices = finalDevices.ToArray();
_switchPreviousFrame = switchPreviousFrame.ToArray(); _switchPreviousFrame = switchPreviousFrame.ToArray();

View File

@ -16,8 +16,11 @@ namespace BizHawk.Tests.Client.Common.Display
[TestInitialize] [TestInitialize]
public void Initializer() public void Initializer()
{ {
_boolController = new(new ControllerDefinition("Dummy Gamepad") { BoolButtons = { "A" } }); _boolController = new(new ControllerDefinition("Dummy Gamepad") { BoolButtons = { "A" } }.MakeImmutable());
_axisController = new(new ControllerDefinition("Dummy Gamepad").AddXYPair("Stick{0}", AxisPairOrientation.RightAndUp, 0.RangeTo(200), MidValue)); _axisController = new(
new ControllerDefinition("Dummy Gamepad")
.AddXYPair("Stick{0}", AxisPairOrientation.RightAndUp, 0.RangeTo(200), MidValue)
.MakeImmutable());
} }
[TestMethod] [TestMethod]

View File

@ -15,14 +15,17 @@ namespace BizHawk.Tests.Client.Common.Movie
[TestInitialize] [TestInitialize]
public void Initializer() public void Initializer()
{ {
_boolController = new(new ControllerDefinition("Dummy Gamepad") { BoolButtons = { "A" } }); _boolController = new(new ControllerDefinition("Dummy Gamepad") { BoolButtons = { "A" } }.MakeImmutable());
_axisController = new(new ControllerDefinition("Dummy Gamepad").AddXYPair("Stick{0}", AxisPairOrientation.RightAndUp, 0.RangeTo(200), 100)); _axisController = new(
new ControllerDefinition("Dummy Gamepad")
.AddXYPair("Stick{0}", AxisPairOrientation.RightAndUp, 0.RangeTo(200), 100)
.MakeImmutable());
} }
[TestMethod] [TestMethod]
public void GenerateLogEntry_ExclamationForUnknownButtons() public void GenerateLogEntry_ExclamationForUnknownButtons()
{ {
SimpleController controller = new(new ControllerDefinition("Dummy Gamepad") { BoolButtons = { "Unknown Button" } }); SimpleController controller = new(new ControllerDefinition("Dummy Gamepad") { BoolButtons = { "Unknown Button" } }.MakeImmutable());
var lg = new Bk2LogEntryGenerator("NES", controller); var lg = new Bk2LogEntryGenerator("NES", controller);
controller["Unknown Button"] = true; controller["Unknown Button"] = true;
var actual = lg.GenerateLogEntry(); var actual = lg.GenerateLogEntry();