diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj index 9be03c184d..07fb3f1ede 100644 --- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj +++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj @@ -470,6 +470,7 @@ + Gambatte.cs diff --git a/BizHawk.Emulation.Cores/Consoles/NEC/PCFX/Tst.cs b/BizHawk.Emulation.Cores/Consoles/NEC/PCFX/Tst.cs index f3d6182ff5..591a9184da 100644 --- a/BizHawk.Emulation.Cores/Consoles/NEC/PCFX/Tst.cs +++ b/BizHawk.Emulation.Cores/Consoles/NEC/PCFX/Tst.cs @@ -26,6 +26,7 @@ namespace BizHawk.Emulation.Cores.Consoles.NEC.PCFX private DiscSectorReader[] _diskReaders; private LibSaturnus.CDTOCCallback _cdTocCallback; private LibSaturnus.CDSectorCallback _cdSectorCallback; + private TstControllerDeck _controllerDeck; [CoreConstructor("PCFX")] public Tst(CoreComm comm, byte[] rom) @@ -34,7 +35,6 @@ namespace BizHawk.Emulation.Cores.Consoles.NEC.PCFX throw new InvalidOperationException("To load a PC-FX game, please load the CUE file and not the BIN file."); } - // MDFNGameInfo->fps = (uint32)((double)7159090.90909090 / 455 / 263 * 65536 * 256); public Tst(CoreComm comm, IEnumerable disks) :base(comm, new Configuration { @@ -74,6 +74,8 @@ namespace BizHawk.Emulation.Cores.Consoles.NEC.PCFX PostInit(); SetCdCallbacks(); + _controllerDeck = new TstControllerDeck(new[] { ControllerType.Gamepad, ControllerType.Gamepad }); + ControllerDefinition = _controllerDeck.Definition; } protected override void LoadStateBinaryInternal(BinaryReader reader) @@ -83,7 +85,13 @@ namespace BizHawk.Emulation.Cores.Consoles.NEC.PCFX protected override LibWaterboxCore.FrameInfo FrameAdvancePrep(IController controller, bool render, bool rendersound) { - return new LibTst.FrameInfo(); + DriveLightOn = false; + var ret = new LibTst.FrameInfo(); + var controls = _controllerDeck.GetData(controller); + ret.Port1Buttons = controls[0]; + ret.Port2Buttons = controls[1]; + ret.ConsoleButtons = controls[2]; + return ret; } private void CDTOCCallback(int disk, [In, Out]LibSaturnus.TOC t) diff --git a/BizHawk.Emulation.Cores/Consoles/NEC/PCFX/TstControllerDeck.cs b/BizHawk.Emulation.Cores/Consoles/NEC/PCFX/TstControllerDeck.cs new file mode 100644 index 0000000000..bacae959db --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/NEC/PCFX/TstControllerDeck.cs @@ -0,0 +1,171 @@ +using BizHawk.Emulation.Common; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BizHawk.Emulation.Cores.Consoles.NEC.PCFX +{ + public enum ControllerType + { + None = 0, + Gamepad = 1, + Mouse + } + + public class TstControllerDeck + { + private readonly ControlDefUnMerger[] _cdums; + private readonly IPortDevice[] _devices; + + private static readonly string[] _consoleButtons = + { + "Power", + "Reset", + "Previous Disk", + "Next Disk" + }; + + public TstControllerDeck(IEnumerable ports) + { + _devices = ports.Select(p => + { + switch (p) + { + case ControllerType.Gamepad: + return new Gamepad(); + case ControllerType.Mouse: + return new Mouse(); + default: + return new None(); + } + }).ToArray(); + + List tmp; + Definition = ControllerDefinitionMerger.GetMerged( + _devices.Select(d => d.Definition), + out tmp); + _cdums = tmp.ToArray(); + + Definition.Name = "PC-FX Controller"; + Definition.BoolButtons.AddRange(_consoleButtons); + } + + public uint[] GetData(IController c) + { + var ret = new uint[_devices.Length + 1]; + for (int i = 0; i < _devices.Length; i++) + ret[i] = _devices[i].GetData(_cdums[i].UnMerge(c)); + + uint console = 0; + uint val = 1; + foreach (var s in _consoleButtons) + { + if (c.IsPressed(s)) + console |= val; + val <<= 1; + } + ret[_devices.Length] = console; + return ret; + } + + public ControllerDefinition Definition { get; } + + private interface IPortDevice + { + ControllerDefinition Definition { get; } + uint GetData(IController c); + } + + private class None : IPortDevice + { + private static readonly ControllerDefinition _definition = new ControllerDefinition(); + + public ControllerDefinition Definition => _definition; + + public uint GetData(IController c) + { + return 0; + } + } + + private class Gamepad : IPortDevice + { + private static readonly ControllerDefinition _definition; + static Gamepad() + { + _definition = new ControllerDefinition + { + BoolButtons = Buttons + .Where(s => s != null) + .Select((s, i) => new { s, i }) + .OrderBy(a => ButtonOrders[a.i]) + .Select(a => a.s) + .ToList() + }; + } + + private static readonly string[] Buttons = + { + "0I", "0II", "0III", "0IV", "0V", "0VI", + "0Select", "0Run", + "0Up", "0Right", "0Down", "0Left", + "0Mode 1", null, "0Mode 2" + }; + + private static readonly int[] ButtonOrders = + { + 1, 1, 1, 1, 1, 1, + 1, 1, + 1, 1, 1, 1, + 1, 1 + }; + + public ControllerDefinition Definition => _definition; + + public uint GetData(IController c) + { + uint ret = 0; + uint val = 1; + foreach (var s in Buttons) + { + if (s != null && c.IsPressed(s)) + ret |= val; + val <<= 1; + } + return ret; + } + } + + private class Mouse : IPortDevice + { + private static readonly ControllerDefinition _definition = new ControllerDefinition + { + BoolButtons = { "0Mouse Left", "0Mouse Right" }, + FloatControls = { "0X", "0Y" }, + FloatRanges = + { + new[] { -127f, 0f, 127f }, + new[] { -127f, 0f, 127f } + } + }; + + public ControllerDefinition Definition => _definition; + + public uint GetData(IController c) + { + var dx = (byte)(int)c.GetFloat("0X"); + var dy = (byte)(int)c.GetFloat("0Y"); + uint ret = 0; + if (c.IsPressed("0Mouse Left")) + ret |= 0x10000; + if (c.IsPressed("0Mouse Right")) + ret |= 0x20000; + ret |= dx; + ret |= (uint)(dy << 8); + return ret; + } + } + } +} diff --git a/waterbox/pcfx/pcfx.cpp b/waterbox/pcfx/pcfx.cpp index 75d8307d67..6a96c95b70 100644 --- a/waterbox/pcfx/pcfx.cpp +++ b/waterbox/pcfx/pcfx.cpp @@ -708,7 +708,7 @@ EXPORT void FrameAdvance(MyFrameInfo& f) for (int i = 0; i < 2; i++) InputData[i] = f.Buttons[i]; - uint32_t ConsoleButtons = f.Buttons[3]; + uint32_t ConsoleButtons = f.Buttons[2]; int NewActiveDisk = ActiveDisk; #define ROSE(n) ((ConsoleButtons & 1 << (n)) > (PrevConsoleButtons & 1 << (n))) if (ROSE(0)) @@ -716,9 +716,9 @@ EXPORT void FrameAdvance(MyFrameInfo& f) if (ROSE(1)) PCFX_Reset(); if (ROSE(2)) - NewActiveDisk++; - if (ROSE(3)) NewActiveDisk--; + if (ROSE(3)) + NewActiveDisk++; #undef ROSE NewActiveDisk = std::max(NewActiveDisk, -1); NewActiveDisk = std::min(NewActiveDisk, CDInterfaces.size() - 1);