From c488cb526d740c889464cf0c4a7aa7121ea3d2bf Mon Sep 17 00:00:00 2001 From: Eremey Valetov Date: Wed, 11 Mar 2026 08:11:13 -0400 Subject: [PATCH] Update Sphinx docs with v0.14.0 roadmap and fix stale references Expand roadmap with detailed implementation plans for the next three features: MBF binary file compatibility (token-stream conversion at load/save boundary), hardware I/O simulator (portio.c with PIT/speaker/ CGA/joystick port emulation), and DRAW command fixes (M parsing bug, scale semantics, A rotation, TA/variable substitution). Remove hardware I/O from known limitations (moving to planned). Fix stale test counts (64 -> 66) and version string (0.11.0 -> 0.13.0) across docs. --- docs/architecture.md | 2 +- docs/getting-started.md | 2 +- docs/index.md | 2 +- docs/roadmap.md | 78 ++++++++++++++++++++++++++++++++++++----- 4 files changed, 72 insertions(+), 12 deletions(-) diff --git a/docs/architecture.md b/docs/architecture.md index 3ffee9e..b990b55 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -57,7 +57,7 @@ HAL writes straight to stdout. src/ — core interpreter (21 files) include/ — headers (13 files) platform/ — HAL backends (1 file) -tests/ — 64 automated test programs, 4 classic interactive programs, compat harness +tests/ — 66 automated test programs, 4 classic interactive programs, compat harness docs/ — Sphinx documentation ``` diff --git a/docs/getting-started.md b/docs/getting-started.md index 8023faa..13876cf 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -37,7 +37,7 @@ Running `./gwbasic` with no arguments launches the full-screen editor: ``` $ ./gwbasic -GW-BASIC 2026 0.11.0 +GW-BASIC 2026 0.13.0 (C) Eremey Valetov 2026. MIT License. Based on Microsoft GW-BASIC assembly source. Ok diff --git a/docs/index.md b/docs/index.md index 60e94f7..8c419ed 100644 --- a/docs/index.md +++ b/docs/index.md @@ -24,7 +24,7 @@ version is structured as modular C suitable for new feature development. - **Printer output** — `LPRINT`/`LLIST` to file or real hardware via `--lpt` - **Classic programs** — Hamurabi, Lunar Lander, Gunner, and Diamond from David Ahl's *BASIC Computer Games* (1978) run out of the box -- **64 test programs** with golden-file regression testing and DOSBox-X +- **66 test programs** with golden-file regression testing and DOSBox-X compatibility testing against real GWBASIC.EXE - **MIT License** diff --git a/docs/roadmap.md b/docs/roadmap.md index b5640f9..4520b51 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -8,15 +8,76 @@ But we've come this far, so why not? Likely approach: translate the token stream to C and lean on GCC/Clang for the heavy lifting. -## Planned Features +## Next Up (v0.14.0) -- **Hardware I/O simulator** — an optional emulation layer for `OUT`, `INP`, - `WAIT`, `MOTOR`, and friends. The idea is to provide a virtual PC peripheral - bus so retro programs that talk to the speaker, joystick port, or parallel - interface can do *something* useful instead of silently no-oping. Think of it - as a tiny museum exhibit for vintage BASIC hardware hacking. -- **MBF format support for binary LOAD** — convert Microsoft Binary Format - float constants when loading files saved by the original GWBASIC.EXE +### MBF Binary File Compatibility + +Make the binary tokenized file format fully compatible with original GWBASIC.EXE +files. Currently, float constants in the token stream are stored as IEEE 754; +the original uses Microsoft Binary Format (MBF). + +**Approach:** always store MBF on disk, always IEEE in memory. Convert at the +`load_binary()`/`save_binary()` boundary in `program_io.c`. A token-walking +function scans each line for `TOK_CONST_SNG` (0x1C, 4 bytes) and +`TOK_CONST_DBL` (0x1F, 8 bytes) and converts in-place using the existing +`gw_mbf_to_ieee_*` / `gw_ieee_to_mbf_*` routines. The walker must skip string +literals, REM/DATA regions, and multi-byte tokens to avoid false positives. + +This makes round-tripping lossless (MBF single has the same 24-bit mantissa as +IEEE single; MBF double's 56 bits cleanly contain IEEE double's 53 bits) and +enables loading authentic `.BAS` files from the 1980s. + +### Hardware I/O Simulator + +An optional emulation layer for `OUT`, `INP`, `WAIT`, `MOTOR`, and friends, +following the established `virmem.c` dispatch-by-address pattern. + +**New module:** `portio.c` / `portio.h` with `portio_inp(port)` / +`portio_out(port, value)` dispatch. + +**Priority ports:** + +| Port | Device | Emulation | +|------|--------|-----------| +| 0x42–0x43 | 8253 PIT channel 2 | Speaker frequency divisor (1193180 / divisor Hz) | +| 0x61 | PPI Port B | Speaker on/off (bits 0–1), routes to `snd_start_continuous()` / `snd_stop_continuous()` | +| 0x3D8 | CGA mode control | Mode register storage, feeds `gfx_init()` | +| 0x3D9 | CGA color select | Palette/background bits, feeds `gfx_palette_set()` | +| 0x201 | Game port | Joystick stub (returns 0xF0 = no buttons) | +| 0x3F8–0x3FE | COM1 serial | Minimal stub (LSR reports transmitter ready to prevent spin loops) | +| Default | — | Reads return 0xFF (floating bus), writes silently discarded | + +**Statement/function changes:** + +- `OUT port, value` → `portio_out(port, value)` +- `WAIT port, mask [, xor_mask]` → busy loop with `portio_inp()`, break check, timeout +- `MOTOR` → accept and silently ignore +- `INP(port)` → `portio_inp(port)` (currently returns 0) +- `STICK(n)` / `STRIG(n)` → joystick state from port 0x201 + +### DRAW Command Fixes + +The DRAW mini-language parser has three bugs and four missing features. + +**Bugs to fix:** + +1. **M command parsing** — the generic argument parser consumes digits that + belong to M's x-coordinate, so `DRAW "M100,50"` moves to (0, 50). Fix: + skip the generic parser when the command is M. +2. **S (scale) semantics** — scale is used as a default distance instead of a + multiplier. `DRAW "U"` moves 4 pixels instead of 1. Correct formula: + `dist = (has_arg ? arg : 1) * scale / 4`. +3. **A (90° rotation)** — recognized but no-op. Needs a rotation state + variable and direction vector transform for U/D/L/R/E/F/G/H. + +**Features to add:** + +- `TA n` — arbitrary rotation angle (degrees, −360 to 360); requires + multi-character command parsing and trigonometric direction vector rotation +- `=variable;` — numeric variable substitution in DRAW strings; requires + passing variable lookup capability into `gfx_draw()` +- `X subexpr;` — execute sub-string from a string variable (recursive parse) +- Scale applied to relative M coordinates ## IDE and Notebook Integration @@ -37,4 +98,3 @@ - String garbage collection not implemented (uses `malloc`/`free` instead) - Maximum 256 variables, 64 arrays, 16 FOR nesting, 24 GOSUB nesting, 16 WHILE nesting -- Hardware I/O (`OUT`, `INP`, `WAIT`, `COM`, `MOTOR`) not yet implemented