dsda: completely remake input system init

This commit is contained in:
feos 2025-05-22 22:34:26 +03:00
parent 498fabc576
commit eb94bd88b9
9 changed files with 141 additions and 340 deletions

View File

@ -197,7 +197,7 @@ namespace BizHawk.Client.Common
DSDA.DoomSyncSettings syncSettings = new() DSDA.DoomSyncSettings syncSettings = new()
{ {
InputFormat = DoomControllerTypes.Doom, InputFormat = DSDA.ControllerTypes.Doom,
CompatibilityLevel = compLevel, CompatibilityLevel = compLevel,
SkillLevel = skill, SkillLevel = skill,
InitialEpisode = episode, InitialEpisode = episode,
@ -226,15 +226,7 @@ namespace BizHawk.Client.Common
*/ */
Result.Movie.SyncSettingsJson = ConfigService.SaveWithType(syncSettings); Result.Movie.SyncSettingsJson = ConfigService.SaveWithType(syncSettings);
var doomController = new DoomControllerDeck( var controller = new SimpleController(DSDA.CreateControllerDefinition(syncSettings));
DoomControllerTypes.Doom,
syncSettings.Player1Present,
syncSettings.Player2Present,
syncSettings.Player3Present,
syncSettings.Player4Present,
turningResolution == DSDA.TurningResolution.Longtics);
var controller = new SimpleController(doomController.Definition);
controller.Definition.BuildMnemonicsCache(Result.Movie.SystemID); controller.Definition.BuildMnemonicsCache(Result.Movie.SystemID);
Result.Movie.LogKey = Bk2LogEntryGenerator.GenerateLogKey(controller.Definition); Result.Movie.LogKey = Bk2LogEntryGenerator.GenerateLogKey(controller.Definition);

View File

@ -18,7 +18,7 @@ namespace BizHawk.Client.Common
Result.Movie.SystemID = VSystemID.Raw.Doom; Result.Movie.SystemID = VSystemID.Raw.Doom;
DSDA.DoomSyncSettings syncSettings = new() DSDA.DoomSyncSettings syncSettings = new()
{ {
InputFormat = DoomControllerTypes.Heretic, InputFormat = DSDA.ControllerTypes.Heretic,
MultiplayerMode = DSDA.MultiplayerMode.Single_Coop, MultiplayerMode = DSDA.MultiplayerMode.Single_Coop,
MonstersRespawn = false, MonstersRespawn = false,
FastMonsters = false, FastMonsters = false,
@ -36,8 +36,7 @@ namespace BizHawk.Client.Common
}; };
Result.Movie.SyncSettingsJson = ConfigService.SaveWithType(syncSettings); Result.Movie.SyncSettingsJson = ConfigService.SaveWithType(syncSettings);
var hereticController = new HereticController(1, false); var controller = new SimpleController(DSDA.CreateControllerDefinition(syncSettings));
var controller = new SimpleController(hereticController.Definition);
controller.Definition.BuildMnemonicsCache(Result.Movie.SystemID); controller.Definition.BuildMnemonicsCache(Result.Movie.SystemID);
void ParsePlayer(string playerPfx) void ParsePlayer(string playerPfx)
{ {

View File

@ -18,7 +18,7 @@ namespace BizHawk.Client.Common
Result.Movie.SystemID = VSystemID.Raw.Doom; Result.Movie.SystemID = VSystemID.Raw.Doom;
DSDA.DoomSyncSettings syncSettings = new() DSDA.DoomSyncSettings syncSettings = new()
{ {
InputFormat = DoomControllerTypes.Hexen, InputFormat = DSDA.ControllerTypes.Hexen,
MultiplayerMode = DSDA.MultiplayerMode.Single_Coop, MultiplayerMode = DSDA.MultiplayerMode.Single_Coop,
MonstersRespawn = false, MonstersRespawn = false,
FastMonsters = false, FastMonsters = false,
@ -48,8 +48,7 @@ namespace BizHawk.Client.Common
_ = input[i++]; // player 8 class _ = input[i++]; // player 8 class
Result.Movie.SyncSettingsJson = ConfigService.SaveWithType(syncSettings); Result.Movie.SyncSettingsJson = ConfigService.SaveWithType(syncSettings);
var hexenController = new HexenController(1, false); var controller = new SimpleController(DSDA.CreateControllerDefinition(syncSettings));
var controller = new SimpleController(hexenController.Definition);
controller.Definition.BuildMnemonicsCache(Result.Movie.SystemID); controller.Definition.BuildMnemonicsCache(Result.Movie.SystemID);
void ParsePlayer(string playerPfx) void ParsePlayer(string playerPfx)
{ {

View File

@ -0,0 +1,106 @@
using System.Linq;
using BizHawk.Common;
using BizHawk.Common.CollectionExtensions;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Computers.Doom
{
public partial class DSDA
{
public static ControllerDefinition CreateControllerDefinition(DoomSyncSettings settings)
{
var controller = new ControllerDefinition($"{settings.InputFormat} Input Format");
var longtics = settings.TurningResolution == TurningResolution.Longtics;
int playersPresent = Convert.ToInt32(settings.Player1Present)
| Convert.ToInt32(settings.Player2Present) << 1
| Convert.ToInt32(settings.Player3Present) << 2
| Convert.ToInt32(settings.Player4Present) << 3;
for (int i = 0; i < 4; i++)
{
if ((playersPresent & (1 << i)) is not 0)
{
var port = i + 1;
controller
.AddAxis($"P{port} Run Speed", (-50).RangeTo(50), 0)
.AddAxis($"P{port} Strafing Speed", (-50).RangeTo(50), 0)
.AddAxis($"P{port} Turning Speed", (-128).RangeTo(127), 0);
// editing a short in tastudio would be a nightmare, so we split it:
// high byte represents shorttics mode and whole angle values
// low byte is fractional part only available with longtics
if (longtics)
{
controller.AddAxis($"P{port} Turning Speed Frac.", (-255).RangeTo(255), 0);
}
controller
.AddAxis($"P{port} Weapon Select", (0).RangeTo(7), 0)
.AddAxis($"P{port} Mouse Running", (-128).RangeTo(127), 0)
// current max raw mouse delta is 180
.AddAxis($"P{port} Mouse Turning", (longtics ? -180 : -128).RangeTo(longtics ? 180 : 127), 0);
if (settings.InputFormat is not ControllerTypes.Doom)
{
controller
.AddAxis($"P{port} Fly / Look", (-7).RangeTo(7), 0)
.AddAxis($"P{port} Use Artifact", (0).RangeTo(10), 0);
}
controller.BoolButtons.AddRange([
$"P{port} Fire",
$"P{port} Use",
$"P{port} Forward",
$"P{port} Backward",
$"P{port} Turn Left",
$"P{port} Turn Right",
$"P{port} Strafe Left",
$"P{port} Strafe Right",
$"P{port} Run",
$"P{port} Strafe",
$"P{port} Weapon Select 1",
$"P{port} Weapon Select 2",
$"P{port} Weapon Select 3",
$"P{port} Weapon Select 4",
]);
if (settings.InputFormat is ControllerTypes.Hexen)
{
controller.BoolButtons.AddRange([
$"P{port} Jump",
$"P{port} End Player",
]);
}
else
{
controller.BoolButtons.AddRange([
$"P{port} Weapon Select 5",
$"P{port} Weapon Select 6",
$"P{port} Weapon Select 7",
]);
}
}
}
controller.BoolButtons.AddRange([
"Change Gamma",
"Automap Toggle",
"Automap +",
"Automap -",
"Automap Full/Zoom",
"Automap Follow",
"Automap Up",
"Automap Down",
"Automap Right",
"Automap Left",
"Automap Grid",
"Automap Mark",
"Automap Clear Marks"
]);
return controller.MakeImmutable();
}
}
}

View File

@ -1,71 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using BizHawk.Common.CollectionExtensions;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Computers.Doom
{
public class DoomControllerDeck
{
public DoomControllerDeck(DoomControllerTypes controllerType, bool player1Present, bool player2Present, bool player3Present, bool player4Present, bool longtics)
{
Definition = new("Doom Demo LMP 1.9 Input Format") { };
if (player1Present) _port1 = ControllerCtors[controllerType](1, longtics);
if (player2Present) _port2 = ControllerCtors[controllerType](2, longtics);
if (player3Present) _port3 = ControllerCtors[controllerType](3, longtics);
if (player4Present) _port4 = ControllerCtors[controllerType](4, longtics);
if (player1Present) Definition.BoolButtons.AddRange(_port1.Definition.BoolButtons.ToList());
if (player2Present) Definition.BoolButtons.AddRange(_port2.Definition.BoolButtons.ToList());
if (player3Present) Definition.BoolButtons.AddRange(_port3.Definition.BoolButtons.ToList());
if (player4Present) Definition.BoolButtons.AddRange(_port4.Definition.BoolButtons.ToList());
if (player1Present) foreach (var kvp in _port1.Definition.Axes) Definition.Axes.Add(kvp);
if (player2Present) foreach (var kvp in _port2.Definition.Axes) Definition.Axes.Add(kvp);
if (player3Present) foreach (var kvp in _port3.Definition.Axes) Definition.Axes.Add(kvp);
if (player4Present) foreach (var kvp in _port4.Definition.Axes) Definition.Axes.Add(kvp);
Definition.BoolButtons.AddRange([
"Change Gamma",
"Automap Toggle",
"Automap +",
"Automap -",
"Automap Full/Zoom",
"Automap Follow",
"Automap Up",
"Automap Down",
"Automap Right",
"Automap Left",
"Automap Grid",
"Automap Mark",
"Automap Clear Marks"
]);
Definition.MakeImmutable();
}
private readonly IPort _port1;
private readonly IPort _port2;
private readonly IPort _port3;
private readonly IPort _port4;
private static IReadOnlyDictionary<DoomControllerTypes, Func<int, bool, IPort>> _controllerCtors;
public ControllerDefinition Definition { get; }
public int ReadButtons1(IController c) => _port1.ReadButtons(c);
public int ReadButtons2(IController c) => _port2.ReadButtons(c);
public int ReadButtons3(IController c) => _port3.ReadButtons(c);
public int ReadButtons4(IController c) => _port4.ReadButtons(c);
public int ReadAxis1(IController c, string axis) => _port1.ReadAxis(c, axis);
public int ReadAxis2(IController c, string axis) => _port2.ReadAxis(c, axis);
public int ReadAxis3(IController c, string axis) => _port3.ReadAxis(c, axis);
public int ReadAxis4(IController c, string axis) => _port4.ReadAxis(c, axis);
public static IReadOnlyDictionary<DoomControllerTypes, Func<int, bool, IPort>> ControllerCtors => _controllerCtors
??= new Dictionary<DoomControllerTypes, Func<int, bool, IPort>>
{
[DoomControllerTypes.Doom] = (portNum, longtics) => new DoomController(portNum, longtics),
[DoomControllerTypes.Heretic] = (portNum, longtics) => new HereticController(portNum, longtics),
[DoomControllerTypes.Hexen] = (portNum, longtics) => new HexenController(portNum, longtics),
};
}
}

View File

@ -6,7 +6,7 @@ namespace BizHawk.Emulation.Cores.Computers.Doom
public partial class DSDA : IEmulator public partial class DSDA : IEmulator
{ {
public IEmulatorServiceProvider ServiceProvider { get; } public IEmulatorServiceProvider ServiceProvider { get; }
public ControllerDefinition ControllerDefinition => _controllerDeck.Definition; public ControllerDefinition ControllerDefinition { get; private set; }
public int Frame { get; private set; } public int Frame { get; private set; }
public string SystemId => VSystemID.Raw.Doom; public string SystemId => VSystemID.Raw.Doom;
public bool DeterministicEmulation => true; public bool DeterministicEmulation => true;
@ -22,14 +22,6 @@ namespace BizHawk.Emulation.Cores.Computers.Doom
new LibDSDA.PackedPlayerInput() new LibDSDA.PackedPlayerInput()
]; ];
ReadPort[] buttonsReaders =
[
_controllerDeck.ReadButtons1,
_controllerDeck.ReadButtons2,
_controllerDeck.ReadButtons3,
_controllerDeck.ReadButtons4,
];
int commonButtons = 0; int commonButtons = 0;
int playersPresent = Convert.ToInt32(_syncSettings.Player1Present) int playersPresent = Convert.ToInt32(_syncSettings.Player1Present)
@ -149,19 +141,19 @@ namespace BizHawk.Emulation.Cores.Computers.Doom
} }
// bool buttons // bool buttons
var actionsBitfield = buttonsReaders[i](controller); if (controller.IsPressed($"P{port} Fire")) players[i].Buttons |= (1 << 0);
players[i].Buttons = actionsBitfield; if (controller.IsPressed($"P{port} Use")) players[i].Buttons |= (1 << 1);
// Raven Games // Raven Games
if (_syncSettings.InputFormat is DoomControllerTypes.Heretic or DoomControllerTypes.Hexen) if (_syncSettings.InputFormat is not ControllerTypes.Doom)
{ {
players[i].FlyLook = controller.AxisValue($"P{port} Fly / Look"); players[i].FlyLook = controller.AxisValue($"P{port} Fly / Look");
players[i].ArtifactUse = controller.AxisValue($"P{port} Use Artifact"); players[i].ArtifactUse = controller.AxisValue($"P{port} Use Artifact");
if (_syncSettings.InputFormat is DoomControllerTypes.Hexen) if (_syncSettings.InputFormat is ControllerTypes.Hexen)
{ {
players[i].Jump = (actionsBitfield & 0b01000) >> 3; players[i].Jump = Convert.ToInt32(controller.IsPressed($"P{port} Jump"));
players[i].EndPlayer = (actionsBitfield & 0b10000) >> 4; players[i].EndPlayer = Convert.ToInt32(controller.IsPressed($"P{port} End Player"));
} }
} }
} }
@ -175,16 +167,16 @@ namespace BizHawk.Emulation.Cores.Computers.Doom
HeadsUpMode = (int)_settings.HeadsUpMode, HeadsUpMode = (int)_settings.HeadsUpMode,
MapDetails = (int)_settings.MapDetails, MapDetails = (int)_settings.MapDetails,
MapOverlay = (int)_settings.MapOverlay, MapOverlay = (int)_settings.MapOverlay,
RenderVideo = renderVideo ? 1 : 0, RenderVideo = Convert.ToInt32(renderVideo),
RenderAudio = renderAudio ? 1 : 0, RenderAudio = Convert.ToInt32(renderAudio),
ShowMessages = _settings.ShowMessages ? 1 : 0, ShowMessages = Convert.ToInt32(_settings.ShowMessages),
ReportSecrets = _settings.ReportSecrets ? 1 : 0, ReportSecrets = Convert.ToInt32(_settings.ReportSecrets),
DsdaExHud = _settings.DsdaExHud ? 1 : 0, DsdaExHud = Convert.ToInt32(_settings.DsdaExHud),
DisplayCoordinates = _settings.DisplayCoordinates ? 1 : 0, DisplayCoordinates = Convert.ToInt32(_settings.DisplayCoordinates),
DisplayCommands = _settings.DisplayCommands ? 1 : 0, DisplayCommands = Convert.ToInt32(_settings.DisplayCommands),
MapTotals = _settings.MapTotals ? 1 : 0, MapTotals = Convert.ToInt32(_settings.MapTotals),
MapTime = _settings.MapTime ? 1 : 0, MapTime = Convert.ToInt32(_settings.MapTime),
MapCoordinates = _settings.MapCoordinates ? 1 : 0, MapCoordinates = Convert.ToInt32(_settings.MapCoordinates),
PlayerPointOfView = _settings.DisplayPlayer - 1, PlayerPointOfView = _settings.DisplayPlayer - 1,
}; };

View File

@ -9,6 +9,13 @@ namespace BizHawk.Emulation.Cores.Computers.Doom
{ {
public partial class DSDA : ISettable<DSDA.DoomSettings, DSDA.DoomSyncSettings> public partial class DSDA : ISettable<DSDA.DoomSettings, DSDA.DoomSyncSettings>
{ {
public enum ControllerTypes
{
Doom,
Heretic,
Hexen
}
public enum CompatibilityLevel : int public enum CompatibilityLevel : int
{ {
[Display(Name = "0 - Doom v1.2")] [Display(Name = "0 - Doom v1.2")]
@ -272,11 +279,11 @@ namespace BizHawk.Emulation.Cores.Computers.Doom
[CoreSettings] [CoreSettings]
public class DoomSyncSettings public class DoomSyncSettings
{ {
[DefaultValue(DoomControllerTypes.Doom)] [DefaultValue(ControllerTypes.Doom)]
[DisplayName("Input Format")] [DisplayName("Input Format")]
[Description("The format provided for the players' input.")] [Description("The format provided for the players' input.")]
[TypeConverter(typeof(DescribableEnumConverter))] [TypeConverter(typeof(DescribableEnumConverter))]
public DoomControllerTypes InputFormat { get; set; } public ControllerTypes InputFormat { get; set; }
[DisplayName("Player 1 Present")] [DisplayName("Player 1 Present")]
[Description("Specifies if player 1 is present")] [Description("Specifies if player 1 is present")]

View File

@ -29,14 +29,8 @@ namespace BizHawk.Emulation.Cores.Computers.Doom
ServiceProvider = ser; ServiceProvider = ser;
_finalSyncSettings = _syncSettings = lp.SyncSettings ?? new DoomSyncSettings(); _finalSyncSettings = _syncSettings = lp.SyncSettings ?? new DoomSyncSettings();
_settings = lp.Settings ?? new DoomSettings(); _settings = lp.Settings ?? new DoomSettings();
_controllerDeck = new DoomControllerDeck(
_syncSettings.InputFormat,
_syncSettings.Player1Present,
_syncSettings.Player2Present,
_syncSettings.Player3Present,
_syncSettings.Player4Present,
_syncSettings.TurningResolution == TurningResolution.Longtics);
_loadCallback = LoadCallback; _loadCallback = LoadCallback;
ControllerDefinition = CreateControllerDefinition(_syncSettings);
// Gathering information for the rest of the wads // Gathering information for the rest of the wads
_wadFiles = lp.Roms; _wadFiles = lp.Roms;
@ -219,7 +213,6 @@ namespace BizHawk.Emulation.Cores.Computers.Doom
private readonly WaterboxHost _elf; private readonly WaterboxHost _elf;
private readonly LibDSDA _core; private readonly LibDSDA _core;
private readonly LibDSDA.load_archive_cb _loadCallback; private readonly LibDSDA.load_archive_cb _loadCallback;
private readonly DoomControllerDeck _controllerDeck;
private readonly Point _nativeResolution = new(320, 200); private readonly Point _nativeResolution = new(320, 200);
private readonly int[] _runSpeeds = [ 25, 50 ]; private readonly int[] _runSpeeds = [ 25, 50 ];
private readonly int[] _strafeSpeeds = [ 24, 40 ]; private readonly int[] _strafeSpeeds = [ 24, 40 ];

View File

@ -1,216 +0,0 @@
using System.Linq;
using BizHawk.Common;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Computers.Doom
{
public enum DoomControllerTypes
{
Doom,
Heretic,
Hexen
}
public interface IPort
{
int ReadButtons(IController c);
int ReadAxis(IController c, string axis);
ControllerDefinition Definition { get; }
int PortNum { get; }
}
public class DoomController : IPort
{
public DoomController(int portNum, bool longtics)
{
PortNum = portNum;
_longtics = longtics;
Definition = new ControllerDefinition("Doom Input Format")
{
BoolButtons = _baseDefinition
.Select(b => $"P{PortNum} " + b)
.ToList()
}.AddAxis($"P{PortNum} Run Speed", (-50).RangeTo(50), 0)
.AddAxis($"P{PortNum} Strafing Speed", (-50).RangeTo(50), 0)
.AddAxis($"P{PortNum} Turning Speed", (-128).RangeTo(127), 0);
// editing a short in tastudio would be a nightmare, so we split it:
// high byte represents shorttics mode and whole angle values
// low byte is fractional part only available with longtics
if (longtics)
{
Definition.AddAxis($"P{PortNum} Turning Speed Frac.", (-255).RangeTo(255), 0);
}
Definition
.AddAxis($"P{PortNum} Weapon Select", (0).RangeTo(7), 0)
.AddAxis($"P{PortNum} Mouse Running", (-128).RangeTo(127), 0)
// current max raw mouse delta is 180
.AddAxis($"P{PortNum} Mouse Turning", (longtics ? -180 : -128).RangeTo(longtics ? 180 : 127), 0)
.MakeImmutable();
}
public int PortNum { get; }
public ControllerDefinition Definition { get; }
private bool _longtics;
private static readonly string[] _baseDefinition =
[
"Fire",
"Use",
"Forward",
"Backward",
"Turn Left",
"Turn Right",
"Strafe Left",
"Strafe Right",
"Run",
"Strafe",
"Weapon Select 1",
"Weapon Select 2",
"Weapon Select 3",
"Weapon Select 4",
"Weapon Select 5",
"Weapon Select 6",
"Weapon Select 7",
];
public int ReadButtons(IController c)
{
int result = 0;
if (c.IsPressed($"P{PortNum} Fire")) result |= (1 << 0);
if (c.IsPressed($"P{PortNum} Use")) result |= (1 << 1);
return result;
}
public int ReadAxis(IController c, string axis)
{
return c.AxisValue(axis);
}
}
public class HereticController : IPort
{
public HereticController(int portNum, bool longtics)
{
PortNum = portNum;
Definition = new ControllerDefinition("Heretic Input Format")
{
BoolButtons = _baseDefinition
.Select(b => $"P{PortNum} " + b)
.ToList()
}.AddAxis($"P{PortNum} Run Speed", (-50).RangeTo(50), 0)
.AddAxis($"P{PortNum} Strafing Speed", (-128).RangeTo(127), 0)
.AddAxis($"P{PortNum} Turning Speed", (-128).RangeTo(127), 0)
.AddAxis($"P{PortNum} Weapon Select", (0).RangeTo(7), 0)
.AddAxis($"P{PortNum} Mouse Running", (-128).RangeTo(127), 0)
.AddAxis($"P{PortNum} Mouse Turning", (-128).RangeTo(127), 0)
.AddAxis($"P{PortNum} Fly / Look", (-7).RangeTo(7), 0)
.AddAxis($"P{PortNum} Use Artifact", (0).RangeTo(10), 0)
.MakeImmutable();
}
public int PortNum { get; }
public ControllerDefinition Definition { get; }
private static readonly string[] _baseDefinition =
[
"Fire",
"Use",
"Forward",
"Backward",
"Turn Left",
"Turn Right",
"Strafe Left",
"Strafe Right",
"Run",
"Weapon Select 1",
"Weapon Select 2",
"Weapon Select 3",
"Weapon Select 4",
"Weapon Select 5",
"Weapon Select 6",
"Weapon Select 7",
];
public int ReadButtons(IController c)
{
int result = 0;
if (c.IsPressed($"P{PortNum} Fire")) { result |= 0b0001; }
if (c.IsPressed($"P{PortNum} Use")) { result |= 0b0010; }
return result;
}
public int ReadAxis(IController c, string axis)
{
return c.AxisValue(axis);
}
}
public class HexenController : IPort
{
public HexenController(int portNum, bool longtics)
{
PortNum = portNum;
Definition = new ControllerDefinition("Hexen Input Format")
{
BoolButtons = _baseDefinition
.Select(b => $"P{PortNum} " + b)
.ToList()
}.AddAxis($"P{PortNum} Run Speed", (-50).RangeTo(50), 0)
.AddAxis($"P{PortNum} Strafing Speed", (-128).RangeTo(127), 0)
.AddAxis($"P{PortNum} Turning Speed", (-128).RangeTo(127), 0)
.AddAxis($"P{PortNum} Weapon Select", (1).RangeTo(4), 0)
.AddAxis($"P{PortNum} Mouse Running", (-128).RangeTo(127), 0)
.AddAxis($"P{PortNum} Mouse Turning", (-128).RangeTo(127), 0)
.AddAxis($"P{PortNum} Fly / Look", (-7).RangeTo(7), 0)
.AddAxis($"P{PortNum} Use Artifact", (0).RangeTo(33), 0)
.MakeImmutable();
}
public int PortNum { get; }
public ControllerDefinition Definition { get; }
private static readonly string[] _baseDefinition =
[
"Fire",
"Use",
"Alt Weapon",
"Jump",
"End Player",
"Forward",
"Backward",
"Turn Left",
"Turn Right",
"Strafe Left",
"Strafe Right",
"Run",
"Weapon Select 1",
"Weapon Select 2",
"Weapon Select 3",
"Weapon Select 4"
];
public int ReadButtons(IController c)
{
int result = 0;
if (c.IsPressed($"P{PortNum} Fire")) { result |= 0b00001; }
if (c.IsPressed($"P{PortNum} Use")) { result |= 0b00010; }
if (c.IsPressed($"P{PortNum} Jump")) { result |= 0b01000; }
if (c.IsPressed($"P{PortNum} End Player")) { result |= 0b10000; }
return result;
}
public int ReadAxis(IController c, string axis)
{
return c.AxisValue(axis);
}
}
}