diff --git a/src/BizHawk.Client.Common/movie/import/FcmImport.cs b/src/BizHawk.Client.Common/movie/import/FcmImport.cs index a6cb95ffa7..8e1d7a44cd 100644 --- a/src/BizHawk.Client.Common/movie/import/FcmImport.cs +++ b/src/BizHawk.Client.Common/movie/import/FcmImport.cs @@ -37,8 +37,7 @@ namespace BizHawk.Client.Common.movie.import NesLeftPort = nameof(ControllerNES), NesRightPort = nameof(ControllerNES) }; - _deck = controllerSettings.Instantiate((x, y) => true); - AddDeckControlButtons(); + _deck = controllerSettings.Instantiate((x, y) => true).AddSystemToControllerDef(); // 004 4-byte little-endian unsigned int: version number, must be 2 uint version = r.ReadUInt32(); @@ -145,7 +144,7 @@ namespace BizHawk.Client.Common.movie.import // Advance to first byte of input data. r.BaseStream.Position = firstFrameOffset; - SimpleController controllers = new(_deck.GetDefinition()); + SimpleController controllers = new(_deck.ControllerDef); string[] buttons = { "A", "B", "Select", "Start", "Up", "Down", "Left", "Right" }; bool fds = false; @@ -287,15 +286,5 @@ namespace BizHawk.Client.Common.movie.import syncSettings.Controls = controllerSettings; Result.Movie.SyncSettingsJson = ConfigService.SaveWithType(syncSettings); } - - private void AddDeckControlButtons() - { - SimpleController controllers = new(_deck.GetDefinition()); - - // TODO: FDS - // Yes, this adds them to the deck definition too - controllers.Definition.BoolButtons.Add("Reset"); - controllers.Definition.BoolButtons.Add("Power"); - } } } diff --git a/src/BizHawk.Client.Common/movie/import/Fm2Import.cs b/src/BizHawk.Client.Common/movie/import/Fm2Import.cs index 8c0c1f9845..0dcc3faf51 100644 --- a/src/BizHawk.Client.Common/movie/import/Fm2Import.cs +++ b/src/BizHawk.Client.Common/movie/import/Fm2Import.cs @@ -27,8 +27,7 @@ namespace BizHawk.Client.Common NesRightPort = nameof(UnpluggedNES) }; - _deck = controllerSettings.Instantiate((x, y) => true); - AddDeckControlButtons(); + _deck = controllerSettings.Instantiate((x, y) => true).AddSystemToControllerDef(); Result.Movie.HeaderEntries[HeaderKeys.Platform] = platform; @@ -123,8 +122,7 @@ namespace BizHawk.Client.Common if (ParseHeader(line, "port0") == "1") { controllerSettings.NesLeftPort = nameof(ControllerNES); - _deck = controllerSettings.Instantiate((x, y) => false); - AddDeckControlButtons(); + _deck = controllerSettings.Instantiate((x, y) => false).AddSystemToControllerDef(); } } else if (line.ToLower().StartsWith("port1")) @@ -132,8 +130,7 @@ namespace BizHawk.Client.Common if (ParseHeader(line, "port1") == "1") { controllerSettings.NesRightPort = nameof(ControllerNES); - _deck = controllerSettings.Instantiate((x, y) => false); - AddDeckControlButtons(); + _deck = controllerSettings.Instantiate((x, y) => false).AddSystemToControllerDef(); } } else if (line.ToLower().StartsWith("port2")) @@ -153,7 +150,7 @@ namespace BizHawk.Client.Common controllerSettings.NesRightPort = nameof(FourScore); } - _deck = controllerSettings.Instantiate((x, y) => false); + _deck = controllerSettings.Instantiate((x, y) => false)/*.AddSystemToControllerDef()*/; //TODO call omitted on purpose? --yoshi } else { @@ -170,7 +167,7 @@ namespace BizHawk.Client.Common private readonly string[] _buttons = { "Right", "Left", "Down", "Up", "Start", "Select", "B", "A" }; private void ImportInputFrame(string line) { - SimpleController controllers = new(_deck.GetDefinition()); + SimpleController controllers = new(_deck.ControllerDef); string[] sections = line.Split(new[] {'|'}, StringSplitOptions.RemoveEmptyEntries); controllers["Reset"] = sections[1][0] == '1'; @@ -213,16 +210,6 @@ namespace BizHawk.Client.Common Result.Movie.AppendFrame(controllers); } - private void AddDeckControlButtons() - { - SimpleController controllers = new(_deck.GetDefinition()); - - // TODO: FDS - // Yes, this adds them to the deck definition too - controllers.Definition.BoolButtons.Add("Reset"); - controllers.Definition.BoolButtons.Add("Power"); - } - private static string ImportTextSubtitle(string line) { line = SingleSpaces(line); @@ -273,4 +260,16 @@ namespace BizHawk.Client.Common } } } + + internal static class NESHelpers + { + public static IControllerDeck AddSystemToControllerDef(this IControllerDeck deck) + { + var def = deck.ControllerDef; + //TODO FDS + def.BoolButtons.Add("Reset"); + def.BoolButtons.Add("Power"); + return deck; + } + } } diff --git a/src/BizHawk.Client.Common/movie/import/FmvImport.cs b/src/BizHawk.Client.Common/movie/import/FmvImport.cs index fb521e3818..3562fdb620 100644 --- a/src/BizHawk.Client.Common/movie/import/FmvImport.cs +++ b/src/BizHawk.Client.Common/movie/import/FmvImport.cs @@ -94,13 +94,11 @@ namespace BizHawk.Client.Common.movie.import NesLeftPort = controller1 ? nameof(ControllerNES) : nameof(UnpluggedNES), NesRightPort = controller2 ? nameof(ControllerNES) : nameof(UnpluggedNES) }; - _deck = controllerSettings.Instantiate((x, y) => true); + _deck = controllerSettings.Instantiate((x, y) => true).AddSystemToControllerDef(); syncSettings.Controls.NesLeftPort = controllerSettings.NesLeftPort; syncSettings.Controls.NesRightPort = controllerSettings.NesRightPort; - AddDeckControlButtons(); - - SimpleController controllers = new(_deck.GetDefinition()); + SimpleController controllers = new(_deck.ControllerDef); /* * 01 Right @@ -161,17 +159,5 @@ namespace BizHawk.Client.Common.movie.import Result.Movie.SyncSettingsJson = ConfigService.SaveWithType(syncSettings); } - - private void AddDeckControlButtons() - { - SimpleController controllers = new(_deck.GetDefinition()); - - // TODO: FDS - // Yes, this adds them to the deck definition too - controllers.Definition.BoolButtons.Add("Reset"); - controllers.Definition.BoolButtons.Add("Power"); - } - - } } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.Core.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.Core.cs index ae4a07c315..c385109ec0 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.Core.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.Core.cs @@ -145,16 +145,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES ram = new byte[0x800]; CIRAM = new byte[0x800]; - // wire controllers - // todo: allow changing this - ControllerDeck = ControllerSettings.Instantiate(ppu.LightGunCallback); // set controller definition first time only if (ControllerDefinition == null) { - ControllerDefinition = new ControllerDefinition(ControllerDeck.GetDefinition()) - { - Name = "NES Controller" - }; + ControllerDeck = ControllerSettings.Instantiate(ppu.LightGunCallback); // this assignment was outside the conditional for some reason? --yoshi + ControllerDefinition = ControllerDeck.ControllerDef; // controls other than the deck ControllerDefinition.BoolButtons.Add("Power"); diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NESControllers.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NESControllers.cs index b4e839e703..7c373759d7 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NESControllers.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NESControllers.cs @@ -70,6 +70,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES /// </summary> public interface IControllerDeck { + /// <remarks> + /// implementations create a single <see cref="ControllerDefinition"/> in their ctors and will always return a reference to it; + /// caller may mutate it + /// </remarks> + ControllerDefinition ControllerDef { get; } + /// <summary> /// call whenever $4016 is written /// </summary> @@ -84,7 +90,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES /// </summary> /// <returns>bits 0-4 are valid</returns> byte ReadB(IController c); // D0:D4 - ControllerDefinition GetDefinition(); + void SyncState(Serializer ser); } @@ -93,6 +99,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES /// </summary> public interface IFamicomExpansion { + ControllerDefinition ControllerDefFragment { get; } + void Strobe(StrobeInfo s, IController c); /// <summary> /// read data from $4016 @@ -104,7 +112,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES /// </summary> /// <returns>bits 1-4 are valid</returns> byte ReadB(IController c); - ControllerDefinition GetDefinition(); + void SyncState(Serializer ser); } @@ -113,9 +121,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES /// </summary> public interface INesPort { + ControllerDefinition ControllerDefFragment { get; } + void Strobe(StrobeInfo s, IController c); // only uses OUT0 byte Read(IController c); // only uses D0, D3, D4 - ControllerDefinition GetDefinition(); + void SyncState(Serializer ser); } @@ -128,13 +138,17 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES private readonly INesPort _right; private readonly ControlDefUnMerger _leftU; private readonly ControlDefUnMerger _rightU; - private readonly ControllerDefinition _definition; + + public ControllerDefinition ControllerDef { get; } public NesDeck(INesPort left, INesPort right, LightgunDelegate ppuCallback) { _left = left; _right = right; - _definition = ControllerDefinitionMerger.GetMerged(new[] { left.GetDefinition(), right.GetDefinition() }, out var cdum); + ControllerDef = ControllerDefinitionMerger.GetMerged( + new[] { left.ControllerDefFragment, right.ControllerDefFragment }, + out var cdum); + ControllerDef.Name = "NES Controller"; _leftU = cdum[0]; _rightU = cdum[1]; @@ -167,11 +181,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES return (byte)(_right.Read(_rightU.UnMerge(c)) & 0x19); } - public ControllerDefinition GetDefinition() - { - return _definition; - } - public void SyncState(Serializer ser) { ser.BeginSection(nameof(_left)); @@ -185,6 +194,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES public class UnpluggedNES : INesPort { + public ControllerDefinition ControllerDefFragment { get; } = new(); + public void Strobe(StrobeInfo s, IController c) { } @@ -194,11 +205,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES return 0; } - public ControllerDefinition GetDefinition() - { - return new ControllerDefinition(); - } - public void SyncState(Serializer ser) { } @@ -224,16 +230,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES private readonly bool _famicomP2Hack; - private readonly ControllerDefinition _definition; + public ControllerDefinition ControllerDefFragment { get; } public ControllerNES() { - _definition = new ControllerDefinition - { - BoolButtons = Buttons - .OrderBy(x => _buttonOrdinals[x]) - .ToList() - }; + ControllerDefFragment = new() { BoolButtons = Buttons.OrderBy(x => _buttonOrdinals[x]).ToList() }; } @@ -253,22 +254,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES { if (famicomP2) { - _definition = new ControllerDefinition - { - BoolButtons = FamicomP2Buttons - .Where((s) => s != null) - .OrderBy(x => _buttonOrdinals[x]) - .ToList() - }; + ControllerDefFragment = new() { BoolButtons = FamicomP2Buttons.Where(static s => s is not null).OrderBy(x => _buttonOrdinals[x]).ToList() }; } else { - _definition = new ControllerDefinition - { - BoolButtons = Buttons - .OrderBy(x => _buttonOrdinals[x]) - .ToList() - }; + ControllerDefFragment = new() { BoolButtons = Buttons.OrderBy(x => _buttonOrdinals[x]).ToList() }; } _famicomP2Hack = famicomP2; @@ -301,11 +291,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES return ret; } - public ControllerDefinition GetDefinition() - { - return _definition; - } - public void SyncState(Serializer ser) { ser.Sync(nameof(_resetting), ref _resetting); @@ -327,15 +312,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES "0A", "0X", "0L", "0R", null, null, null, null // 4 0s at end }; - private readonly ControllerDefinition _definition; - - public ControllerSNES() - { - _definition = new ControllerDefinition - { - BoolButtons = Buttons.Where(s => s != null).ToList() - }; - } + public ControllerDefinition ControllerDefFragment { get; } + = new() { BoolButtons = Buttons.Where(static s => s is not null).ToList() }; // reset is not edge triggered; so long as it's high, the latch is continuously reloading // so we need to latch in two places: @@ -364,11 +342,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES return ret; } - public ControllerDefinition GetDefinition() - { - return _definition; - } - public void SyncState(Serializer ser) { ser.Sync(nameof(_resetting), ref _resetting); @@ -385,7 +358,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES private bool _resetting; private byte _latchedValue = 0x54 ^ 0xff; - private static readonly ControllerDefinition Definition + public ControllerDefinition ControllerDefFragment { get; } = new ControllerDefinition { BoolButtons = { "0Fire" } } .AddAxis("0Paddle", 0.RangeTo(160), 80); @@ -414,11 +387,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES return ret; } - public ControllerDefinition GetDefinition() - { - return Definition; - } - public void SyncState(Serializer ser) { ser.Sync(nameof(_shiftidx), ref _shiftidx); @@ -440,7 +408,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES "1A", "1B", "1Select", "1Start", "1Up", "1Down", "1Left", "1Right", }; - private static readonly ControllerDefinition Definition = new ControllerDefinition { BoolButtons = new List<string>(Buttons) }; + public ControllerDefinition ControllerDefFragment { get; } + = new() { BoolButtons = Buttons.ToList() }; private bool _resetting; private int _latchedValue; @@ -473,11 +442,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES return ret; } - public ControllerDefinition GetDefinition() - { - return Definition; - } - public void SyncState(Serializer ser) { ser.Sync(nameof(_resetting), ref _resetting); @@ -489,7 +453,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES { private static readonly string[] D3Buttons = { "0PP2", "0PP1", "0PP5", "0PP9", "0PP6", "0PP10", "0PP11", "0PP7" }; private static readonly string[] D4Buttons = { "0PP4", "0PP3", "0PP12", "0PP8" }; - private static readonly ControllerDefinition Definition = new ControllerDefinition { BoolButtons = new List<string>(D3Buttons.Concat(D4Buttons)) }; + + public ControllerDefinition ControllerDefFragment { get; } + = new() { BoolButtons = D3Buttons.Concat(D4Buttons).ToList() }; private bool _resetting; private int _latched3; @@ -522,11 +488,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES return (byte)(d3 << 3 | d4 << 4); } - public ControllerDefinition GetDefinition() - { - return Definition; - } - public void SyncState(Serializer ser) { ser.Sync(nameof(_resetting), ref _resetting); @@ -554,8 +515,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES /// </summary> public LightgunDelegate PPUCallback { get; set; } - private static readonly ControllerDefinition Definition - = new ControllerDefinition { BoolButtons = { "0Fire" } }.AddZapper("0Zapper {0}"); + public ControllerDefinition ControllerDefFragment { get; } + = new ControllerDefinition { BoolButtons = { "0Fire" } } + .AddZapper("0Zapper {0}"); public void Strobe(StrobeInfo s, IController c) { @@ -572,11 +534,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES return ret; } - public ControllerDefinition GetDefinition() - { - return Definition; - } - public void SyncState(Serializer ser) { } @@ -603,8 +560,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES private bool _resetting; private uint _latchedValue; - private static readonly ControllerDefinition Definition - = new ControllerDefinition { BoolButtons = { "0Fire" } }.AddZapper("0Zapper {0}"); + public ControllerDefinition ControllerDefFragment { get; } + = new ControllerDefinition { BoolButtons = { "0Fire" } } + .AddZapper("0Zapper {0}"); private void Latch(IController c) { @@ -637,11 +595,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES return ret; } - public ControllerDefinition GetDefinition() - { - return Definition; - } - public void SyncState(Serializer ser) { ser.Sync(nameof(_resetting), ref _resetting); @@ -671,14 +624,16 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES private readonly ControlDefUnMerger _player2U; private readonly ControlDefUnMerger _player3U; - private readonly ControllerDefinition _definition; + public ControllerDefinition ControllerDef { get; } public FamicomDeck(IFamicomExpansion expSlot, LightgunDelegate ppuCallback) { _player3 = expSlot; - _definition = ControllerDefinitionMerger.GetMerged( - new[] { _player1.GetDefinition(), _player2.GetDefinition(), _player3.GetDefinition() }, out var cdum); - _definition.BoolButtons.Add("P2 Microphone"); + ControllerDef = ControllerDefinitionMerger.GetMerged( + new[] { _player1.ControllerDefFragment, _player2.ControllerDefFragment, _player3.ControllerDefFragment }, + out var cdum); + ControllerDef.BoolButtons.Add("P2 Microphone"); + ControllerDef.Name = "NES Controller"; _player1U = cdum[0]; _player2U = cdum[1]; _player3U = cdum[2]; @@ -713,11 +668,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES return ret; } - public ControllerDefinition GetDefinition() - { - return _definition; - } - public void SyncState(Serializer ser) { ser.BeginSection("Left"); @@ -741,7 +691,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES private bool _resetting; private byte _latchedValue = 0x54 ^ 0xff; - private static readonly ControllerDefinition Definition + public ControllerDefinition ControllerDefFragment { get; } = new ControllerDefinition { BoolButtons = { "0Fire" } } .AddAxis("0Paddle", 0.RangeTo(160), 80); @@ -775,11 +725,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES return ret; } - public ControllerDefinition GetDefinition() - { - return Definition; - } - public void SyncState(Serializer ser) { ser.Sync(nameof(_shiftidx), ref _shiftidx); @@ -875,7 +820,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES }; - private static readonly ControllerDefinition Definition = new ControllerDefinition { BoolButtons = new List<string>(Buttons) }; + public ControllerDefinition ControllerDefFragment { get; } + = new() { BoolButtons = Buttons.ToList() }; private bool _active; private int _column; @@ -919,11 +865,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES return ret; } - public ControllerDefinition GetDefinition() - { - return Definition; - } - public void SyncState(Serializer ser) { ser.Sync(nameof(_active), ref _active); @@ -944,7 +885,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES "1A", "1B", "1Select", "1Start", "1Up", "1Down", "1Left", "1Right", }; - private static readonly ControllerDefinition Definition = new ControllerDefinition { BoolButtons = new List<string>(P1Buttons.Concat(P2Buttons)) }; + public ControllerDefinition ControllerDefFragment { get; } + = new() { BoolButtons = P1Buttons.Concat(P2Buttons).ToList() }; private bool _resetting; private int _latchedP1; @@ -983,11 +925,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES return ret; } - public ControllerDefinition GetDefinition() - { - return Definition; - } - public void SyncState(Serializer ser) { ser.Sync(nameof(_resetting), ref _resetting); @@ -998,7 +935,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES public class OekaKids : IFamicomExpansion { - private static readonly ControllerDefinition Definition + public ControllerDefinition ControllerDefFragment { get; } = new ControllerDefinition { BoolButtons = { "0Click", "0Touch" } } .AddZapper("0Pen {0}"); // why would a tablet have the same resolution as a CRT monitor? --yoshi @@ -1052,11 +989,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES return ret; } - public ControllerDefinition GetDefinition() - { - return Definition; - } - public void SyncState(Serializer ser) { ser.Sync(nameof(_resetting), ref _resetting); @@ -1067,6 +999,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES public class UnpluggedFam : IFamicomExpansion { + public ControllerDefinition ControllerDefFragment => new(); + public void Strobe(StrobeInfo s, IController c) { } @@ -1081,11 +1015,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES return 0; } - public ControllerDefinition GetDefinition() - { - return new ControllerDefinition(); - } - public void SyncState(Serializer ser) { }