Browse Source

docs: document CALC launcher; add no-keypress boot mode

Eric Streit 4 ngày trước cách đây
mục cha
commit
a2d92d0f0f
4 tập tin đã thay đổi với 42 bổ sung và 10 xóa
  1. 27 8
      README.md
  2. 3 1
      shell/tests/calc_cli.py
  3. 9 0
      shell/tests/exec/bootcom.s
  4. 3 1
      shell/tests/run_com_exec.py

+ 27 - 8
README.md

@@ -18,19 +18,20 @@ second copy of a status table is a claim about the world that expires silently
 and is never noticed expiring, so there is one now, and this file says where it
 is.
 
-In short, current as of `v-TP3-DEAD-FIXTURES`:
+In short, current as of `v-TP3-CALC-CLI`:
 
 - The shell and the WordStar-style editor are done.
 - The compiler front end and 8086 code generator are done for the language
-  subset the fixtures cover, and the emitted `.COM` images **run**: 31 fixtures
-  boot in `qemu-system-i386` and print exactly their expected bytes, and 36
-  further cases call the runtime's own entries directly.
+  subset the fixtures cover, and the emitted `.COM` images **run** under
+  `qemu-system-i386` and Exec86.
+- **CALC.PAS compiles and runs.** The generated CALC.COM reaches the welcome
+  screen, grid and command menu, and exits cleanly through `/Q`.
 - **The shell's `R` key is still a stub.** There is no in-process 8086
   interpreter, so nothing runs a `.COM` from inside `tpshell` itself; execution
-  happens only under the test harness.
-- `string` *variables*, nested procedures, `var` parameters, range and index
-  checks, typed constants and `array` at its point of use are not implemented.
-  `SUMMARY.md` lists them with the reason for each.
+  happens under the test harness or the CALC launcher below.
+- The next capacity limit is CALC's full Help/heap use (16,281-byte `Pages`
+  plus a 16 KiB stack); the current flat-segment layout has less headroom than
+  that. `SUMMARY.md` and `CALC-COMPILE.md` record the details.
 
 ## Build
 
@@ -48,6 +49,24 @@ The shell runs in raw mode: it needs a real ANSI terminal, no wrappers.
 To run the checks: `cd shell && bash tests/run_all.sh`. It is not part of
 `make`, because it needs qemu and takes a few minutes.
 
+## CALC launcher
+
+`tests/calc_cli.py` builds CALC.COM in a temporary include directory, boots it
+under qemu and prints its serial output:
+
+```sh
+cd shell
+python3 tests/calc_cli.py                  # build + default welcome/quit keys
+python3 tests/calc_cli.py --com CALC.PAS.COM --keys '\r\r/Q'
+python3 tests/calc_cli.py --keys-file keys.bin --raw > screen.bin
+```
+
+Options: `--keys` (Python escapes such as `\r`, `\n`, `\x1b`), `--keys-file`,
+`--com`, `--timeout`, `--raw`, `--quiet`, `--verbose`, and `--no-keypress`
+(make AH=0Bh report no queued key; useful for scripted CALC input).
+Input is a static boot-time key stream, not a live terminal. The automated
+smoke check is `python3 tests/calc_smoke.py`, run by `tests/run_all.sh`.
+
 ## Layout
 
 - `shell/Term.def|mod` — raw termios keyboard + ANSI screen primitives

+ 3 - 1
shell/tests/calc_cli.py

@@ -67,6 +67,8 @@ def main(argv=None):
                     help="only print the exit status")
     ap.add_argument("--verbose", action="store_true",
                     help="show the compiler output and image size")
+    ap.add_argument("--no-keypress", action="store_true",
+                    help="make AH=0Bh report no queued key (needed for scripted CALC input)")
     args = ap.parse_args(argv)
 
     td = None
@@ -80,7 +82,7 @@ def main(argv=None):
                      % (len(com), r.COM_MAX))
         keys = (open(args.keys_file, "rb").read()
                 if args.keys_file else decode_keys(args.keys))
-        boot = r.build_boot_sector()
+        boot = r.build_boot_sector(no_keypress=args.no_keypress)
         with tempfile.TemporaryDirectory(prefix="tpcalc-run-") as runtd:
             img = os.path.join(runtd, "calc.img")
             open(img, "wb").write(r.build_floppy(boot, com, keys))

+ 9 - 0
shell/tests/exec/bootcom.s

@@ -272,6 +272,14 @@ handler:
 	jmp	.Ldone8
 
 .Lh0b:					# input status: AL=FFh if a character waits
+.ifdef NO_KEYPRESS
+	# CALC's main loop treats every queued byte after a Read as an extended
+	# key scan code.  A preloaded key stream therefore cannot drive it unless
+	# this status call reports "nothing waiting"; the CLI uses this build.
+	xorw	%ax, %ax
+	clc
+	jmp	.Ldone8
+.else
 	movw	INLEN, %ax
 	movw	INCUR, %bx
 	cmpw	%ax, %bx		# INCUR vs INLEN: >= is end of input
@@ -283,6 +291,7 @@ handler:
 	xorw	%ax, %ax		# AL = 0: nothing waiting
 	clc
 	jmp	.Ldone8
+.endif
 
 .Lh3d:					# open file: no filesystem in this harness
 	# The runtime uses real DOS AH=3Dh.  A boot floppy has no DOS and no

+ 3 - 1
shell/tests/run_com_exec.py

@@ -90,7 +90,7 @@ if FLAT_LOAD + COM_MAX > INLEN_FLAT:
 EXIT_BASE = 1
 
 
-def build_boot_sector(load_seg=None, inlen=None, copy_bytes=None, scratch=None):
+def build_boot_sector(load_seg=None, inlen=None, copy_bytes=None, scratch=None, no_keypress=False):
     """Assemble tests/exec/bootcom.s and return its 512 bytes."""
     with tempfile.TemporaryDirectory() as td:
         obj, raw = os.path.join(td, "b.o"), os.path.join(td, "b.bin")
@@ -103,6 +103,8 @@ def build_boot_sector(load_seg=None, inlen=None, copy_bytes=None, scratch=None):
             cmd += ["--defsym", "COPY_BYTES=%d" % copy_bytes]
         if scratch is not None:
             cmd += ["--defsym", "SCRATCH_SEG=%d" % scratch]
+        if no_keypress:
+            cmd += ["--defsym", "NO_KEYPRESS=1"]
         cmd += ["-o", obj, os.path.join(HERE, "exec", "bootcom.s")]
         r = subprocess.run(cmd, capture_output=True)
         if r.returncode != 0: