Files
CydandClaude Fable 5 de5a97d37d Workstream A prototype: play without the cockpit
Splits the control surface the game consumes from the RIO board into
RIOBase (8 virtuals + the five analog scalars); the serial RIO is now one
implementation of it. Adds two new ones:

- PadRIO (L4CONTROLS=PAD): in-process RIO speaking the full surface from
  an XInput controller + PC keyboard using vRIO's default profile (left
  stick/WASD = stick, triggers/Q,E = pedals, right stick Y/PgUp,PgDn =
  rate throttle that holds position, A/Space = trigger, B/R = reverse,
  dpad/arrows = hat, Start,Back/F1,F2 = config). Samples in GetNextEvent
  so button latency does not depend on the 15 s menu-time analog cadence;
  hot-plugs pads; L4PADFLIP=XY inverts stick axes; lamp commands land in
  lampState[] for the planned on-screen cockpit panel. The stock
  VTVRIOMapper/lamp/button path runs unchanged.

- PlasmaScreen (L4PLASMA=SCREEN): the 128x32 plasma glass as a desktop
  window in plasma orange (L4PLASMASCALE, default x4), rendering the same
  Video8BitBuffered surface the gauge system always drew; no COM port.

Verified in the sandbox with vRIO off and no serial devices: boots to a
running mission, controller hot-detected, plasma window drawing live game
content (score readout). BUILD.md 4 documents the desktop environ.ini and
bindings; roadmap updated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 13:13:37 -05:00

390 lines
7.7 KiB
C++

