Commit Graph

76 Commits

Author SHA1 Message Date
Eremey Valetov
b3fdb02cc4 Update Sphinx roadmap: compiler 64/72 tests (89%) — only 5 remain 2026-03-29 19:18:43 -04:00
Eremey Valetov
ca6e216aad Compiler: fix last 4 valid failures — 64/72 tests (89%)
misc_stmts: fix ERDEV/IOCTL$ PRINT detection (peek past spaces for $
suffix), add IOCTL$() handler in emit_str_atom that consumes (#filenum).

random_access: use emit_delegate_stmt with read_back=true for FIELD/GET/
PUT/LSET/RSET so FIELD variables are synced back after GET.

error_handler: add division-by-zero check in compiled / operator (GCC
statement expression checks divisor==0 → gw_error(11)). Second error now
caught correctly.

get_put: fix CLS to call gfx_cls()+gfx_flush() when graphics active,
producing the expected Sixel frame after SCREEN mode changes.

64/72 tests pass (89%). Only 5 remain: 3 structural (CHAIN/COMMON/RUN
"file" unsupported) + 2 RNG-dependent (different random seed).
2026-03-29 19:17:56 -04:00
Eremey Valetov
cc69054430 Update Sphinx roadmap: compiler 60/72 tests (83%) 2026-03-29 18:48:58 -04:00
Eremey Valetov
f2a593975f Compiler: MID$ assign, CLEAR resize, ENVIRON delegate, PMAP/POINT — 60/72
MID$ assignment: fix text_ptr positioning (skip 0xFF+FUNC_MID, keep at
'(' for gw_stmt_mid_assign which does its own gw_chrget). Variable
read-back for modified strings. Unlocks mid_assign.bas.

CLEAR n: implement pool resize via strpool_reset(). Parse optional comma
prefix for CLEAR ,n syntax. Unlocks string_gc.bas.

ENVIRON statement: delegate to runtime instead of skip stub, so
ENVIRON "GWTEST=hello123" actually calls setenv(). Unlocks misc_stmts
ENVIRON$ function.

PMAP(coord, func): emit gfx_pmap() call. POINT(x,y): emit gfx_point().
PSET/PRESET: delegate. BSAVE/BLOAD/SAVE/LOAD: delegate.
FILES/SHELL/CHDIR/MKDIR/RMDIR/KILL/NAME: delegate.

60/72 tests pass (83%). 9 remaining failures.
2026-03-29 18:48:09 -04:00
Eremey Valetov
44f9609fe4 Update Sphinx roadmap: compiler 58/72 tests (81%) 2026-03-29 18:27:36 -04:00
Eremey Valetov
2c2a41b043 Compiler: graphics (PMAP/POINT/PSET), file delegation, BSAVE/BLOAD — 58/72
PMAP(coord, func): emit gfx_pmap() call instead of stub 0.
Unlocks view_window.

POINT(x, y): emit gfx_point() call. Unlocks draw_commands.

PSET/PRESET: delegate to runtime. Unlocks graphics_stubs.

BSAVE/BLOAD/SAVE/LOAD: delegate to runtime. Restores bsave_bload,
save_load.

FILES/SHELL/CHDIR/MKDIR/RMDIR/KILL/NAME: delegate to runtime via
emit_delegate_stmt instead of skip stubs. Restores filesystem.

PRINT # position fix: save print_tok before advance/skip_spaces.

Test script: normalize both sides for whitespace comparison, add
temp file cleanup between tests.

58/72 tests pass (81%). 11 remaining failures.
2026-03-29 18:26:51 -04:00
Eremey Valetov
3d23a096f7 Update Sphinx roadmap: compiler 50/72 tests (69%) 2026-03-29 17:52:25 -04:00
Eremey Valetov
73d2ece084 Compiler: file I/O via runtime delegation — 50/72 tests (69%)
Add emit_delegate_stmt() helper that embeds raw token bytes with full
variable sync (write before, read back after) and calls gw_exec_stmt().
Reusable pattern replaces ad-hoc token embedding in multiple handlers.

OPEN/CLOSE: delegate to runtime (handles all OPEN syntax variants).
PRINT #n: delegate with correct PRINT token position (was off-by-one).
WRITE #n: detect '#' and delegate (screen WRITE still inline).
INPUT/LINE INPUT: delegate with variable read-back.
LINE (INPUT or graphics): delegate.
LPRINT/LLIST: delegate.

50/72 tests pass. New: file_io, mbf_format, write_input.
2026-03-29 17:51:41 -04:00
Eremey Valetov
1dbb260c18 Update Sphinx roadmap: compiler 49/72 tests (68%) 2026-03-29 17:21:23 -04:00
Eremey Valetov
1756cb972c Compiler: CVI/MKI$, MID$ assign, ON ERROR, ERR/ERL, all-line labels — 49/72
CVI/CVS/CVD: handle 0xFD-prefix extended functions in emit_atom.
MKI$/MKS$/MKD$: handle in emit_str_atom. peek_expr_type detects FD
functions for correct PRINT type. Unlocks mkicvi.bas.

MID$ assignment: delegate to runtime via token embedding with variable
sync (both write and read-back for string variables).

ON ERROR GOTO / RESUME: set up gw_run_jmp in generated main() so
gw_error() can longjmp to the error handler. Create dummy
program_line_t so gw_find_line succeeds. Set gw.on_error_line when
ON ERROR GOTO is compiled. RESUME NEXT clears gw.in_error_handler
and dispatches to next line via line-number lookup.

ERR/ERL: emit gw_errno and gw.err_line_num for error pseudo-variables.

All-line labels: emit L_n labels for every program line (not just GOTO
targets) so RESUME NEXT can dispatch to any line.

49/72 tests pass (mkicvi new). error_handler and mid_assign partial.
2026-03-29 17:20:37 -04:00
Eremey Valetov
01a3cd24ba Update Sphinx roadmap: compiler 48/72 tests (67%) 2026-03-29 16:12:12 -04:00
Eremey Valetov
9d0eb579bc Compiler: string comparison, ON ERROR GOTO, graphics delegation — 48/72
String comparison: detect VT_STR left operand in relationals (>, <, =,
<=, >=, <>), re-emit as string atom, and use strcmp-based comparison
via GCC statement expression. Unlocks bubble_sort.

ON ERROR GOTO: add setjmp guard in generated main() that dispatches
to all GOTO target labels on error. Partial error_handler support.

Graphics/sound/file I/O extended statements: delegate to runtime via
token embedding with variable sync (same technique as PRINT USING and
DEF FN). Includes CIRCLE, DRAW, PAINT, PLAY, VIEW, WINDOW, PALETTE,
FIELD, LSET, RSET, PUT, GET. Fixed FE-prefix position tracking.

FRE("") GC: sync string variables to interpreter table before GC so
the collector can find live strings in compiled programs.

Division semantics: / always float (cast to double).

48/72 tests pass. New: bubble_sort, invoice. play_music/play_scale
restored after FE-prefix fix.
2026-03-29 16:11:21 -04:00
Eremey Valetov
5546ba42fe Update Sphinx roadmap: compiler 46/72 tests pass (64%) 2026-03-29 15:43:14 -04:00
Eremey Valetov
e1c0b91522 Compiler: string concat, division semantics, PRINT USING null bytes — 46/72
String concatenation: refactored emit_str_expr to use emit_str_atom +
concat loop. Self-referencing assignment A$ = A$ + B$ evaluates RHS
to temp before freeing old value.

Division semantics: GW-BASIC / always produces float (cast both operands
to double). Integer division is only for \ operator.

PRINT USING null-byte fix: token scanner now skips over float/double
constants (which may contain 0x00 bytes) instead of stopping on them.
Uses program_line_t.len for bounds instead of null termination.

FRE(): call strpool_gc() via comma expression for accurate reporting.
STICK(): return 128 (center). EOF/LOC/LOF function stubs.

46/72 tests pass. New: portio, print_using, print_using_edge,
monte_carlo (partial), string_gc, plus retained caesar_cipher,
roman_numerals.
2026-03-29 15:42:27 -04:00
Eremey Valetov
70e5fdbba8 Update Sphinx roadmap: compiler 43/72 tests pass 2026-03-29 15:19:57 -04:00
Eremey Valetov
6f81e769d5 Compiler: string concatenation, READ arrays, array assign — 43/72 tests
String concatenation: refactor emit_str_expr into emit_str_atom + concat
loop. S$ = S$ + R$(I) now correctly accumulates via gw_str_concat.
String assignment order fix: evaluate RHS to temp before freeing old
value, so self-referencing A$ = A$ + B$ reads A$ before clearing it.

READ into array elements: subscript parsing with multi-dim support.

Array assignment: don't zero element before RHS evaluation (fixes
C(I,J) = C(I,J) + A(I,K)*B(K,J) self-referencing pattern).

