Random Boxes

This file is part of Timex Sinclair Public Domain Library Tape 1007. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000
Tags: Demo

This program is a machine code loader and launcher that prints random sized boxes with random character fills.. The BASIC program uses a single `RAND USR 17298` call at line 2 to transfer execution into the machine code embedded in the REM, which begins at address 16514 (the first byte after the REM token and length bytes on a 16K machine). The REM data is substantial — several hundred bytes of Z80 opcodes — and handles all primary logic including what appear to be floating-point arithmetic routines, display output via RST instructions, and structured data tables stored at fixed addresses in the 0x4400 region. Lines 10–30 provide a simple BASIC wrapper: clearing memory, saving the program under the name “1032%2”, then restarting with RUN.


Program Analysis

Program Structure

The BASIC listing is intentionally minimal, serving only as a vehicle to store and launch Z80 machine code:

  1. Line 1 — A REM statement containing the entire machine code payload (several hundred bytes of raw Z80 opcodes).
  2. Line 2 — RAND USR 17298 transfers execution to the machine code. Address 17298 decimal is 0x4392, which falls well into the REM body, suggesting the code self-relocates or that the REM begins at the standard address 0x4009 and the entry point is offset accordingly.
  3. Line 10 — CLEAR with no argument resets the BASIC stack and clears variables.
  4. Line 20 — SAVE "1032%2" saves the program to tape.
  5. Line 30 — RUN re-executes from line 1 after saving.

The flow implies the program is intended to be loaded, auto-saved under the given name, and then run. Lines 10–30 act as a distribution/duplication wrapper rather than core program logic.

Machine Code Entry Point

On a standard 16K machine the REM data begins at address 16514 (0x4082). RAND USR 17298 (0x4392) therefore enters the code at a byte offset of 784 into the REM block, past the initial setup routines. The first bytes of the REM (\2A\39\40\E5\CD\2B\0F) decode as:

  • 2A 39 40 — LD HL,(0x4039)
  • E5 — PUSH HL
  • CD 2B 0F — CALL 0x0F2B (a ROM routine)

This suggests the very start of the REM block (reachable via a different entry or self-modifying jump) begins by reading a word from address 0x4039 and calling into the ROM, consistent with floating-point or channel setup.

ROM Calls and RST Usage

Throughout the disassembly several well-known ROM entry points appear:

AddressLikely ROM routine
0x0F2BEvaluate expression / FP stack
0x0F23Related arithmetic entry
0x0A1FPrint character / output
0x0918Display / print routine
0x0BBDCassette or I/O routine

RST instructions appear as D7 (RST 0x10 — print character to current channel) and CF (RST 0x08 — error handler), which are standard Spectrum/TS2068 ROM fast-call idioms used to minimise code size.

Fixed Memory Map at 0x4400

A notable feature is the heavy use of absolute addresses in the 0x4400–0x44FF range as a structured data area. Addresses referenced include:

  • 0x4421 / 0x4439 / 0x443A / 0x443B — flag bytes and counters read and written throughout the code.
  • 0x441E — a single byte used as a direction or mode flag (modified by 32 1E 40 = LD (0x401E),A).
  • 0x44C7, 0x44C9, 0x44CB, 0x44CD, 0x44CF, 0x44D1, 0x44D3, 0x44D5, 0x44D7, 0x44D9 — a tightly packed array of 16-bit words, each loaded/stored with LD HL,(...) / LD (...),HL pairs, suggesting a table of coordinates or vector components.
  • 0x445D — used as a base pointer in one display loop.

Arithmetic and Multiply Routines

The REM block contains what appears to be a custom 16-bit multiply routine starting near offset 0x41C5. It uses the classic shift-and-add pattern:

  • A loop counter of 16 (06 10) iterates once per bit.
  • Double-length left shifts are performed with ADD HL,HL and RL C / RL A.
  • Conditional ADD HL,DE accumulates partial products.

A separate signed division or normalisation block appears at approximately offset 0x41ED, using ED 52 (SBC HL,DE) and ED 62 (NEG equivalent on HL) with carry checks, typical of fixed-point scaling code used in line-drawing or 3D projection.

Display and Graphics Handling

Several code sections use D7 (RST 16) to stream character codes to the display, including control codes 0x12 (AT), 0x16 (INK/PAPER attribute tokens), and 0x13 (TAB). The sequence 3E 12 D7 (LD A,18 / RST 16) appears more than once, consistent with positioning the print cursor via AT row/column pairs. A loop at one location outputs a sequence of block graphic characters from a table, building a sprite or border directly through the channel output system rather than direct screen memory writes.

