Files
CydandClaude Opus 4.8 094637b0a4 Editor: rework to the original Win32 RIO control-panel layout
Reworked the profile/mapping editor to mirror the original unfinished Win32
RIO driver's control-panel design (docs/Win32RIO, by FASA / Michel Lowrance)
instead of the flat config-sheet grid. The wallpaper region positions are a
VGA chroma-split display artifact, not the cockpit's logical shape.

- RioJoy.Core.Editing.CockpitPanel: the functional layout — five MFD clusters,
  four board columns (Throttle/Secondary/Screen/Joystick-Hat), an encoder-gauge
  strip, and the two later-added 4x4 keypads (Internal/External). Places every
  address 0x00-0x47 / 0x50-0x6F exactly once (unit-tested).
- Tray PanelView/PanelCanvas render the panel; ProfileEditorForm drives it.
  Buttons show label + assigned function (ButtonBinding.Describe -> CTL-N, JOY1,
  POV-U, Mse LB, RIO command names; unit-tested). Lamp shade is driven by the
  IsLit flag (not by whether a function is assigned); keypads are neutral blue
  with no Lit checkbox. Added an Unassign button next to Apply.
- Removed the superseded sheet-grid UI (SheetView/SheetCanvas); SheetLayout +
  config-sheet.csv stay as reference data.

docs/Win32RIO: the original driver (tasgame.sys, a 32-bit kernel HID minidriver
that opened the serial port, set baud/8N1/DTR, and spoke the *identical* RIO
protocol -- AnalogRequest/Reply, Button Pressed/Released, Check/Lamp/Reset/
Version -- validating our protocol port), oemsetup.inf, RemoteDriver.doc, and the
extracted control-panel / game-controllers mockups.

~236 xUnit tests green. PLAN.md updated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 19:48:14 -05:00

98 lines
3.5 KiB
C#

using RioJoy.Core.Mapping;
using Xunit;
namespace RioJoy.Core.Tests.Mapping;
public class ButtonBindingTests
{
[Theory]
[InlineData(RioRouteKind.Keyboard, 0x47, 0x0047)]
[InlineData(RioRouteKind.Joystick, 0x58, 0x1058)]
[InlineData(RioRouteKind.Hat, 0x01, 0x2001)]
[InlineData(RioRouteKind.Mouse, 0x10, 0x4010)]
[InlineData(RioRouteKind.RioCommand, 0x60, 0x7060)]
public void Create_PacksRoutingFlagsAndValue(RioRouteKind kind, byte value, ushort expected)
{
RioMapEntry e = RioMapEntry.Create(kind, value);
Assert.Equal(expected, e.Raw);
Assert.Equal(kind, e.Kind);
Assert.Equal(value, e.Value);
}
[Fact]
public void Create_SetsHighByteBits()
{
RioMapEntry e = RioMapEntry.Create(
RioRouteKind.Keyboard, 0x41, lit: true, shift: true, ctrl: true, alt: true, extended: true);
Assert.True(e.HasLamp);
Assert.True(e.Shift);
Assert.True(e.Ctrl);
Assert.True(e.Alt);
Assert.True(e.Extended);
Assert.Equal(0x41, e.Value);
// 0x8000|0x0800|0x0400|0x0200|0x0100|0x41
Assert.Equal(0x8F41, e.Raw);
}
[Theory]
[InlineData(RioRouteKind.Keyboard)]
[InlineData(RioRouteKind.Joystick)]
[InlineData(RioRouteKind.Hat)]
[InlineData(RioRouteKind.Mouse)]
[InlineData(RioRouteKind.RioCommand)]
public void Binding_RoundTripsThroughWord(RioRouteKind kind)
{
var b = new ButtonBinding
{
Kind = kind,
Value = 0x2A,
IsLit = true,
Shift = true,
Alt = true,
};
ushort word = b.ToWord();
ButtonBinding back = ButtonBinding.FromWord(word);
Assert.Equal(b.Kind, back.Kind);
Assert.Equal(b.Value, back.Value);
Assert.Equal(b.IsLit, back.IsLit);
Assert.Equal(b.Shift, back.Shift);
Assert.Equal(b.Ctrl, back.Ctrl);
Assert.Equal(b.Alt, back.Alt);
Assert.Equal(b.Extended, back.Extended);
Assert.Equal(word, back.ToWord());
}
[Fact]
public void Binding_FromWord_DecodesLegacyValue()
{
// 0x8F41 from the encode test -> lit keyboard 'A' with all modifiers.
ButtonBinding b = ButtonBinding.FromWord(0x8F41);
Assert.Equal(RioRouteKind.Keyboard, b.Kind);
Assert.Equal(0x41, b.Value);
Assert.True(b.IsLit && b.Shift && b.Ctrl && b.Alt && b.Extended);
}
[Fact]
public void Binding_Default_IsUnmapped()
{
Assert.True(new ButtonBinding().IsUnmapped);
Assert.False(new ButtonBinding { Value = 0x41 }.IsUnmapped);
}
[Fact]
public void Describe_FormatsEachKind()
{
Assert.Equal("", new ButtonBinding().Describe());
Assert.Equal("K", new ButtonBinding { Value = 0x4B }.Describe());
Assert.Equal("CTL-N", new ButtonBinding { Value = 0x4E, Ctrl = true }.Describe());
Assert.Equal("CTL-SFT-K", new ButtonBinding { Value = 0x4B, Ctrl = true, Shift = true }.Describe());
Assert.Equal("JOY1", new ButtonBinding { Kind = RioRouteKind.Joystick, Value = 1 }.Describe());
Assert.Equal("POV-U", new ButtonBinding { Kind = RioRouteKind.Hat, Value = (byte)(int)RioHat.Up }.Describe());
Assert.Equal("Mse LB", new ButtonBinding { Kind = RioRouteKind.Mouse, Value = (byte)MouseAction.LeftClick }.Describe());
Assert.Equal("ResetThrottle", new ButtonBinding { Kind = RioRouteKind.RioCommand, Value = (byte)RioCommandCode.ResetThrottle }.Describe());
}
}