PRINT USING colon-in-string: skip quoted strings when scanning for
statement-end colon.

43/72 tests pass. New: caesar_cipher, roman_numerals.
2026-03-29 15:19:15 -04:00
Eremey Valetov
8a058b0664 Update Sphinx roadmap: compiler 41/72 tests pass 2026-03-29 14:53:42 -04:00
Eremey Valetov
1dcc39f45b Compiler: READ arrays, PRINT USING colon fix, array assign fix — 41/72
READ into array elements: parse subscripts after variable name in READ
handler, call gwrt_array_elem + gwrt_data_read. Unlocks matrix_mult,
roman_numerals (partial).

PRINT USING colon-in-string: scan past quoted strings when finding
statement-end colon for token embedding. Fixes truncated format strings
like "Pi estimate: #.####".

Array element assignment: don't zero element before RHS evaluation.
Previous code did `*_elem = {.type=4}` which zeroed fval before
reading C(I,J) in `C(I,J) = C(I,J) + A(I,K)*B(K,J)`, making
self-referencing assignments always read 0.

DEF FN call fix: skip past TOK_FN byte before calling gw_eval_fn_call.

DEFINT pre-scan: analysis pass processes DEFINT/DEFSNG/DEFDBL/DEFSTR
before variable type resolution.

Integer assignment rounding: use gw_cint() (rint) instead of (int16_t)
C truncation.

