BizHawk/BizHawk.Emulation.Cores/Consoles/PC Engine/PceControllerDeck.cs

163 lines
4.3 KiB
C#

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<string>()
};
}
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"
};
}
}