Files
TeslaRel410/emulator/vpx-device/serialnamedpipe.h
T
CydandClaude Opus 4.8 aadda7f9a5 Cockpit camera complete + namedpipe transport + 832x512 native res
Render bridge (live_bridge.py, vrview_gl.py):
- Hat glances render (left/right frame the canopy, hat-down = clean rear).
  Root bug was a stale _ckpt['fix'] key -> KeyError every glance frame ->
  render aborted (screen froze on hold, snapped back on release). The glance
  itself is the authentic eye-DCS action-0x1f reflush fp_cam already applies.
- Torso twist turret-true (root-axis yaw, zero parallax); lasers follow torso.
- Rear glance drops the canopy shell for a clean view (original-hardware
  behavior); mission-fade shroud 9fd hidden.
- Wireframe debug mode (VRVIEW_WIREFRAME / 'w' key), scene-pass scoped.
- Renderer output = 832x512, the dPL3 board's native framebuffer res.

DOSBox-X fork: namedpipe serial backend (serialnamedpipe.cpp/.h) for
vRIO/vPLASMA, replacing com0com; overlapped non-blocking I/O; typed frames
(0x00 data / 0x01 DTR+RTS). Tracked copies + apply steps in vpx-device.

Docs: COCKPIT-CAGE-NOTES (full glance/twist/rear forensics), XP-PORT-PLAN
(back-burnered), RIO-NOTES (namedpipe + keypad), pipe/egg conf variants.

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

96 lines
3.4 KiB
C++

/*
* VWE fork: serial-over-named-pipe backend (Windows only).
*
* Replaces com0com virtual COM pairs for the vRIO cockpit board and the
* vPLASMA score display: DOSBox is the pipe CLIENT with background retry;
* the peripheral app (vRIO / vPLASMA) is the pipe SERVER. An unconnected
* pipe behaves like an unplugged cable: the UART exists, modem-in lines
* (CTS/DSR/CD) are low, writes are discarded.
*
* Wire format (single duplex byte-mode pipe, typed frames, identical in
* both directions -- contract pinned with the vRIO session 2026-07-12):
* 0x00 <len:u8> <bytes> serial data, len >= 1 (batching allowed)
* 0x01 <lines:u8> sender's own OUTPUT lines: bit0 DTR, bit1 RTS;
* the receiver applies the null-modem cross
* (their DTR -> our DSR+CD, their RTS -> our CTS)
* On connect each side sends one 0x01 with its current state. An unknown
* frame type is a protocol bug: log + drop the connection, no resync.
*
* Conf: serial1=namedpipe pipe:vrio [rxpollus:100] [rxburst:16] [rxdelay:n]
* (pipe:<name> maps to \\.\pipe\<name>; a full \\... path also works;
* rx options have directserial semantics)
*/
#ifndef DOSBOX_SERIALNAMEDPIPE_H
#define DOSBOX_SERIALNAMEDPIPE_H
#include "dosbox.h"
#if defined(WIN32)
#include "serialport.h"
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <deque>
#include <string>
#include <vector>
class CSerialNamedPipe : public CSerial {
public:
CSerialNamedPipe(Bitu id, CommandLine* cmd);
virtual ~CSerialNamedPipe();
void updatePortConfig(uint16_t divider, uint8_t lcr);
void updateMSR();
void transmitByte(uint8_t val, bool first);
void setBreak(bool value);
void setRTSDTR(bool rts, bool dtr);
void setRTS(bool val);
void setDTR(bool val);
void handleUpperEvent(uint16_t type);
private:
void tryConnect();
void dropConnection(const char* why);
void pumpPipe(); // drain pipe -> parse frames -> rxq / line state
bool doReceive(); // deliver one rx byte to the UART if available
void queueSend(const uint8_t* data, DWORD len); // NEVER blocks
void kickTx(); // start the next overlapped write if idle
void pollTx(); // reap a completed / wedged overlapped write
void sendLineState(); // frame 0x01 with our current DTR/RTS
HANDLE pipe = INVALID_HANDLE_VALUE;
std::string pipename;
double next_retry_ms = 0.0; // PIC_FullIndex() of the next connect attempt
// ALL pipe I/O is overlapped: a blocking write here deadlocked the emu
// thread against a peer that also writes-first (both hellos, no reader).
OVERLAPPED tx_ov = {};
OVERLAPPED rx_ov = {};
bool tx_inflight = false;
double tx_wedge_ms = 0.0; // deadline for an unfinished write
std::vector<uint8_t> txq; // bytes waiting for the next write
std::vector<uint8_t> tx_pend; // buffer owned by the in-flight write
std::vector<uint8_t> inbuf; // partial frame reassembly
std::deque<uint8_t> rxq; // decoded serial bytes awaiting the UART
bool cur_dtr = false; // our output lines (mirrors MCR writes)
bool cur_rts = false;
// receive pacing, directserial semantics (VWE RIO low-latency knobs)
float rx_poll_ms = 1.0f;
float rx_burst_div = 1.0f;
Bitu rx_retry = 0;
Bitu rx_retry_max = 0;
Bitu rx_state = 0;
};
#endif // WIN32
#endif // DOSBOX_SERIALNAMEDPIPE_H