Hello!

Developer(s): Kristian Boisvert
Date: 1988
Type: Program
Platform(s): TS 2068

This program is a menu-driven file launcher that displays a scrollable directory of programs stored on a disk drive, allowing the user to select and load them by pressing a letter key. It uses machine code routines loaded at a computed address (derived from system variables at addresses 23635–23636) to handle hardware-level operations such as drive selection and screen scrolling. The directory is stored in a 200×9 DIM array `a$`, with entries differentiated by a `.Cx` suffix convention to distinguish between BASIC and CODE files, triggering different LOAD paths accordingly. Lines 8000–8120 provide utility subroutines that POKE machine code bytes to modify the behavior of `.Cx` file printing in the launcher. The program targets a TS2068 with a Larken disk drive.


Program Analysis

Program Structure

The program is organized into a handful of logical blocks:

  1. Lines 0–1: REM headers — line 0 contains embedded machine code (its content is binary data, not readable BASIC text), and line 1 contains a title/credit banner.
  2. Lines 10–109: Initialization — sets display attributes, dimensions the name array, and computes the base address of the machine code from system variables.
  3. Lines 110–240: Main interactive loop — draws the UI, polls the keyboard, handles scrolling and drive selection, and loads the selected program.
  4. Lines 8000–8120: Utility patches — POKEs bytes into the machine code to toggle whether .Cx files are printed in the directory.
  5. Line 9999: Save line — saves the program with auto-run from line 1.

Machine Code Usage

Machine code is embedded in the REM statement at line 0. Its base address is computed at line 109 as USR (5+PEEK 23635+256*PEEK 23636), which is 5 bytes past the start of the BASIC program area — exactly where the payload inside the line-0 REM begins. This is the standard technique for self-relocating machine code on these systems.

RANDOMIZE USR 100 is used as a disk ROM entry point throughout the program (lines 107, 230, 240, 9999), consistent with disk interface conventions where address 100 is a jump into the disk operating system.

Lines 170 and 180 call into the machine code at offsets +98 and +126 from the computed base address to perform hardware-assisted scroll-down and scroll-up operations respectively, avoiding slow BASIC scrolling of the display.

Directory and Navigation

The program directory is held in a$(200,9), a two-dimensional string array of up to 200 entries each nine characters wide. The variable L holds the count of valid entries (set from the machine code’s output via USR). The variable NAME acts as the current scroll position, always pointing to the first of the currently displayed pair of rows.

The display shows 8 pairs of entries (16 total) at a time, labeled A–P. Pressing a letter key A–P selects the corresponding entry relative to the current scroll position. Pressing 6 or cursor-down scrolls forward by two entries; pressing 7 or cursor-up scrolls back.

Key BASIC Idioms

  • (a$(NAME+X-65) AND NAME+X-65<=L) — the Spectrum AND operator used to conditionally print a string: returns the string if the condition is true, or an empty string if false, avoiding an explicit IF.
  • GO TO DRIVE-1 at line 107 — a computed GO TO targeting a line number derived from the selected drive number minus one (e.g., drive 1 → line 0, drive 2 → line 1). This is a valid technique for jumping to non-standard or pre-computed line numbers.
  • POKE 23658,8 — sets the FLAGS2 system variable bit to enable cursor keys, so CHR$ 10 (cursor down) and CHR$ 11 (cursor up) are readable via INKEY$.
  • POKE 23606,0: POKE 23607,60 — sets the system variable RASP/PIP area, commonly used to silence or adjust key click behavior.

File Type Detection

At lines 220–230, the program scans the selected filename D$ for the first period character. Once found, it checks whether the character two positions later is "C". If so, the file is treated as a CODE file and loaded with LOAD D$CODE followed by PAUSE 0 and a return to the main menu. Otherwise, it is loaded as a BASIC program with LOAD D$ (line 240), which transfers control entirely.

Utility Patch Routines (Lines 8000–8120)

These routines modify four bytes inside the machine code at offset +69 from the base address. Line 8010 zeroes those bytes (presumably NOPs), enabling .Cx file entries to appear in the directory listing. Line 8110 POKEs the values 254, 67, 40, 217, which patch in a conditional branch or filter that suppresses .Cx files. Both routines end with STOP, indicating they are run standalone as maintenance utilities rather than called during normal program operation.

Notable Anomalies

  • Line 105 loops back to itself on invalid input rather than using a structured loop, which is standard practice in this era of BASIC programming.
  • The FOR F=1 TO 9 loop at line 220 uses NEXT F inside an IF — if no period is found within the 9-character filename, the loop exits naturally and F will equal 10, potentially causing an out-of-bounds substring access at D$(F+1). This is a latent bug if filenames without a period are somehow stored in the array.
  • The INK and PAPER commas in PRINT statements (e.g., PAPER 7,,) use multiple separators to produce blank lines efficiently within a single PRINT statement.

