Files
TeslaRel410/emulator/vpx-device/serialplasma.h
T
CydandClaude Opus 4.8 844c11f792 emulator: in-fork plasma display (serial2=plasma) window in the explode layout
Bring the pod's 128x32 plasma readout in-fork, completing the self-contained
glass cockpit -- no vPLASMA process, no pipe.

- serialplasma.{cpp,h}: CSerialPlasma, a serial<n>=plasma backend that parses
  the game's ESC P graphics stream (L4PLASMA streams whole changed rows;
  receive-only, no replies) into a 128x32 1bpp framebuffer. Transcribed from
  vPLASMA's PlasmaProtocol + VPlasmaDevice (graphics path); the factory
  text-mode/fonts aren't used by the game and aren't rendered, but their escape
  operands are still consumed so the parser can't desync. Seam PLASMA_GetFrame()
  for the renderer.
- vpxlog.cpp: draw the framebuffer as an amber-on-black window in the explode
  layout, lazily created once a plasma port exists, parked centered under the
  lower-left MFD (VPX_PLASMA="x,y,w,h" overrides); WS_EX_NOACTIVATE so it can't
  steal DOSBox focus.
- Register SERIAL_TYPE_PLASMA (serialport.h/.cpp, dosbox.cpp -- documented in
  the vpx-device README step 3d, since those stock files live in the git-ignored
  src tree).
- Confs: serial2 in the _rio confs + deploy templates switches from
  namedpipe pipe:vplasma to the in-fork plasma.

Live-validated 2026-07-24. Real pods keep directserial realport:COM2; the
standalone vPLASMA app keeps namedpipe pipe:vplasma.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 12:48:07 -05:00

70 lines
2.4 KiB
C++

/*
* VWE fork: in-fork cockpit plasma display (serial<n>=plasma).
*
* The pod's 128x32 dot-matrix plasma readout on COM2. Like serial=rio, it's
* emulated natively inside DOSBox-X and rendered as a window (by vpxlog, in the
* explode layout) -- no external vPLASMA process, no pipe.
*
* The GAME (L4PLASMA.CPP) renders everything itself into a local 1bpp buffer
* and streams changed rows with a single ESC P graphics command; it is a
* receive-only display (no replies). This device implements exactly that path:
* parse the ESC command stream into a 128x32 1bpp framebuffer. The factory
* test tool's text mode (fonts/attributes/cursor) is NOT used by the game and
* is not rendered here -- its escape operands are still consumed so the parser
* never desyncs. Transcribed from the vPLASMA app (C:\VWE\vrio VPlasma.Core:
* PlasmaProtocol + VPlasmaDevice), graphics path only.
*
* Conf: serial2=plasma (real pods keep directserial realport:COM2;
* the vPLASMA app keeps namedpipe pipe:vplasma)
*/
#ifndef DOSBOX_SERIALPLASMA_H
#define DOSBOX_SERIALPLASMA_H
#include "dosbox.h"
#include "serialport.h"
#include <mutex>
// vpxlog reads this each frame to draw the plasma window: 128x32 1bpp packed,
// 16 bytes/row, MSB = leftmost pixel (512 bytes). Returns false when no
// serial<n>=plasma port is installed, so no plasma window is shown.
bool PLASMA_GetFrame(uint8_t out[512]);
class CSerialPlasma : public CSerial {
public:
CSerialPlasma(Bitu id, CommandLine* cmd);
virtual ~CSerialPlasma();
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);
void getFrame(uint8_t out[512]); // render-thread snapshot
private:
void feed(uint8_t b); // parse one wire byte (emu thread)
// parser state machine (VPlasmaDevice.Step)
enum { P_TEXT = 0, P_ESC, P_OPERAND, P_GHDR, P_GDATA };
int st = P_TEXT;
uint8_t hdr[5] = {}; // ESC P header: screen, y, xbyte, w, h
int hdrFill = 0;
int dataIdx = 0, dataLen = 0;
// 128x32 1bpp framebuffer, 16 bytes/row, MSB = leftmost pixel
std::mutex fbMx;
uint8_t fb[512] = {};
long graphicsRows = 0;
bool logv = false;
void logf(const char* fmt, ...);
};
#endif // DOSBOX_SERIALPLASMA_H