Skip to content

Wait for a player action on MTX500 in BASIC

Reuse an untimed update with a small native caller, clear state ownership, a custom step and a reset mistake you can recognise.

Enter 1, then Return. The count advances once. Wait as long as you like: the world waits with you. That is a useful starting point for an adventure, a board game or a menu-driven decision.

The counter stands in for your game rules. Input collects a command, the update decides whether it counts, and presentation shows the result. You can replace any one of those without moving initialisation into the loop.

MTX500 BASIC showing turn two after two accepted commands.
Two commands, two updates. Waiting does not spend a turn.

Put it in your project

Use normal MTX500 BASIC. Enter the complete reusable.bas from the source folder, then RUN. These two maintained pieces concatenate to that complete program; keep their line numbers distinct from the rest of your project.

Initialise once, then collect and handle commands

caller.bas
10 LET N=0:LET S=1
20 CLS:PRINT "TURN";N
30 INPUT A
35 IF A=9 THEN STOP
40 GOSUB 1000
50 GOTO 20

A reusable conditional update

routines.bas
1000 LET C=0
1010 IF A<>1 THEN RETURN
1020 LET N=N+S
1030 IF N>255 THEN LET N=N-256
1040 LET C=1
1050 RETURN

0 leaves the count alone; 9 stops the caller. INPUT expects a number and follows the interpreter’s own handling of malformed input. This is a command gate, rather than a text-adventure parser.

Value Contract
N Persistent count, initialised once; whole number 0–255.
S Step, a whole number 0–255; unchanged by the routine.
A Submitted command; unchanged by the routine.
C Result: 1 when accepted, 0 when ignored.

GOSUB 1000 uses these global variables. Reserve the names and line range, or rename them consistently. The routine touches no hardware addresses. BASIC owns variable storage, keyboard input, screen output and interrupts. These are ordinary BASIC numbers: the 0–255 limit is this routine’s agreement, rather than the interpreter’s storage format.

With both inputs in range, N+S is at most 510, so one subtraction is enough to wrap it into a byte. Passing a fractional, negative or larger value breaks that agreement. Use a different range rule if your game needs an unbounded score.

CLS clears the screen in this caller. Move the count into your own status panel if other text must survive. The update does not need a screen clear. INPUT blocks until Return; an on-screen countdown would need input and deadline checks that can keep running while the player thinks.

Change the amount, keep the policy

This complete variation uses a step of three. Two accepted commands give 0 → 3 → 6. It still accepts only two actions.

Three units for each accepted command

customise.bas
10 LET N=0:LET S=3
20 CLS:PRINT "TURN";N
30 INPUT A
35 IF A=9 THEN STOP
40 GOSUB 1000
50 GOTO 20
1000 LET C=0
1010 IF A<>1 THEN RETURN
1020 LET N=N+S
1030 IF N>255 THEN LET N=N-256
1040 LET C=1
1050 RETURN
MTX500 BASIC showing six.
Change the rule update without changing how commands are collected.

Common mistake: starting over every time

This listing is deliberately broken. Its jump returns through the initialiser. The action briefly changes N, then the next pass erases it. The visible count stays at zero.

Broken: return through the initialiser

reset-each-command.bas
10 LET N=0:LET S=1
20 CLS:PRINT "TURN";N
30 INPUT A
35 IF A=9 THEN STOP
40 GOSUB 1000
50 GOTO 10
1000 LET C=0
1010 IF A<>1 THEN RETURN
1020 LET N=N+S
1030 IF N>255 THEN LET N=N-256
1040 LET C=1
1050 RETURN
MTX500 BASIC still showing zero after two accepted commands.
Keep persistent state outside the repeated path.

Restore the jump to line 20 to repair it. Initialisation belongs at the start of a game or a deliberate restart. A new turn should inherit the previous turn’s state.

The MTX display lives in VDP memory, rather than a CPU-mapped text buffer. The retained test uses a small, separately documented screen reader to copy the actual 40×24 name table for inspection. It does not supply the count. That diagnostic reader is not needed by the reusable program; its temporary RAM allocation is not a general BASIC memory allocator.

Where time belongs

An untimed world advances on an accepted action. A timed turn also needs a deadline and a rule for an action arriving at that deadline. Display refresh, firmware interrupts and CPU activity do not decide that policy for you.

Compare the loop choices and the assembly implementation. The languages have different storage and ownership agreements; choose the one that suits your project.

Source and verification

Native-emulator executed: Emu198x 0.44.1, with MTX500 firmware; assembly is built with Asm198x 0.0.71. Actual keyboard input drives the program. Host writes do not supply game state. The images above are native framebuffer captures.

The maintained source includes the complete caller, reusable pieces and deliberate fault. The retained observations cover normal use, idle waits and ignored commands, a custom step, reset and repair, 254 → 255 → 0, and a nonzero start. An independent checker rejects altered counts, sources and captures, missing observations and falsely repaired faults.

This qualifies these small workloads on the named configuration. It does not establish original-hardware, cassette-transfer, other-model or whole-emulator compatibility. The older input/drawing/sound probe remains a separate record; this loop entry makes no fresh audio claim.

Primary references

Memotech’s MTX Series BASIC Tutor, Reference and Operator’s Manual, original manual scan: BASIC control flow, USR and return value in BC. Memotech’s MTX Video Memory Mapping, document scan: separate VDP RAM, ports and access spacing. Keyboard drive/sense follows the retained stock-firmware input-loop and MTX hardware reference.