This program prints a comprehensive character and keyword reference string, then loads a custom character set into memory and patches the system variable that points to the UDG (User Defined Graphics) table. The LOAD command at line 9991 brings in 520 bytes of machine code to address 64368, which is in the high RAM area typically used for custom data on the TS2068. Lines 9992 POKEs 23606 and 23607 to redirect the UDG pointer: the 16-bit address stored there is 250×256+112 = 64112, pointing the system to the newly loaded character definitions. Line 9998 saves both the BASIC loader and the machine code block, with LINE 9991 ensuring the code auto-runs on load.
Program Analysis
Program Structure
The program has two functional sections: a single display line followed by a cluster of utility lines at the top of the line-number space. Line 1 is a print statement serving as a character/keyword reference. Lines 9989–9998 form the loader/installer for a custom character set stored as a machine code block.
- Line 1 — Prints a long reference string covering printable ASCII characters, TS2068 BASIC keywords, and special symbols.
- Lines 9989–9990 — REM comments labelling the purpose of the code block (“CHARACTERS A THRU Z”, “NEW CHR$ a”).
- Line 9991 — Loads 520 bytes of machine code to address 64368.
- Line 9992 — POKEs the UDG system variable to redirect it to the loaded character data.
- Line 9997 — STOP, preventing fall-through to the SAVE line during normal execution.
- Line 9998 — Saves the BASIC program (auto-running at line 9991) and the code block.
Memory Map and System Variables
The loader targets two well-known system variables to redirect the UDG character table:
| Address | System Variable | Value POKEd | Purpose |
|---|---|---|---|
| 23606 | UDG (low byte) | 112 | Low byte of new UDG base address |
| 23607 | UDG (high byte) | 250 | High byte of new UDG base address |
The combined 16-bit address is 250 × 256 + 112 = 64112. This places the new UDG table in high RAM, well above the normal RAMTOP area, consistent with the code block loaded at 64368 — the 520 bytes likely include both the character bitmaps and possibly a small machine code routine.
The Code Block
The block at address 64368 is 520 bytes long. Since standard UDG coverage for 26 lowercase letters (a–z) requires 26 × 8 = 208 bytes, the additional bytes (312 extra) suggest the block contains either extended character definitions, additional symbol glyphs, or supporting machine code. The REM at line 9989 references “A THRU Z”, confirming at minimum a full lowercase alphabet replacement.
Key BASIC Idioms and Techniques
- High line numbers for utilities — Placing the loader at lines 9989–9998 keeps it well away from any program content that would follow line 1, and makes it easy to identify as infrastructure rather than application code.
- STOP before SAVE — Line 9997’s
STOPprevents line 9998 from executing during normal program runs; the SAVE line is only intended to be run manually or during development. - Auto-run SAVE —
SAVE "NEW CHR$" LINE 9991encodes the entry point so reloading the tape automatically runs the installer from line 9991. - Paired SAVE commands — The BASIC and CODE blocks are saved as two separate tape files under the same name, a standard technique for bundling a loader with its associated binary.
Line 1 — Character Reference
The PRINT statement on line 1 appears to be a developer reference listing every printable character alongside BASIC keywords, used to visually verify that the custom character set renders all glyphs correctly. It covers digits, uppercase and lowercase letters, punctuation, and a broad selection of TS2068 keywords including BEEP, CIRCLE, SCREEN$, ATTR, STICK, ON ERR, FREE, SOUND, and trigonometric/mathematical functions.
Notable Observations
- The UDG pointer (23606/23607) is set to 64112, which is 256 bytes below the loaded code block at 64368 — suggesting the character bitmap data begins at 64112 and the code (if any) follows it.
- 520 bytes ÷ 8 bytes per character = 65 characters, enough to redefine the full UDG set (21 standard UDGs = 168 bytes) plus substantial additional data, or to cover a different range of characters entirely.
- No error trapping (
ON ERR) is used; if the LOAD at 9991 fails, execution halts with a tape error rather than gracefully recovering.
Content
Source Code
1 PRINT "1234567890QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm!@#$%&'()_;AT OR AND ><>=<><= STOP NOT STEP TO THEN ^-+=.,*/?`:ASN ACS ATN VERIFY RND MERGE []IN OUT ©FREE STICK\ON ERRBEEP CIRCLE VAL$ SCREEN$ ATTR BEEP INK PAPER FLASH BRIGHT OVER INVERSE SIN COS TAN INT RNDSTR$ CHR$ CODE PEEK TAB READ RESTORE DATA SGN ABS SQR VAL LEN USR LN EXP LPRINT LLIST BIN INKEY$PI"
9989 REM CHARAECTERS *A THRU Z*
9990 REM *********************** NEW CHR$ a ***********************
9991 LOAD "NEW CHR$"CODE 64368,520
9992 POKE 23606,112: POKE 23607,250
9997 STOP
9998 SAVE "NEW CHR$" LINE 9991: SAVE "NEW CHR$"CODE 64368,520
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