FD CB (IY-bit) Instructions

Several FD CB prefix instructions appear, operating on bits of (IY+offset). For example:

  • FD CB 21 46 — BIT 0,(IY+33) — tests a system flag.
  • FD CB 21 4E — BIT 1,(IY+33)
  • FD CB 01 4E — BIT 1,(IY+1)
  • FD CB 01 C6 — SET 0,(IY+1)

These are accessing the system variables area via the IY register (which the ROM keeps pointing to 0x5C3A on the Spectrum/TS2068), specifically flags related to input mode and key state.

Notable Techniques

  • REM as code store: The entire executable lives in the REM at line 1; RAND USR jumps directly into it, bypassing any BASIC interpreter overhead.
  • EX (SP),HL tricks: E3 (EX (SP),HL) appears multiple times to swap HL with the top of stack, a compact way to pass or return values without dedicated registers.
  • Self-modifying or table-driven dispatch: Several JP (HL) / E9 instructions at the ends of routines use a pointer loaded from the data table at 0x4400, providing an indirect jump dispatch mechanism.
  • Inline data tables: The final bytes of the REM (2A 00 07 00 1E 00 ...) are clearly a data table rather than code, used as parameters for the routines above.

Anomalies and Observations

  • The CLEAR at line 10 has no address argument; this clears variables but does not set a new RAMTOP, which means it does not protect the machine code sitting in the REM from being overwritten by BASIC — the machine code must have already finished and returned to BASIC by this point.
  • The SAVE filename "1032%2" uses the %2 escape for inverse video of ‘2’, which on tape gives a distinctive visual name but does not affect the saved bytes.
  • The RUN at line 30 after saving will re-enter line 1 and immediately jump back into machine code via line 2, causing any post-save logic to loop.

Appears On

Assembled by Tim Ward from many sources. Contains programs 10294-10335.

Image Gallery