41/72 tests pass. 0 compile errors.
New: hundred_doors, matrix_mult, pascal_triangle, stats_calc.
2026-03-29 14:53:02 -04:00
Eremey Valetov
e6a6bddb26 Update Sphinx roadmap: compiler 37/72 tests, DEF FN, DEFINT, rounding 2026-03-29 14:29:25 -04:00
Eremey Valetov
1858ad4b0c Compiler: DEF FN, DEFINT, STRING$("c"), gw_cint rounding — 37/72 tests
DEF FN: embed definition tokens and call gw_exec_stmt() at runtime.
FN calls: embed call tokens, sync variables, call gw_eval_fn_call().
Unlocks def_fn.bas, def_types.bas, stats_calc (partial).

DEFINT/DEFSNG/DEFDBL/DEFSTR: pre-scan pass in analysis.c sets the
def_type table before variable type resolution. Integer variables now
correctly use gw_cint() rounding instead of C truncation (7.9 → 8,
not 7). Unlocks variables.bas, mult_table.bas.

STRING$(n, "c"): handle string second argument by extracting the first
character's ASCII code at compile time. Unlocks diamond.bas.

Extended expressions (FE-prefix): TIMER, DATE$, TIME$, ENVIRON$, ERDEV$
handled in both emit_atom and emit_str_expr.

37/72 tests pass. 0 compile errors. 32 output mismatches.
2026-03-29 14:28:28 -04:00
Eremey Valetov
12c4ee7cbb Update Sphinx roadmap: compiler has zero compile errors, 32/72 tests pass 2026-03-29 14:05:36 -04:00
Eremey Valetov
6b63f14b8c Compiler: zero compile errors — all 72 programs compile, 32 pass
Fix last 2 compile errors:
- SWAP with array elements: parse subscripts via emit_to_buf, use
  gwrt_array_elem pointers for both operands
