Files
riojoy/src/RioJoy.Core/Mapping/RioAddress.cs
T
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

52 lines
1.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
namespace RioJoy.Core.Mapping;
/// <summary>
/// Translates raw RIO events into an <c>iRIO</c> table address. The 72 digital
/// buttons map to <c>0x000x47</c> directly; keypad 0 is offset by <c>0x50</c>
/// and keypad 1 by <c>0x60</c> (port of <c>KeypadEvent</c>, riovjoy2.cpp#L1185);
/// see docs/PROTOCOL.md §5.
/// </summary>
public static class RioAddress
{
/// <summary>Number of digital button inputs (addresses 0x000x47).</summary>
public const int ButtonCount = 72;
/// <summary>Address offset added to keypad-0 key indices.</summary>
public const int Keypad0Base = 0x50;
/// <summary>Address offset added to keypad-1 key indices.</summary>
public const int Keypad1Base = 0x60;
/// <summary>Highest valid address (keypad 1, index 0x0F).</summary>
public const int MaxAddress = Keypad1Base + 0x0F; // 0x6F
/// <summary>Size of the <c>iRIO</c> table (addresses 0x00..0x6F inclusive).</summary>
public const int TableSize = MaxAddress + 1; // 112
/// <summary>Address for a digital button event (<paramref name="index"/> 0x000x47).</summary>
public static int FromButton(byte index)
{
if (index >= ButtonCount)
throw new ArgumentOutOfRangeException(
nameof(index), $"Button index must be 0..{ButtonCount - 1}.");
return index;
}
/// <summary>
/// Address for a keypad key event: <paramref name="pad"/> 0 or 1,
/// <paramref name="index"/> 0x000x0F. Mirrors the legacy offsets (+0x50 / +0x60).
/// </summary>
public static int FromKeypad(byte pad, byte index)
{
if (index > 0x0F)
throw new ArgumentOutOfRangeException(nameof(index), "Keypad index must be 0..0x0F.");
return pad switch
{
0 => Keypad0Base + index,
1 => Keypad1Base + index,
_ => throw new ArgumentOutOfRangeException(nameof(pad), "Keypad must be 0 or 1."),
};
}
}