#pragma once
#include "l4pcspak.h"
#include "..\munga\notation.h"
#include "..\munga\average.h"
// These are purposely grouped as two parameters in one equate
// (See PCSPAK.HH).
// The standard PC COM ports ALWAYS use these combinations.
//#define RIO_COM1 PCSP_COM1
//#define RIO_COM2 PCSP_COM2
//#define RIO_COM3 PCSP_COM3
//#define RIO_COM4 PCSP_COM4
class FilterChannel SIGNATURED
{
public:
static const char *highName;
static const char *centerName;
static const char *lowName;
static const char *joystickXName;
static const char *joystickYName;
static const char *throttleName;
static const char *leftPedalName;
static const char *rightPedalName;
enum AlignMode { unaligned, normal };
enum PolarMode { unipolar, bipolar };
FilterChannel();
FilterChannel(
NotationFile *init_file,
const char *page_name,
int default_min, int default_max
);
FilterChannel(
NotationFile *init_file,
const char *page_name,
int default_min, int default_center, int default_max
);
~FilterChannel();
void
SetPolarity(PolarMode newPolarity);
void
SetDeadBand(Scalar amount_of_deadband);
virtual void
BeginAlignment();
virtual void
EndAlignment(NotationFile *init_file=NULL);
virtual Scalar
Update(int value);
Logical
TestInstance() const;
protected:
void
CalculateDeadBands();
const char *pageName;
PolarMode polarity;
AlignMode mode;
int previousValue, min, max, center;
int lowerRange, lowerDeadband;
int upperRange, upperDeadband;
Scalar deadbandScalar;
Logical valuesFromFile;
AverageOf<int> average;
};
class RIO;
class Ranger SIGNATURED
{
friend class RIO;
protected:
Ranger(
const char *page_name,
int default_min,
int default_max,
Scalar deadband_scalar
);
~Ranger();
void
ForceToZero();
void
SetDeadBand(Scalar amount_of_deadband);
Scalar
Update(int input);
Logical
TestInstance() const;
void
Statistics(NotationFile *stat_file);
const char
*pageName;
Logical
sampledInputFlag;
int
offset,
hardwareMinimum,
hardwareMaximum,
hardwareRange,
deadbandInteger,
highestInput,
lowestInput;
};
//########################################################################
//############################### RIOBase ################################
//########################################################################
//
// The control surface the game consumes from the cockpit RIO board,
// independent of transport. RIO (below) is the serial-hardware
// implementation; PadRIO (l4padrio.h) synthesizes the same surface from
// an XInput controller + the PC keyboard for cockpit-less play.
//
class RIOBase
{
public:
enum RIOStatusType {
BoardOk=0, BoardMissing=1, BoardBad=2,
LampBad=3,
RestartCount=4, AbandonCount=5, FullBufferCount=6
};
enum LampState{
solid=0, flashSlow=1, flashMed=2, flashFast=3,
state1Off=0x00, state1Dim=0x04, state1Bright=0x0C,
state2Off=0x00, state2Dim=0x10, state2Bright=0x30,
};
enum RIOEventType {
ButtonPressedEvent,
ButtonReleasedEvent,
KeyEvent,
AnalogEvent,
VersionEvent
};
struct RIOKeyPair
{
int Unit;
int Key;
};
struct RIOEvent
{
RIOEventType Type;
union
{
int Unit;
RIOKeyPair Keyboard;
}Data;
};
RIOBase()
{
TestModeActive = 0;
Throttle = (Scalar) 0;
LeftPedal = (Scalar) 0;
RightPedal = (Scalar) 0;
JoystickX = (Scalar) 0;
JoystickY = (Scalar) 0;
MajorRevision = 0;
MinorRevision = 0;
}
virtual ~RIOBase() {}
virtual Logical
TestInstance() const
{ return True; }
virtual Logical
GetNextEvent(RIOEvent *destinationPointer) = 0;
virtual void
ForceCenterJoystick() {}
virtual void
SetJoystickDeadBand(Scalar) {}
virtual void
SetThrottleDeadBand(Scalar) {}
virtual void
SetPedalsDeadBand(Scalar) {}
virtual void
RequestCheck() {}
virtual void
RequestVersion() {}
virtual void
RequestAnalogUpdate() {}
virtual void
GeneralReset() {}
virtual void
ResetThrottle() {}
virtual void
ResetLeftPedal() {}
virtual void
ResetRightPedal() {}
virtual void
ResetVerticalJoystick() {}
virtual void
ResetHorizontalJoystick() {}
virtual void
SetLamp(int lampNumber, int state) = 0;
int
TestModeActive;
Scalar
Throttle, LeftPedal, RightPedal, JoystickX, JoystickY;
int
MajorRevision, MinorRevision;
};
class RIO :
public RIOBase,
public PCSerialPacket
{
protected:
enum RIOCommand{
CheckRequest=0x80,
VersionRequest,
AnalogRequest,
ResetRequest,
LampRequest,
CheckReply,
VersionReply,
AnalogReply,
ButtonPressed,
ButtonReleased,
KeyPressed,
KeyReleased,
TestModeChange
};
public:
//Win32 Serial support: ADB 02/13/07
//RIO(Word port, Word intNum, Logical perform_tests = True);
RIO(const char* port, Logical perform_tests = True);
~RIO();
Logical
TestInstance() const;
Logical
GetNextEvent(RIOEvent *destinationPointer);
void
ForceCenterJoystick(),
SetJoystickDeadBand(Scalar dead_band),
SetThrottleDeadBand(Scalar dead_band),
SetPedalsDeadBand(Scalar dead_band);
void
RequestCheck(),
RequestVersion(),
RequestAnalogUpdate();
void
GeneralReset(),
ResetThrottle(),
ResetLeftPedal(),
ResetRightPedal(),
ResetVerticalJoystick(),
ResetHorizontalJoystick();
void
SetLamp(int lampNumber, int state);
void
TestCheckReply(int type, int location)
{
RIO::reply_check_string[1] = (Byte) (type & 0x7F);
RIO::reply_check_string[2] = (Byte) (location & 0x7F);
SendPacket((Byte *)reply_check_string);
}
void
TestVersionReply(int major, int minor)
{
RIO::reply_version_string[1] = (Byte) (major & 0x7F);
RIO::reply_version_string[2] = (Byte) (minor & 0x7F);
SendPacket((Byte *)reply_version_string);
}
void
TestAnalogReply()
{
SendPacket((Byte *)reply_analog_string);
}
void
TestButtonPressed(int button)
{
RIO::reply_button_press_string[1] = (Byte) (button & 0x7F);
SendPacket((Byte *)reply_button_press_string);
}
void
TestButtonReleased(int button)
{
RIO::reply_button_release_string[1] = (Byte) (button & 0x7F);
SendPacket((Byte *)reply_button_release_string);
}
void
TestKeyPressed(int board, int key)
{
RIO::reply_key_press_string[1] = (Byte) (board & 0x7F);
RIO::reply_key_press_string[2] = (Byte) (key & 0x7F);
SendPacket((Byte *)reply_key_press_string);
}
void
TestKeyReleased(int board, int key)
{
RIO::reply_key_release_string[1] = (Byte) (board & 0x7F);
RIO::reply_key_release_string[2] = (Byte) (key & 0x7F);
SendPacket((Byte *)reply_key_release_string);
}
void
TestEnterTestMode()
{SendPacket((Byte *)reply_test_enter_string);}
void
TestExitTestMode()
{SendPacket((Byte *)reply_test_exit_string);}
int
ReceiveQueueCount()
{ return PCSerialPacket::ReceiveQueueCount(); }
int
TransmitQueueCount()
{ return PCSerialPacket::TransmitQueueCount(); }
// TestModeActive, the five analog Scalars, and Major/MinorRevision
// now live in RIOBase.
int remoteRetryCount;
int remoteAbandonCount;
int remoteFullBufferCount;
int lineErrorCount;
int abandonCount;
int overrunCount;
int discardCount; // used by BeginAnalogCalibration()
protected:
void
OpenFailureFile();
void
CloseFailureFile();
void
CheckErrors();
Logical
operational;
Ranger
*leftPedalRanger, *rightPedalRanger;
Ranger
*throttleRanger;
Ranger
*joystickXRanger, *joystickYRanger;
NotationFile
*failureFile;
int
failureFileOpenCount;
static Byte reply_check_string[];
static Byte reply_version_string[];
static Byte reply_analog_string[];
static Byte reply_button_press_string[];
static Byte reply_button_release_string[];
static Byte reply_key_press_string[];
static Byte reply_key_release_string[];
static Byte reply_test_enter_string[];
static Byte reply_test_exit_string[];
};