Source Code

   1 REM \2A\39\40\E5\CD\2B\0F\CD\1F\0A\3E\12\D7\3A\21\40\CB\47\20\26\2A\0E\40\E5\CD\75\43\E1\FE\77\28\E7\FD\CB\21\46\00\20\3A\FE\76\28\21\FE\16\28\08\FE\1C\38\E4\FE\26\30\E0\D7\18\DD\07\07\2F\E6\02\C6\02\32\1E\40\21\00\00\3E\12\D7\18\CB\3E\13\D7\CD\10\41\38\B3\E1\D5\E5\CD\1F\0A\C1\CD\18\09\E1\A7\C9\FE\76\28\26\FE\1C\38\AE\FE\2C\30\AA\D7\D6\1C\5F\16\00\19\EB\21\1E\40\35\28\D9\EB\29\29\29\29\18\95\FD\CB\21\4E\C0\CB\7C\C8\E1\E1\37\C9\11\00\00\4B\7E\FE\16\20\04\23\0C\18\F7\E5\D6\1C\6F\26\00\19\EB\E1\23\7E\FE\13\28\15\FE\7E\28\11\E5\D5\E1\06\09\19\2B\CD\04\41\23\10\F8\EB\E1\18\D3\97\B9\C8\A7\ED\62\ED\52\EB\A7\C9\22\32\40\CB\BC\D1\C9\00\3A\3B\40\F5\CD\2B\0F\CD\75\43\A7\20\02\CF\FF\FE\28\20\F4\F1\CB\77\C0\C3\23\0F\44\4D\C3\35\0F\43\4D\C3\F5\08\7D\01\00\00\C3\75\0B\C5\06\10\7C\4D\21\00\00\29\CB\11\17\30\01\19\10\F7\C1\C9\00\01\18\06\0E\02\18\02\0E\00\7C\AA\E6\80\47\D5\CD\ED\41\E3\CD\ED\41\EB\E1\79\A7\28\36\78\B1\E5\ED\62\ED\52\E5\C1\D1\21\00\00\37\3F\F5\7A\53\1E\08\29\30\05\8F\ED\4A\18\09\87\ED\4A\38\03\ED\42\3D\3C\1D\20\EC\5F\F1\30\E2\CB\4F\20\01\EB\CB\7F\C8\18\0B\CD\7F\41\CB\10\D0\18\03\7C\07\D0\EB\A7\ED\62\ED\52\C9\7C\07\38\06\B5\C8\21\01\00\C9\21\FF\FF\C9\A7\ED\52\C9\A7\ED\52\7C\B5\21\00\00\C0\2C\C9\A7\ED\52\C8\18\E3\EB\01\00\80\18\04\EB\01\01\80\7C\A8\67\7A\A8\57\ED\52\26\00\79\6F\D8\EE\01\6F\C9\7C\B5\21\00\00\C8\7A\B3\C8\2C\C9\7C\B5\B2\ED\62\18\F5\3E\01\18\01\AF\E3\5E\23\56\23\E3\2B\29\19\A7\28\08\EB\E1\E3\EB\73\23\72\C9\5E\23\56\EB\C9\EB\CD\6B\42\EB\C9\D5\11\4B\00\ED\4B\32\40\03\62\68\CD\09\13\E5\62\69\CD\09\13\C1\7C\81\30\01\04\67\7D\90\30\01\25\6F\2B\C3\4C\41\00\00\3A\21\40\CB\47\20\1A\CB\4F\20\0A\CB\7C\28\06\3E\16\D7\CD\F0\41\01\F0\D8\1E\FF\C5\CD\E1\07\CD\AD\0A\E5\C1\21\5D\40\57\1E\1C\70\CB\7A\28\01\71\97\ED\6F\83\D7\97\ED\6F\83\D7\CB\7A\CB\FA\28\EF\C9\E1\7E\23\FE\70\28\2F\FE\76\20\03\D7\18\F3\CD\79\41\18\EE\97\18\02\3E\90\4B\45\21\30\40\56\77\D5\E5\CD\B2\0B\E1\D1\72\C9\CD\0C\42\7C\B5\E3\5E\23\56\23\E3\C0\E1\EB\E9\7D\E6\1F\4F\FD\CB\01\4E\28\0A\FD\96\38\CB\FF\C6\3C\D4\71\08\FD\86\39\FE\21\3A\3A\40\DE\01\CD\FA\08\FD\CB\01\C6\C9\E1\5E\23\56\23\E5\D5\21\07\00\19\06\04\56\2B\5E\2B\D5\10\F9\E1\C1\D1\7A\19\EB\E1\E3\73\23\72\C5\E1\07\30\01\EB\CD\1B\42\E1\D8\C1\E9\EB\73\C9\C1\E5\C1\C9\6E\26\00\C9\11\DA\7F\D5\E5\C9\C5\E1\C9\EB\CD\7F\43\EB\C9\CD\7F\43\38\FB\CD\7F\43\30\FB\D5\CD\BB\02\E5\C1\2C\6C\28\04\CD\BD\07\6E\26\00\7D\D1\C9\11\36\00\CD\6B\42\CD\96\41\22\C7\44\11\16\00\CD\6B\42\CD\9A\41\22\C9\44\11\01\00\2A\C9\44\CD\20\42\CD\FD\42\C4\43\11\0A\00\CD\6B\42\CD\96\41\22\C9\44\11\02\00\2A\C9\44\CD\92\41\EB\21\01\00\CD\05\42\E5\11\02\00\2A\C7\44\CD\92\41\EB\21\01\00\CD\05\42\D1\CD\73\41\21\01\00\22\CB\44\2A\C7\44\22\CD\44\21\01\00\22\CF\44\21\01\44\22\D1\44\CD\D2\42\80\70\CD\2F\43\CB\44\11\02\00\2A\C7\44\CD\92\41\EB\21\01\00\CD\05\42\CD\09\43\21\01\00\22\CB\44\2A\C9\44\22\CD\44\21\01\00\22\CF\44\21\36\44\22\D1\44\11\02\00\2A\C7\44\CD\92\41\EB\21\01\00\CD\05\42\CD\09\43\CD\D2\42\80\70\21\01\00\22\D3\44\11\02\00\2A\C7\44\CD\05\42\22\D5\44\21\01\00\22\D7\44\21\6C\44\22\D9\44\2A\C9\44\CD\78\41\CD\2F\43\D3\44\CD\D2\42\80\70\CD\2F\43\CB\44\11\02\00\2A\C7\44\CD\92\41\EB\21\01\00\CD\05\42\CD\09\43\21\01\00\22\CB\44\2A\C7\44\22\CD\44\21\01\00\22\CF\44\21\AC\44\22\D1\44\CD\D2\42\80\70\CD\2F\43\CB\44\CD\7F\43\CD\0C\42\CD\FD\42\C4\44\CD\5E\43\C3\92\43\2A\00\07\00\1E\00\2A\00\01\00\01\44\06\00\05\00\01\00\6C\44
   2 RAND USR 17298
  10 CLEAR 
  20 SAVE "1032%2"
  30 RUN 

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