- ENVIRON$/DATE$/TIME$ in expressions: handle 0xFE-prefix tokens in
  both emit_atom (numeric) and emit_str_expr (string) contexts, with
  proper string detection in PRINT

Other fixes:
- RND(n): discard argument via buffer (don't emit inline)
- Float 0.0f: emit "0.0f" not "0f"
- MID$ 3-argument: proper optional length parameter
- FOR scope: static limit/step (no {} blocks)
- RESUME/RESUME NEXT: proper statement handler
- ON TIMER/KEY/COM: skip event traps
- MID$ assignment: skip handler
- ERROR statement: emit gw_error()
- TIMER as expression: emit time() call
- PMAP/ERDEV as expressions: stub values

32/72 tests pass. 0 compile errors. 37 output mismatches. 3 skipped.
2026-03-29 14:04:56 -04:00
Eremey Valetov
cc7c27be27 Update Sphinx roadmap with compiler progress (32/72 tests, 2 compile errors) 2026-03-29 13:32:06 -04:00
Eremey Valetov
0e0052f9cf Compiler: fix 16 of 18 compile errors — 32/72 tests passing
Fixes:
- Include graphics.h/virmem.h in gwrt.h (5 programs: draw_commands,
  get_put, graphics_stubs, peek_gfx, view_window)
- RND(n): discard argument to buffer instead of emitting it inline
- Float constant 0: emit "0.0f" not "0f" (invalid C suffix)
- MID$ function: proper 3-argument emission with optional length
- FOR/NEXT: use static variables instead of block scope for limit/step
  (fixes FOR inside IF/THEN and unmatched brace issues)
- RESUME/RESUME NEXT: handle as statements (not misparse as FOR/NEXT)
- ON TIMER/KEY/COM: skip event trap setup (not misparse as ON n GOTO)
- MID$ assignment: recognize and skip (don't misparse as variable)
- ERROR statement: emit gw_error() call
- ERASE: stub handler

Only 2 compile errors remain: bubble_sort (SWAP with arrays),
misc_stmts (ENVIRON$ variable name clash).

32 of 72 tests pass. New: datetime, luhn, peek_poke, error_handler,
on_timer, timer_stop, monte_carlo, number_guess.
2026-03-29 13:31:17 -04:00
Eremey Valetov
4f4a8df412 Update Sphinx roadmap with compiler progress (27/72 tests) 2026-03-29 12:17:47 -04:00
Eremey Valetov
c3319a59c7 Compiler: PRINT USING, STRING$, INSTR, combined relationals — 27/72 tests
PRINT USING: embed token bytes in generated C and call gw_print_using()
at runtime. Variable values synced to interpreter table before the call
so gw_eval() can resolve them. Unlocks fibonacci, temp_table, calendar.

STRING$ (single-byte token 0xD4): handle in emit_str_expr and PRINT
string detection. Emits gw_fn_strings() call.

INSTR (single-byte token 0xD6): handle in emit_atom with start position
detection. Emits gw_fn_instr() call.

PRINT USING token skip fix: skip past TOK_USING before embedding bytes
(gw_print_using expects text_ptr after USING, not at it).

27 of 72 tests now pass. New: fibonacci, calendar, temp_table.
2026-03-29 12:17:06 -04:00
Eremey Valetov
948a75e70a Update Sphinx roadmap with compiler progress (23/72 tests) 2026-03-29 11:42:11 -04:00
Eremey Valetov
3b6f8fdc80 Compiler: fix array names, combined relationals, expression type tracking
Array name emission: use emit_name_str() to avoid null bytes in C string
literals when variable name has only one significant character.

Combined relationals: handle <=, >=, <> token pairs (TOK_LT+TOK_EQ etc.)
in the precedence climber. Previously these emitted "unknown tok 0xe5"
which broke WHILE X <= 10 and similar conditions.

Expression type tracking: peek_expr_type() determines VT_INT/VT_SNG/VT_DBL
from the leading token in PRINT expressions. PRINT now emits the correct
gw_value_t type for proper number formatting (single vs double precision).

23 of 72 tests now pass (up from 19). New: arrays, hailstone, while_wend,
prime_sieve, leibniz.
2026-03-29 11:41:39 -04:00
Eremey Valetov
2c9dc85b64 Update Sphinx roadmap with compiler progress (19/72 tests, arrays) 2026-03-29 10:41:37 -04:00
Eremey Valetov
7ff24ae85e Compiler: add array support, fix number format, OPEN variable clash
Arrays: DIM creates arrays via gwrt_dim() runtime call. Array element
read/write uses gwrt_array_elem() with buffered subscript expressions
(open_memstream) to correctly determine dimension count. Auto-DIM with
default size 10 for undeclared arrays.

Number formatting: PRINT now uses gw_print_value() (same as interpreter)
instead of gwrt_print_sng(), producing correct type-specific output.

OPEN fix: analysis pass skips OPEN statement arguments to avoid
misidentifying OUTPUT/INPUT/APPEND as variable names.

OPEN/CLOSE/INPUT: emit skip stubs (file I/O compilation is Phase 3).

19 of 72 tests now pass (up from 17). New: hanoi, text_adventure.
2026-03-29 10:41:02 -04:00
Eremey Valetov
248dfaae11 Update Sphinx roadmap with compiler Phase 2 progress (17/72 tests) 2026-03-29 10:23:10 -04:00
Eremey Valetov
58c6d8c99d Compiler Phase 2: WHILE/WEND, ON GOTO/GOSUB, MOD/IDIV/POW, statements
Add WHILE/WEND, ON n GOTO/GOSUB, ON ERROR GOTO, DIM (stub), SWAP,
POKE, DEF SEG, RANDOMIZE, COLOR, LOCATE, SCREEN, WIDTH, KEY, WRITE,
OPTION BASE, DEFINT/DEFSNG/DEFDBL/DEFSTR, TRON/TROFF.

Fix MOD/IDIV/POW operators: buffer left operand via open_memstream so
both sides can be properly cast (MOD/IDIV → int16_t, POW → pow()).
Previously MOD on float operands was a C compile error.

Handle all extended statement tokens (0xFE prefix): graphics, sound,
file I/O, view/window, environ, timer — either with real codegen or
graceful skip.

17 of 72 tests now pass (up from 15). 26 compile errors (down from 30).
2026-03-29 10:22:34 -04:00
Eremey Valetov
e535250f6c Fix compiler QA round 2: nested FOR/NEXT, remove unused code, clean warnings
- FOR/NEXT: use a FOR stack to match NEXT variables to their corresponding
  FOR labels, fixing nested loops (e.g., FOR I...FOR J...NEXT J...NEXT I)
- Remove unused emit_int_expr function
- Build now zero warnings across all targets
- Compiler passes 15 of 72 test programs (Phase 1 target: ~30)
2026-03-29 10:03:46 -04:00
Eremey Valetov
4dc255118a Fix compiler QA: misleading indentation, DATA escaping, NEXT safety, bounds
- codegen.c: refactor one-liner function cases to proper multi-line blocks,
  eliminating all -Wmisleading-indentation warnings
- codegen.c: escape quotes and backslashes in DATA pool string literals
- codegen.c: guard NEXT against for_label_counter=0 (NEXT without FOR)
- codegen.c: remove unused functions (emit_expr, read_sng, read_dbl)
- analysis.c: add bounds check on data_line_map writes
- Build now produces zero warnings across all three targets
2026-03-29 09:38:15 -04:00
Eremey Valetov
22206c012d Update Sphinx docs with AOT compiler Phase 1 2026-03-29 07:01:03 -04:00
Eremey Valetov
d3b57d9f3b Implement ahead-of-time compiler (Phase 1): BASIC to C via token stream
New tool gwbasic-compile translates tokenized .bas programs to C source,
which gcc compiles into native executables linked against libgwrt.a (the
interpreter's runtime modules minus the execution loop).

Pipeline: .bas → gw_crunch() → analysis pass (line table, variable census,
GOTO targets, DATA collection) → C codegen → gcc → native executable.

Phase 1 supports: PRINT, LET, IF/THEN/ELSE, GOTO, GOSUB/RETURN, FOR/NEXT,
END/STOP/SYSTEM, REM, DATA/READ/RESTORE, CLS, arithmetic/relational/logical
operators, core math functions (SIN, COS, SQR, ABS, etc.), string functions
(LEFT$, RIGHT$, MID$, CHR$, ASC, VAL, STR$, LEN, etc.), string concatenation.

All control flow uses goto/labels (no C for/while) so GOTO into loops works.
GOSUB uses a return-label stack with switch dispatch.
2026-03-29 06:59:42 -04:00
Eremey Valetov
eaa1166d8c Fix QA findings: FRE GC safety, WAIT mask=0, ENVIRON leak, sentinel collision
- FRE(): remove strpool_gc() call during expression evaluation — temporaries
  on the C stack would become dangling pointers after compaction
- WAIT: reject mask=0 (would infinite-loop since AND 0 is always 0)
- ENVIRON: use setenv()+free() instead of putenv() to avoid memory leak
  and dangling pointer if pool is compacted
- portio: add bounds check to com1_inp() (com1_out already had one)
- kernel: use CHR$(1) sentinel prefix to avoid collision with user output
- kernel: fix INPUT prompt rfind() edge case when no newline in buffer
- eval.c: enlarge DATE$ format buffer to silence -Wformat-truncation
2026-03-29 06:15:16 -04:00
Eremey Valetov
a510154405 Update Sphinx docs with Jupyter kernel enhancements (Sixel, INPUT, lexer) 2026-03-29 06:04:31 -04:00
Eremey Valetov
ba655fedbb Add inline Sixel graphics, INPUT stdin support, Pygments lexer to kernel
Sixel graphics: pure-Python decoder extracts ESC P...ESC \ sequences from
the output stream, renders RGBA pixels, and encodes as PNG for inline
display in the notebook. No external dependencies (no PIL, no Ghostscript).

INPUT support: when gwbasic prints "? " (INPUT prompt), the kernel uses
the Jupyter stdin protocol (raw_input) to request input from the user and
feeds the response back to the subprocess.

Pygments lexer (basic_lexer.py): GW-BASIC syntax highlighting with line
numbers, keywords, builtins, string/number literals, and comments.
Registered as a Pygments entry point and referenced in kernel language_info.

Test suite expanded from 10 to 14 tests (Sixel decode, PNG encode, inline
graphics integration, lexer tokenization).
2026-03-29 06:03:50 -04:00
Eremey Valetov
9ff3aaf104 Update Sphinx docs with Jupyter kernel, move to IDE integration next 2026-03-29 05:52:49 -04:00
Eremey Valetov
3e8aaa298b Implement Jupyter kernel for GW-BASIC 2026
Persistent subprocess model: gwbasic reads BASIC from stdin and writes
output to stdout in piped mode (no banner, no prompts, unbuffered).
Sentinel protocol (PRINT "<<<GWDONE>>>") delimits output per cell.

Features: state persistence across cells, error detection and reporting,
tab completion for GW-BASIC keywords, %reset/%timeout/%new magic
commands, Ctrl+C forwarding, automatic process restart.

Includes setup.py for pip install, kernel.json spec, install script,
and 10-test smoke suite (all passing).
2026-03-29 05:51:37 -04:00
Eremey Valetov
65f99da932 Update Sphinx docs with string pool GC, remove string GC from limitations 2026-03-29 04:58:29 -04:00
Eremey Valetov
eb32021c19 Implement string space pool with compacting garbage collector
Replaces individual malloc/free string management with a contiguous pool
(default 32KB) and compacting GC, matching the original GW-BASIC's
GETSPA/GARBAG architecture. Allocation is a bump pointer; gw_str_free()
is a no-op (descriptors are nulled, data reclaimed by GC). Compaction
runs at statement boundaries when the pool drops below 4KB free, walking
the variable table and array storage to relocate live strings.

FRE() now returns actual free pool space. FRE("") triggers a GC pass
before reporting. CLEAR n sets the string space size.
2026-03-29 04:55:48 -04:00
Eremey Valetov
724f823536 Update Sphinx docs with v0.15.0 gap-fill: ENVIRON, ERDEV, IOCTL, RESET, etc. 2026-03-28 18:50:22 -04:00
Eremey Valetov
612d3972dc Implement remaining statement/function gaps: RESET, ENVIRON/ENVIRON$, ERDEV/ERDEV$, IOCTL/IOCTL$, LCOPY, DATE$/TIME$ assignment, CALL, COM
Closes the last unimplemented extended statement tokens. ENVIRON uses
putenv/getenv for real environment variable access. DATE$/TIME$
assignment is accepted but silently ignored (no system clock modification).
ERDEV/ERDEV$/IOCTL$/PEN return stub values (no real device hardware).
CALL/CALLS raise Illegal function call. COM event trapping silently
accepted.
2026-03-28 18:48:38 -04:00
Eremey Valetov
d69c46330c Update Sphinx docs with v0.15.0 Hardware I/O Simulator, bump version 2026-03-28 18:30:04 -04:00
Eremey Valetov
e100290dd3 Implement Hardware I/O Simulator (OUT/INP/WAIT/MOTOR, port emulation)
New portio.c module following the virmem.c dispatch-by-address pattern,
emulating 8253 PIT channel 2 (speaker frequency), PPI port B (speaker
on/off), CGA mode/color select registers, game port (joystick stub),
COM1 serial (transmitter-ready stub), and floating bus default (0xFF).

OUT/WAIT/MOTOR statements and INP()/STICK()/STRIG() functions now fully
functional. Continuous tone generation via PulseAudio pthread worker for
programs that drive the speaker through OUT &H43/&H42/&H61.
2026-03-28 18:27:19 -04:00
Eremey Valetov
0d9f29aa7a Fix DRAW M/S/A bugs, add TA rotation, =variable; substitution, X substring execution
Rewrites gfx_draw() as a recursive draw_engine() to support all DRAW
mini-language features:

Bug fixes:
- M command parsing: skip generic arg parser so M100,50 correctly
  parses both coordinates instead of consuming x as a generic arg
- S (scale) semantics: distance is now (arg ?: 1) * scale / 4, matching
  original GW-BASIC where S4 means 1 pixel per unit, not 4
- A (rotation): implements 90-degree rotation state with direction
  vector transform for all 8 direction commands

New features:
- TA n: arbitrary rotation angle (-360 to 360 degrees) via cos/sin
- =variable;: numeric variable substitution in DRAW strings
- X stringvar;: execute substring from string variable (recursive)
- Scale factor applied to relative M coordinates
2026-03-21 02:48:17 -04:00
Eremey Valetov
3f3104c385 Implement MBF binary file compatibility, fix binary loader null-byte truncation, update to v0.14.0
Binary tokenized SAVE/LOAD now stores float constants in Microsoft Binary
Format (MBF) on disk, matching original GWBASIC.EXE.  A token-walking function
(convert_floats) converts IEEE↔MBF at the save_binary()/load_binary() boundary.

Also fixes a latent bug where load_binary() scanned for 0x00 to find the end
of each token line — this fails when float bytes contain null (e.g. MBF for
100.5 is 00 00 49 87).  The loader now uses the next-line pointer to compute
token data length, matching the original's approach.
2026-03-21 01:38:53 -04:00
Eremey Valetov
c488cb526d 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.
2026-03-11 08:11:13 -04:00