diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
index 07fb3f1ede..75343412ce 100644
--- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
+++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
@@ -1005,6 +1005,7 @@
+
PCEngine.cs
diff --git a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IEmulator.cs
index ce4d1af49a..5fa7f01d7e 100644
--- a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IEmulator.cs
+++ b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IEmulator.cs
@@ -6,7 +6,7 @@ namespace BizHawk.Emulation.Cores.PCEngine
{
public IEmulatorServiceProvider ServiceProvider { get; private set; }
- public ControllerDefinition ControllerDefinition => PCEngineController;
+ public ControllerDefinition ControllerDefinition => _controllerDeck.Definition;
public void FrameAdvance(IController controller, bool render, bool rendersound)
{
diff --git a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ISettable.cs b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ISettable.cs
index 28694b69d5..39e6d2dcaf 100644
--- a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ISettable.cs
+++ b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ISettable.cs
@@ -1,4 +1,7 @@
-using BizHawk.Emulation.Common;
+using System.ComponentModel;
+
+using BizHawk.Common;
+using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.PCEngine
{
@@ -62,6 +65,36 @@ namespace BizHawk.Emulation.Cores.PCEngine
public class PCESyncSettings
{
+ [DefaultValue(PceControllerType.GamePad)]
+ [DisplayName("Port 1 Device")]
+ [Description("The type of controller plugged into the first controller port")]
+ [TypeConverter(typeof(DescribableEnumConverter))]
+ public PceControllerType Port1 { get; set; } = PceControllerType.GamePad;
+
+ [DefaultValue(PceControllerType.Unplugged)]
+ [DisplayName("Port 2 Device")]
+ [Description("The type of controller plugged into the second controller port")]
+ [TypeConverter(typeof(DescribableEnumConverter))]
+ public PceControllerType Port2 { get; set; } = PceControllerType.Unplugged;
+
+ [DefaultValue(PceControllerType.Unplugged)]
+ [DisplayName("Port 3 Device")]
+ [Description("The type of controller plugged into the third controller port")]
+ [TypeConverter(typeof(DescribableEnumConverter))]
+ public PceControllerType Port3 { get; set; } = PceControllerType.Unplugged;
+
+ [DefaultValue(PceControllerType.Unplugged)]
+ [DisplayName("Port 4 Device")]
+ [Description("The type of controller plugged into the fourth controller port")]
+ [TypeConverter(typeof(DescribableEnumConverter))]
+ public PceControllerType Port4 { get; set; } = PceControllerType.Unplugged;
+
+ [DefaultValue(PceControllerType.Unplugged)]
+ [DisplayName("Port 5 Device")]
+ [Description("The type of controller plugged into the fifth controller port")]
+ [TypeConverter(typeof(DescribableEnumConverter))]
+ public PceControllerType Port5 { get; set; } = PceControllerType.Unplugged;
+
public ControllerSetting[] Controllers =
{
new ControllerSetting { IsConnected = true },
diff --git a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.Input.cs b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.Input.cs
index c40788c08a..52b5c7e444 100644
--- a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.Input.cs
+++ b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.Input.cs
@@ -63,6 +63,8 @@ namespace BizHawk.Emulation.Cores.PCEngine
}
}
+ private readonly PceControllerDeck _controllerDeck;
+
private byte ReadInput()
{
InputCallbacks.Call();
@@ -72,21 +74,7 @@ namespace BizHawk.Emulation.Cores.PCEngine
if (player < 6)
{
_lagged = false;
- if (SEL == false) // return buttons
- {
- if (_controller.IsPressed("P" + player + " B1")) value &= 0xFE;
- if (_controller.IsPressed("P" + player + " B2")) value &= 0xFD;
- if (_controller.IsPressed("P" + player + " Select")) value &= 0xFB;
- if (_controller.IsPressed("P" + player + " Run")) value &= 0xF7;
- }
- else
- {
- //return directions
- if (_controller.IsPressed("P" + player + " Up")) value &= 0xFE;
- if (_controller.IsPressed("P" + player + " Right")) value &= 0xFD;
- if (_controller.IsPressed("P" + player + " Down")) value &= 0xFB;
- if (_controller.IsPressed("P" + player + " Left")) value &= 0xF7;
- }
+ value &= _controllerDeck.Read(player, _controller, SEL);
}
if (Region == "Japan")
diff --git a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.cs b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.cs
index 32ca565b65..d3d43f1464 100644
--- a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.cs
+++ b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.cs
@@ -41,7 +41,14 @@ namespace BizHawk.Emulation.Cores.PCEngine
Settings = (PCESettings)settings ?? new PCESettings();
_syncSettings = (PCESyncSettings)syncSettings ?? new PCESyncSettings();
Init(game, rom);
- SetControllerButtons();
+
+ _controllerDeck = new PceControllerDeck(
+ _syncSettings.Port1,
+ _syncSettings.Port2,
+ _syncSettings.Port3,
+ _syncSettings.Port4,
+ _syncSettings.Port5);
+ //SetControllerButtons(); // TODO: get rid of this method
}
public PCEngine(CoreComm comm, GameInfo game, Disc disc, object Settings, object syncSettings)
@@ -96,7 +103,14 @@ namespace BizHawk.Emulation.Cores.PCEngine
// the default RomStatusDetails don't do anything with Disc
CoreComm.RomStatusDetails = string.Format("{0}\r\nDisk partial hash:{1}", game.Name, new DiscSystem.DiscHasher(disc).OldHash());
- SetControllerButtons();
+
+ _controllerDeck = new PceControllerDeck(
+ _syncSettings.Port1,
+ _syncSettings.Port2,
+ _syncSettings.Port3,
+ _syncSettings.Port4,
+ _syncSettings.Port5);
+ //SetControllerButtons();
}
// ROM
diff --git a/BizHawk.Emulation.Cores/Consoles/PC Engine/PceControllerDeck.cs b/BizHawk.Emulation.Cores/Consoles/PC Engine/PceControllerDeck.cs
new file mode 100644
index 0000000000..ac5a9efd24
--- /dev/null
+++ b/BizHawk.Emulation.Cores/Consoles/PC Engine/PceControllerDeck.cs
@@ -0,0 +1,162 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using BizHawk.Emulation.Common;
+
+namespace BizHawk.Emulation.Cores.PCEngine
+{
+ public enum PceControllerType
+ {
+ Unplugged,
+ GamePad
+ }
+
+ public class PceControllerDeck
+ {
+ private static readonly Type[] Implementors =
+ {
+ typeof(UnpluggedController), // Order must match PceControllerType enum values
+ typeof(StandardController)
+ };
+
+ public PceControllerDeck(
+ PceControllerType controller1,
+ PceControllerType controller2,
+ PceControllerType controller3,
+ PceControllerType controller4,
+ PceControllerType controller5)
+ {
+ Port1 = (IPort)Activator.CreateInstance(Implementors[(int)controller1], 1);
+ Port2 = (IPort)Activator.CreateInstance(Implementors[(int)controller2], 2);
+ Port3 = (IPort)Activator.CreateInstance(Implementors[(int)controller3], 3);
+ Port4 = (IPort)Activator.CreateInstance(Implementors[(int)controller4], 4);
+ Port5 = (IPort)Activator.CreateInstance(Implementors[(int)controller5], 5);
+
+ Definition = new ControllerDefinition
+ {
+ Name = "PC Engine Controller",
+ BoolButtons = Port1.Definition.BoolButtons
+ .Concat(Port2.Definition.BoolButtons)
+ .Concat(Port3.Definition.BoolButtons)
+ .Concat(Port4.Definition.BoolButtons)
+ .Concat(Port5.Definition.BoolButtons)
+ .ToList()
+ };
+
+ Definition.FloatControls.AddRange(Port1.Definition.FloatControls);
+ Definition.FloatControls.AddRange(Port2.Definition.FloatControls);
+ Definition.FloatControls.AddRange(Port3.Definition.FloatControls);
+ Definition.FloatControls.AddRange(Port4.Definition.FloatControls);
+ Definition.FloatControls.AddRange(Port5.Definition.FloatControls);
+
+ Definition.FloatRanges.AddRange(Port1.Definition.FloatRanges);
+ Definition.FloatRanges.AddRange(Port2.Definition.FloatRanges);
+ Definition.FloatRanges.AddRange(Port3.Definition.FloatRanges);
+ Definition.FloatRanges.AddRange(Port4.Definition.FloatRanges);
+ Definition.FloatRanges.AddRange(Port5.Definition.FloatRanges);
+ }
+
+ private readonly IPort Port1;
+ private readonly IPort Port2;
+ private readonly IPort Port3;
+ private readonly IPort Port4;
+ private readonly IPort Port5;
+
+ public byte Read(int portNum, IController c, bool sel)
+ {
+ switch (portNum)
+ {
+ default:
+ throw new ArgumentException($"Invalid {nameof(portNum)}: {portNum}");
+ case 1:
+ return Port1.Read(c, sel);
+ case 2:
+ return Port2.Read(c, sel);
+ case 3:
+ return Port3.Read(c, sel);
+ case 4:
+ return Port4.Read(c, sel);
+ case 5:
+ return Port5.Read(c, sel);
+ }
+ }
+
+ public ControllerDefinition Definition { get; }
+ }
+
+ public interface IPort
+ {
+ byte Read(IController c, bool sel);
+
+ ControllerDefinition Definition { get; }
+
+ int PortNum { get; }
+ }
+
+ public class UnpluggedController : IPort
+ {
+ public UnpluggedController(int portNum)
+ {
+ PortNum = portNum;
+ Definition = new ControllerDefinition
+ {
+ BoolButtons = new List()
+ };
+ }
+
+ public byte Read(IController c, bool sel)
+ {
+ return 0x3F;
+ }
+
+ public ControllerDefinition Definition { get; }
+
+ public int PortNum { get; }
+ }
+
+ public class StandardController : IPort
+ {
+ public StandardController(int portNum)
+ {
+ PortNum = portNum;
+ Definition = new ControllerDefinition
+ {
+ BoolButtons = BaseDefinition
+ .Select(b => $"P{PortNum} " + b)
+ .ToList()
+ };
+ }
+
+ public ControllerDefinition Definition { get; }
+
+ public int PortNum { get; }
+
+ public byte Read(IController c, bool sel)
+ {
+ byte result = 0x3F;
+
+ if (sel == false)
+ {
+ if (c.IsPressed($"P{PortNum} B1")) result &= 0xFE;
+ if (c.IsPressed($"P{PortNum} B2")) result &= 0xFD;
+ if (c.IsPressed($"P{PortNum} Select")) result &= 0xFB;
+ if (c.IsPressed($"P{PortNum} Run")) result &= 0xF7;
+ }
+ else
+ {
+ if (c.IsPressed($"P{PortNum} Up")) { result &= 0xFE; }
+ if (c.IsPressed($"P{PortNum} Right")) { result &= 0xFD; }
+ if (c.IsPressed($"P{PortNum} Down")) { result &= 0xFB; }
+ if (c.IsPressed($"P{PortNum} Left")) { result &= 0xF7; }
+ }
+
+ return result;
+ }
+
+ private static readonly string[] BaseDefinition =
+ {
+ "Up", "Down", "Left", "Right", "Select", "Run", "B2", "B1"
+ };
+ }
+}