Ported from RP412: RIOBase split out of the serial RIO (L4RIO.h), rioPointer is RIOBase* (L4CTRL.h), PAD token -> new PadRIO() speaking the RIO surface from an XInput pad + keyboard (L4PADRIO/L4PADBINDINGS, vRIO bindings.txt grammar, hot-plug), KeyLight RGB mirror TU (BT412KEYLIGHT, /std:c++17 per-file). BT-side fixes PadRIO forced into the open: - Both keyboard input bridges (mech4.cpp, mechmppr.cpp BT_KEY_BRIDGE) stand down when a RIO device exists -- they overwrote the engine controls push every frame. M/X conveniences stay live. - Mapper attribute chain OFF BY ONE (latent real-pod bug): the DOS chain below MechControlsMapper carried two base attributes, WinTesla carries one, and AttributeIndexSet::Find is positional -- the .CTL stick mapping wrote throttlePosition. Pad slot + binary-locked enum; gotcha ledgered (reconstruction-gotchas #11). Verified: PAD throttle lever ramps + sticks, stick turns with the authentic speed-vs-turn clamp (61.5 -> 22.0 u/s), mech drives; keyboard fallback intact (BT_FORCE_THROTTLE harness). New diags: BT_CTRLMAP_LOG, BT_STICK_LOG. (Phase 2 of docs/BT412-ROADMAP.md) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
123 lines
3.1 KiB
C++
123 lines
3.1 KiB
C++
#pragma once
|
|
|
|
#include "l4rio.h"
|
|
#include "l4padbindings.h"
|
|
|
|
//########################################################################
|
|
//############################### PadRIO #################################
|
|
//########################################################################
|
|
//
|
|
// A cockpit-less RIO: synthesizes the RIOBase control surface from an
|
|
// XInput controller and the PC keyboard. Selected with L4CONTROLS=PAD.
|
|
//
|
|
// Every input is REBINDABLE: bindings.txt beside the exe (vRIO's
|
|
// profile format, written with the full default layout on first run)
|
|
// maps keys and pad controls to RIO button addresses (0x00-0x47), the
|
|
// pilot/external keypads (0x50-0x6F, delivered as arcade KeyEvents;
|
|
// unbound by default - the game never reads them), and the five axes
|
|
// with deflect/rate semantics. Defaults: vRIO's complete board layout
|
|
// (number+letter rows = MFD banks, F-keys = secondary columns) with
|
|
// flight on the numpad - 8/2/4/6 stick, 7/9 pedals, 0 trigger - and
|
|
// the modifiers: Shift/Ctrl throttle up/down, Alt reverse thrust,
|
|
// Space trigger, arrows hat.
|
|
//
|
|
// Set L4PADFLIP to a string containing 'X' and/or 'Y' to invert the
|
|
// stick axes on top of whatever the profile produces.
|
|
//
|
|
class PadRIO :
|
|
public RIOBase
|
|
{
|
|
public:
|
|
PadRIO();
|
|
~PadRIO();
|
|
|
|
Logical
|
|
TestInstance() const;
|
|
|
|
Logical
|
|
GetNextEvent(RIOEvent *destinationPointer);
|
|
|
|
void
|
|
RequestAnalogUpdate();
|
|
|
|
void
|
|
GeneralReset();
|
|
void
|
|
ResetThrottle();
|
|
|
|
void
|
|
SetLamp(int lampNumber, int state);
|
|
|
|
// Lamp state the game has commanded, indexed by RIO lamp number.
|
|
// The on-screen cockpit buttons read this to light themselves.
|
|
enum { lampCount = 64 };
|
|
unsigned char
|
|
lampState[lampCount];
|
|
|
|
//---------------------------------------------------------------
|
|
// On-screen cockpit buttons (MFDSplitView strips) press RIO units
|
|
// through these; they are no-ops when no PadRIO is active (e.g.
|
|
// real serial hardware selected).
|
|
//---------------------------------------------------------------
|
|
static void
|
|
SetScreenButton(int unit, Logical pressed);
|
|
static int
|
|
GetLampState(int unit);
|
|
static Logical
|
|
IsActive()
|
|
{ return activeInstance != NULL; }
|
|
|
|
protected:
|
|
void
|
|
PollInputs();
|
|
void
|
|
QueueEvent(const RIOEvent &an_event);
|
|
|
|
enum { queueSize = 64 };
|
|
enum { buttonUnits = 0x48 }; // through LastMappableButton
|
|
|
|
RIOEvent
|
|
eventQueue[queueSize];
|
|
int
|
|
queueHead, queueTail;
|
|
|
|
static PadRIO
|
|
*activeInstance;
|
|
|
|
// pressed state driven by the on-screen cockpit buttons
|
|
unsigned char
|
|
screenButton[0x48];
|
|
|
|
unsigned long
|
|
lastPollTick,
|
|
lastPadCheckTick;
|
|
int
|
|
padIndex; // connected XInput slot, -1 = none
|
|
Logical
|
|
padReported; // one-time connect/disconnect log flags
|
|
Logical
|
|
analogRequested;
|
|
|
|
unsigned char
|
|
buttonDown[buttonUnits];
|
|
|
|
// keypad pressed-state (0x50-0x6F), for KeyEvent edges
|
|
enum { keypadUnits = 0x20 };
|
|
unsigned char
|
|
keypadDown[keypadUnits];
|
|
|
|
PadBindingProfile
|
|
profile;
|
|
|
|
Scalar
|
|
throttleAccum;
|
|
Logical
|
|
invertX, invertY;
|
|
Logical
|
|
keyLightActive; // Dynamic Lighting keyboard mirror running
|
|
|
|
Scalar
|
|
sentThrottle, sentLeftPedal, sentRightPedal,
|
|
sentJoystickX, sentJoystickY;
|
|
};
|