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>
70 lines
2.4 KiB
C++
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
|