#!/usr/bin/env python3 """ vrserver.py -- the board behind a socket. This is the endpoint the DOSBox-X C012 I/O handler connects to (see CAPTURE.md). It speaks RAW link bytes: host -> board : the exact byte stream FLYK writes to port 0x151 (0x150 base) board -> host : reply bytes FLYK reads from port 0x150 It logs every reassembled message and reply to a capture file, so a real FLYK boot produces an annotated transcript we can diff against the source-derived spec and use to pin the open items (readpixels layout, bit30 receive semantics). Boot handling: on a link RESET marker (control byte from the handler), the board re-arms and, per the source handshake, queues 3 iserver transactions so FLYK's startup_handshake() proceeds into the framed HSP/860/init traffic. python vrserver.py # listen on 127.0.0.1:8620, log to capture.log python vrserver.py --selftest # loopback test: replay a synthetic boot+scene """ import socket, struct, sys, threading, time from vrboard import VirtualBoard, Assembler, pack_iserver, A HOST, PORT = '127.0.0.1', 8620 RESET_MARK = b'\x00RSET' # control frame the handler sends on a link reset strobe class BoardSession: def __init__(self, log): self.board = VirtualBoard() self.asm = Assembler() self.out = bytearray() # board->host bytes waiting to be read self.log = log self.seq = 0 def on_reset(self): self._emit("RESET (link re-armed; queuing 3 iserver handshake txns)") self.out.clear() # source: C-runtime does 3 iserver transactions before the host proceeds for _ in range(3): self.out += pack_iserver(2, b'\x20\x00\x00') # getenv-shaped stub self.board.log.clear() def feed(self, data): """Consume host->board bytes; return board->host bytes to send back.""" if not data: return b'' self.asm.feed(data) for msg in self.asm: self.board.log.clear() reply = self.board.handle(msg) for line in self.board.log: self._emit(" " + line) self._emit(f"MSG {msg!r}") if reply: self.out += reply act = struct.unpack_from(' (board queues 3 iserver) -> host would service them -> # then framed boot/init/scene traffic sess.on_reset() assert len(sess.out) > 0, "reset should queue handshake bytes" sess.out.clear() from vrboard import pack_vr stream = pack_vr(A.code860, b'\x00'*40) stream += pack_vr(A.init, b'video=svga|\n\x00') stream += pack_vr(A.create, struct.pack('host stream:", names) assert names == ['init', 'create', 'draw_scene'], names assert sess.board.frames == 1 log.close() print("OK: socket board reassembles chunked input, boots, and replies correctly.") print(" (see selftest_capture.log for the annotated transcript)") if __name__ == '__main__': if '--selftest' in sys.argv: _selftest() else: serve()