From: Svjatoslav Agejenko Date: Sat, 26 Sep 2026 12:31:48 +0000 (+0300) Subject: fix(interp): treat DECLARE parameter names as placeholders per QB45 X-Git-Url: http://www2.svjatoslav.eu/gitweb/?a=commitdiff_plain;p=crtbasic.git fix(interp): treat DECLARE parameter names as placeholders per QB45 - bindScope no longer registers the argument cell under a DECLARE-only parameter name; only the definition's names bind, matching QB45 where DECLARE names are placeholders. The declared parameter still contributes its type (by-value cell kind, array/asTyped flags). Previously a name mismatch aliased locals to byref arguments (truth.bas teeslg's x2 wrote into its caller's x2); verified pixel-identical against QB.EXE in DOSBox. Adds regression test declareParameterNamesArePlaceholders. - GameDriver gains --textdump/--textcell: TextDump recognizes each 8xN screen cell against the built-in CP437 VGA font into diffable text (custom glyphs get stable private-use code points), written wherever a $ screenshot lands or at end of run. --- diff --git a/src/main/java/eu/svjatoslav/crtbasic/interp/Interpreter.java b/src/main/java/eu/svjatoslav/crtbasic/interp/Interpreter.java index def421b..2fd05d0 100644 --- a/src/main/java/eu/svjatoslav/crtbasic/interp/Interpreter.java +++ b/src/main/java/eu/svjatoslav/crtbasic/interp/Interpreter.java @@ -1412,7 +1412,14 @@ public final class Interpreter { } } scope.put(headerKey, cell); - scope.put(declaredKey, cell); + // QB45 semantics: DECLARE parameter names are placeholders, + // only the definition's names are visible in the body. The + // declared param still contributes its TYPE (by-value cell + // kind above, array()/asTyped() below) — but the cell is NOT + // registered under a declared-only name. (Previously it was, + // which aliased locals to arguments when DECLARE and the + // definition disagreed on names — truth.bas teeslg's x2 + // wrote into its caller's x2, unlike real QB45.) // An "AS type" parameter claims the bare name: body references // canonicalize through the DEFxxx default ("delayInSeconds" → // "…%" under DEFINT A-Z), so register the same cell under that diff --git a/src/test/java/eu/svjatoslav/crtbasic/drivers/GameDriver.java b/src/test/java/eu/svjatoslav/crtbasic/drivers/GameDriver.java index 0cac09e..bc01812 100644 --- a/src/test/java/eu/svjatoslav/crtbasic/drivers/GameDriver.java +++ b/src/test/java/eu/svjatoslav/crtbasic/drivers/GameDriver.java @@ -22,7 +22,7 @@ import java.util.List; *
  *   GameDriver program.bas [--steps=N] [--screenshot=out.png]
  *       [--keys=SCRIPT] [--mouse=SCRIPT] [--interval=MS] [--vars=a%,b%,c$]
- *       [--block]
+ *       [--block] [--textdump=out.txt] [--textcell=N]
  * 
* *

Key script: each character is one input event, delivered roughly every @@ -42,6 +42,11 @@ import java.util.List; * so an end-of-run screenshot only catches screens reachable without * input.

* + *

{@code --textdump} additionally writes the screen as recognized text + * (see {@link TextDump}) wherever a screenshot is taken: at every {@code $} + * token with the same numbering, or at end of run when no {@code $} was + * scripted. {@code --textcell} sets the cell height in pixels (default 8).

+ * *

Mouse script: space-separated tokens, one event per interval, feeding * the emulated qbext mouse TSR:

*