Content

Appears On

Tape-based magazine.

Related Products

Related Articles

This utility is used as a boot program for the LARKEN LKDOS cartridge (ALL CARTRIDGES!) To transfer the program to...

Related Content

Image Gallery

Source Code

    0 REM NEXT STEP bCODE 2 STEP FREE STEP { GO SUB [K\! FOR !p FREE # RETURN IF (5 RETURN COPY  PLOT FREE RETURN RETURN ( LET OR FREE # RETURN .(STR$ READ STR$ FREE RETURN A( INVERSE RETURN C( INK + FREE RETURN COPY  IF OR # FREE IF STR$ OR CLS STEP INT <>H!#H> GO SUB VAL = PAUSE STICK RETURN P FOR <>O! OUT O> GO SUB LN +++= PAUSE z RETURN G FOR <>0
    1 REM                                                                                                     HELLO!                                               WRITTEN BY KRISTIAN BOISVERT                                     COPYRIGHT \*1988 BYTE POWER                                    
   10 INVERSE 0: OVER 0: INK 0: PAPER 7: BORDER 7: CLS 
  100 REM MAIN ROUTINE
  102 POKE 23658,8: POKE 23606,0: POKE 23607,60: DIM a$(200,9): GO TO 109
  105 INPUT "DRIVE [1-5]...................";DRIVE: IF DRIVE<1 OR DRIVE>5 THEN GO TO 105
  107 RANDOMIZE USR 100: GO TO DRIVE-1
  109 LET NAME=1: LET L=USR (5+PEEK 23635+256*PEEK 23636)
  110 PRINT AT 0,0; PAPER 7,, PAPER 3; INK 7;TAB 13;"HELLO!",,,TAB 2;"WRITTEN BY KRISTIAN BOISVERT",,,TAB 3;"COPYRIGHT \*1988 BYTE POWER",
  120 PRINT AT 18,0; INK 7; PAPER 1,,,,,,AT 20,0;"[7]- SCROLL UP","[6]- SCROLL DOWN";AT 19,5;"[LETTER]- LOAD PROGRAM";AT 18,7;"[1]- SELECT DRIVE"
  130 PRINT AT 7,0; PAPER 2,,: LET X=65: FOR F=8 TO 15: PRINT AT F,0; INK 0; PAPER 6;CHR$ X;"- ";(a$(NAME+X-65) AND NAME+X-65<=L),CHR$ (X+1);"- ";(a$(NAME+X-64) AND NAME+X-64<=L),: LET X=X+2: NEXT F: PRINT AT 16,0; PAPER 2,,
  150 LET B$=INKEY$
  160 IF B$="1" THEN GO TO 105
  170 IF (B$="6" OR B$=CHR$ 10) AND NAME+16<=L THEN RANDOMIZE USR (PEEK 23635+256*PEEK 23636+98): LET NAME=NAME+2: PRINT INK 0; PAPER 6;AT 15,3;A$(NAME+14),AT 15,19;(A$(NAME+15) AND NAME+15<=L),
  180 IF (B$="7" OR B$=CHR$ 11) AND NAME-2>=1 THEN RANDOMIZE USR (PEEK 23635+256*PEEK 23636+126): LET NAME=NAME-2: PRINT INK 0; PAPER 6;AT 8,3;A$(NAME),AT 8,19;A$(NAME+1),
  190 IF B$<"A" OR B$>"P" THEN GO TO 150
  200 IF NAME+(CODE B$-65)>L THEN GO TO 150
  210 LET D$=A$(NAME+(CODE B$-65)): PRINT #1;AT 1,0;"LOADING... ";D$
  220 FOR F=1 TO 9: IF D$(F)<>"." THEN NEXT F
  230 INK 0: PAPER 7: LET D$=D$(1 TO F+2): IF D$(F+1)="C" THEN RANDOMIZE USR 100: LOAD D$CODE : PAUSE 0: CLS : GO TO 109
  240 RANDOMIZE USR 100: LOAD D$
 8000 REM PRINT ".Cx" FILES
 8010 LET A=PEEK 23635+256*PEEK 23636+69: FOR F=A TO A+3: POKE F,0: NEXT F: STOP 
 8100 REM DON'T PRINT ".Cx" FILES
 8110 LET A=PEEK 23635+256*PEEK 23636+69: POKE A,254: POKE A+1,67: POKE A+2,40: POKE A+3,217
 8120 STOP 
 9999 RANDOMIZE USR 100: SAVE "HELLO!.B1" LINE 1

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top