Implement Rumble for Nyma

This commit is contained in:
CasualPokePlayer 2022-09-17 01:36:51 -07:00
parent de1e7eef69
commit de38781081
2 changed files with 25 additions and 4 deletions

View File

@ -27,6 +27,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
_nyma.SetInputDevices(_controllerAdapter.Devices);
ControllerDefinition = _controllerAdapter.Definition;
}
protected delegate void ControllerThunk(IController c, byte[] b);
protected class ControllerAdapter : IStatable
@ -244,14 +245,22 @@ namespace BizHawk.Emulation.Cores.Waterbox
var val = c.AxisValue(name);
b[byteStart] = (byte)val;
b[byteStart + 1] = (byte)(val >> 8);
});
});
break;
}
case InputType.Status:
// TODO: wire up statuses to something (not controller, of course)
break;
case InputType.Rumble:
// TODO: wtf do we do here???
ret.HapticsChannels.Add(name);
// this is a special case, we treat b here as output rather than input
// so these thunks are called after the frame has advanced
_rumblers.Add((c, b) =>
{
// TODO: not entirely sure this is correct...
var val = b[byteStart] | (b[byteStart + 1] << 8);
c.SetHapticChannelStrength(name, val << 7);
});
break;
default:
{
@ -279,7 +288,8 @@ namespace BizHawk.Emulation.Cores.Waterbox
private readonly byte[] _switchPreviousFrame;
private readonly List<Action<IController, byte[]>> _thunks = new List<Action<IController, byte[]>>();
private readonly List<ControllerThunk> _thunks = new();
private readonly List<ControllerThunk> _rumblers = new();
public void SetBits(IController src, byte[] dest)
{
@ -288,6 +298,12 @@ namespace BizHawk.Emulation.Cores.Waterbox
t(src, dest);
}
public void DoRumble(IController dest, byte[] src)
{
foreach (var r in _rumblers)
r(dest, src);
}
private const ulong MAGIC = 9569546739673486731;
public void SaveStateBinary(BinaryWriter writer)

View File

@ -224,9 +224,12 @@ namespace BizHawk.Emulation.Cores.Waterbox
private Task _frameThreadProcActive;
private IController _currentController;
protected override LibWaterboxCore.FrameInfo FrameAdvancePrep(IController controller, bool render, bool rendersound)
{
DriveLightOn = false;
_currentController = controller; // need to remember this for rumble
_controllerAdapter.SetBits(controller, _inputPortData);
_frameAdvanceInputLock = GCHandle.Alloc(_inputPortData, GCHandleType.Pinned);
LibNymaCore.BizhawkFlags flags = 0;
@ -251,7 +254,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
: LibNymaCore.CommandType.NONE,
InputPortData = (byte*)_frameAdvanceInputLock.AddrOfPinnedObject(),
FrontendTime = GetRtcTime(SettingsQuery("nyma.rtcrealtime") != "0"),
DiskIndex = (int)controller.AxisValue("Disk Index")
DiskIndex = controller.AxisValue("Disk Index")
};
if (_frameThreadStart != null)
{
@ -261,6 +264,8 @@ namespace BizHawk.Emulation.Cores.Waterbox
}
protected override void FrameAdvancePost()
{
_controllerAdapter.DoRumble(_currentController, _inputPortData);
if (_frameThreadProcActive != null)
{
// The nyma core unmanaged code should always release the threadproc to completion