Files
CydandClaude Opus 4.8 cc64d241c9 Phase 3: input mapping + output routing (RioJoy.Core.Mapping)
Port the iRIO decode and Press_V2/Release_V2 routing into testable C#:

- Mapping/: RioMapEntry decodes the 16-bit map word (lamp/mouse/hat/joy/extended/
  alt/ctrl/shift flags + value) and resolves the routing Kind by the legacy
  precedence (joy+hat+mouse => RIO command; none => keyboard; else joy>hat>mouse).
  RioAddress translates button/keypad events to table addresses (+0x50/+0x60
  keypad offsets); RioInputMap is the 112-entry per-profile table replacing the
  hard-coded iRIO[].
- InputRouter ports Press_V2/Release_V2: modifier press/release ordering,
  scancode keys, joystick buttons, POV hat, mouse move/click (deltas corrected
  per PROTOCOL.md), RIO-command dispatch, and lamp feedback (bright on press, dim
  on release; RIO commands carry none). InitializeLamps() dims all lamp entries.
- Output is split behind sink interfaces (IInputSink/IJoystickSink/ILampSink/
  IRioCommandSink) so routing is pure + unit-tested; Output/SendInputSink is the
  real SendInput keyboard/mouse adapter (scancode injection).
- tests: 30 new xUnit tests (84 total) for entry decode, address translation,
  and router routing/precedence/lamp/modifier ordering via a recording sink.

The joystick sink's real adapter (HID feeder -> RioGamepad via DeviceIoControl)
is blocked on the Phase 1 driver; routing already targets IJoystickSink.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 15:10:06 -05:00

45 lines
1.1 KiB
C#

using RioJoy.Core.Mapping;
using Xunit;
namespace RioJoy.Core.Tests.Mapping;
public class RioAddressTests
{
[Fact]
public void Button_MapsDirectly()
{
Assert.Equal(0x00, RioAddress.FromButton(0x00));
Assert.Equal(0x47, RioAddress.FromButton(0x47));
}
[Fact]
public void Button_RejectsOutOfRange()
{
Assert.Throws<ArgumentOutOfRangeException>(() => RioAddress.FromButton(0x48));
}
[Theory]
[InlineData(0, 0x00, 0x50)]
[InlineData(0, 0x0F, 0x5F)]
[InlineData(1, 0x00, 0x60)]
[InlineData(1, 0x0F, 0x6F)]
public void Keypad_AppliesOffset(byte pad, byte index, int expected)
{
Assert.Equal(expected, RioAddress.FromKeypad(pad, index));
}
[Fact]
public void Keypad_RejectsBadPadOrIndex()
{
Assert.Throws<ArgumentOutOfRangeException>(() => RioAddress.FromKeypad(2, 0));
Assert.Throws<ArgumentOutOfRangeException>(() => RioAddress.FromKeypad(0, 0x10));
}
[Fact]
public void TableSize_Is112()
{
Assert.Equal(112, RioAddress.TableSize);
Assert.Equal(0x6F, RioAddress.MaxAddress);
}
}