This program is a promotional demo for the Chicago Sinclair Special Interest Group, displaying an animated introduction screen with scrolling ticker text. It makes extensive use of machine code routines called via RAND USR at addresses in the 30000–31000+ range to handle graphics drawing, screen effects, and hardware control, with parameters passed by POKEing values into fixed RAM locations just before each call. The program builds a long inverse-video text string in C$ that scrolls smoothly across row 22 in three phases: an entry scroll from the right, a middle pan, and an exit scroll to the left. A subroutine at line 2000 displays a sequence of inverse-video advertising messages (“LOOKING FOR INEXPENSIVE COMPUTING?”) and then draws what appears to be a logo using ZX81 block graphics characters. The program loops indefinitely via GOTO 10 at line 1220.
Program Analysis
Program Structure
The program is organized into a main sequence and two subroutines, executing in a continuous loop:
- Lines 10–200: Machine code initialization and startup animation sequence, including screen setup, palette cycling, and display effects via repeated RAND USR calls inside FOR loops.
- Lines 210–490: Further animation phases, culminating in a CLS and transition to the main content.
- Lines 498–499: GOSUB to the advertisement subroutine (2000) and then to a screen-fill subroutine (4000).
- Lines 500–510: Draws a decorative border on rows 21–23 using block graphic characters.
- Lines 520–570: Builds the scrolling ticker string
C$(andB$) from concatenated inverse-video text fragments. - Lines 1060–1200: Three-phase horizontal scroll of
B$across row 22. - Line 1210–1220: CLS and GOTO 10 for an infinite loop.
- Lines 2000–2660: Advertisement subroutine — displays inverse-video promotional messages with delay loops, then draws a block-graphic logo using PLOT and machine code line-draw routines.
- Lines 4000–4130: Screen animation subroutine using machine code loops for rows and columns.
Machine Code Usage
The program relies heavily on external machine code routines loaded elsewhere in RAM. Parameters are passed by POKEing values into fixed addresses immediately before each RAND USR call. The following addresses are used:
| Address | Usage |
|---|---|
30646 / 30656 | Row/column animation routine (scroll down?) |
30696 / 30699 | Row/column animation routine (scroll up?) |
30946 | Called once after POKE 31738,50 — likely sets display mode or speed |
30962 | Called after delay loop — display effect |
30968 | Called at startup |
31017 | Called in subroutines; may clear or initialize screen region |
31028 | Called at program start and in subroutine 2000 — likely hardware init |
31152 | Called after POKEing 31737,0 and 31736,21 |
31179 | Called once after startup |
31329 | Called after POKEing coordinates into 31733/31732 — likely a line-draw routine |
31351 | Called with parameter in 31741 — likely a colour/attribute cycle routine |
31465 | Called at start of subroutine 4000 |
31666 | Column animation routine |
The parameter-passing convention is consistent: POKE the target address with a value, then immediately call RAND USR. For example, lines 2300–2320 POKE X and Y into addresses 31733 and 31732 before calling the line-draw routine at 31329. The PLOT call preceding each line-draw likely sets the start point.
The REM Line as Data
Line 50 is a REM statement containing a long sequence of block graphic characters (%, >, <, V, etc. rendered as block graphics in the ZX81 character set). This is a classic technique for embedding machine code or sprite data within a BASIC program — the REM body is never executed by BASIC but sits at a known address in memory where machine code can read or use it as a data table. The characters in the REM are almost certainly the machine code payload itself, encoded as BASIC token bytes.
Scrolling Ticker Implementation
The scrolling marquee is implemented in three FOR loops across lines 1060–1200, all printing to row 22:
- Entry phase (lines 1060–1100):
Fruns 0 to 30; printsB$(1 TO F+1)at column31-F, sliding text in from the right. - Middle phase (lines 1110–1150):
Eruns 1 toLEN B$-33; prints a 32-character windowB$(E+1 TO E+32)at column 0, panning through the string. - Exit phase (lines 1160–1200):
Cruns 0 to 31; prints a shrinking tail of the string at column 0, sliding text off to the left.
Each phase includes a short delay loop (FOR D=1 TO 3: NEXT D) and a POKE 16418,0 before each print. Address 16418 is the ZX81 system variable MARGIN, and zeroing it suppresses the automatic scroll so the display stays stable during animation.
Inverse Video Text
All displayed text uses the %X inverse video escape throughout, giving the entire presentation a reverse-video aesthetic. The ticker string C$ is built in three concatenation steps (lines 520, 560, 565) to stay within BASIC line-length limits. The content credits club officers by name and role, including the chair and contacts for beginners, BASIC programming, machine/assembly language, and hardware.
Block Graphics Logo
Subroutine 2000 draws a multi-row logo at lines 2490–2650 using ZX81 block graphic characters (▌, ▘, ▝, ▄, ▟, etc.) arranged carefully across rows 1–18. The logo appears to spell out “SINCLAIR” or a related acronym in chunky pixel art. Three PLOT+POKE+RAND USR 31329 sequences before the logo draw lines connecting elements of the graphic.
Notable Techniques
POKE 16418,0before each PRINT in the scroll loop suppresses auto-scroll (zeroes the MARGIN system variable).- Parameters for machine code routines are passed via fixed POKE addresses rather than registers, allowing clean BASIC-to-ML interfacing.
- String concatenation across multiple LET statements works around the ZX81’s line-length restriction for long ticker messages.
- Delay loops (
FOR I=1 TO N: NEXT I) are used for timing throughout, since no PAUSE command with fine granularity is available. - The program restarts via
GOTO 10(line 1220) rather thanGOTO 1orRUN, skipping re-execution of the very first machine code init calls if any state persists — though in practice the ML routines at line 10 and 20 are called again each loop.
Potential Anomalies
Line 40 sets up FOR B=1 TO 1, which executes its body exactly once. The corresponding NEXT B at line 200 closes this single-iteration loop. This appears to be a structural leftover — perhaps the loop count was once larger for repeated animation passes during the intro sequence.
The exit-scroll phase (lines 1160–1200) prints a string slice B$(C+LEN B$-31 TO LEN B$) which shrinks from 32 characters down to 1 as C increases, but the AT column stays at 0. This means the text does not actually slide off to the left — it truncates from the left edge while the right end stays fixed. Whether this is intentional or a minor bug depends on the desired visual effect.
Content
Source Code
10 RAND USR 31028
20 RAND USR 30968
40 FOR B=1 TO 1
50 REM :% >% >% >% >% > >% >% >% > >% >% >% >% >% V < < < <% < < <% < < < < < < <% V% > > > > > > >% > > >% > > > > V < < < <% < < <% < < < < < < <% V% >% >% >% >% > > >% > > >% > >% >% >% V% < <% < <% < < <% < < <% < < < < V > > > >% > > >% > > >% > > > >% V% < < < <% < < <% < < <% < < < < V% >% >% >% >% > >% >% >% > >% >% >% >% >% :
60 POKE 31738,50
70 RAND USR 30946
72 RAND USR 31179
80 FOR I=1 TO 16
90 RAND USR 30699
100 NEXT I
110 FOR I=1 TO 13
120 RAND USR 31666
130 NEXT I
140 FOR I=1 TO 16
150 RAND USR 30696
160 NEXT I
170 FOR I=1 TO 12
180 RAND USR 30656
190 NEXT I
200 NEXT B
210 FOR I=1 TO 8
220 RAND USR 30699
230 NEXT I
240 FOR I=1 TO 5
250 RAND USR 31666
260 NEXT I
270 PRINT AT 2,5;"SPECIAL INTEREST GROUP"
280 PRINT AT 18,6;"SINCLAIR ZX/TS 1000"
281 FOR I=128 TO 138
282 FOR P=1 TO 6
284 POKE 31742,I
285 RAND USR 31017
286 NEXT P
287 NEXT I
288 POKE 31742,151
289 RAND USR 31017
300 FOR P=1 TO 75
310 NEXT P
330 POKE 31737,0
340 POKE 31736,21
350 RAND USR 31152
360 FOR I=1 TO 90
370 NEXT I
380 RAND USR 30962
390 POKE 31361,21
400 POKE 31740,0
410 FOR I=1 TO 37
420 POKE 31741,I
430 RAND USR 31351
440 NEXT I
445 FOR I=1 TO 12
450 POKE 31741,151
460 RAND USR 31351
470 POKE 31741,0
480 RAND USR 31351
490 NEXT I
492 CLS
498 GOSUB 2000
499 GOSUB 4000
500 POKE 16418,0
505 PRINT AT 21,0;"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
508 PRINT AT 22,0;"% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % "
510 PRINT AT 23,0;";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"
520 LET C$="%P%R%E%S%E%N%T%I%N%G% %C%H%I%C%A%G%O%S% %O%L%D%E%S%T% %R%U%N%N%I%N%G% %S%P%E%C%I%A%L% %I%N%T%E%R%E%S%T% %G%R%O%U%P% % % % % % % % "
560 LET C$=C$+"%C%H%A%I%R%-%P%E%R%S%O%N% % %L%A%R%R%Y% %P%.% %W%E%I%G%E%L% % % % %F%O%R% %B%E%G%I%N%N%E%R%S% % %S%E%E% % %B%I%L%L% %K%E%N%T% % % % %F%O%R% %B%A%S%I%C% %P%R%O%G%R%A%M%M%I%N%G% % %S%E%E% % %K%E%N% %D%U%D%A% % % % %F%O%R% %M%A%C%H%I%N%E% %L%A%N%G%U%A%G%E% % %O%R% % %A%S%S%E%M%B%L%Y% %L%A%N%G%U%A%G%E% % %S%E%E% % %R%I%C%K% %S%H%A%N%D%R%O%S%S% % %O%R% % %R%I%C%H%A%R%D% %M%E%H%A%N% % % % "
565 LET C$=C$+"%F%O%R% %H%A%R%D%W%A%R%E% % %S%E%E% % %F%R%A%N%K% %K%E%Y%S%E%R% % %O%R% % %J%O%H%N% %M%E%N%A%R%E%K% % % "
570 LET B$=C$
1060 FOR F=0 TO 30
1065 POKE 16418,0
1070 PRINT AT 22,31-F;B$(1 TO F+1)
1080 FOR D=1 TO 3
1090 NEXT D
1100 NEXT F
1110 FOR E=1 TO LEN B$-33
1115 POKE 16418,0
1120 PRINT AT 22,0;B$(E+1 TO E+32)
1130 FOR D=1 TO 3
1140 NEXT D
1150 NEXT E
1160 FOR C=0 TO 31
1165 POKE 16418,0
1170 PRINT AT 22,0;B$(C+LEN B$-31 TO LEN B$)
1180 FOR D=1 TO 3
1190 NEXT D
1200 NEXT C
1210 CLS
1220 GOTO 10
2000 RAND USR 31017
2010 POKE 31741,128
2020 RAND USR 31351
2060 PRINT AT 4,10;"%L%O%O%K%I%N%G% %F%O%R"
2070 PRINT AT 10,5;"%I%N%E%X%P%E%N%S%I%V%E% %C%O%M%P%U%T%I%N%G% %?"
2080 FOR I=1 TO 60
2090 NEXT I
2100 PRINT AT 16,10;"%L%O%O%K% %N%O% %M%O%R%E"
2110 FOR I=1 TO 60
2120 NEXT I
2130 FOR I=1 TO 40
2140 PRINT AT 4,10;"% % %S%I%N%C%L%A%I%R% % "
2150 PRINT AT 10,5;"%S%P%E%C%I%A%L% %I%N%T%E%R%E%S%T% %G%R%O%U%P% % % "
2160 PRINT AT 16,5;"%H%A%S% %T%H%E% %A%N%S%W%E%R%S% %F%O%R% %Y%O%U"
2170 NEXT I
2180 FOR P=1 TO 40
2190 PRINT AT 4,10;"% %T%A%L%K% %T%O% %U%S"
2200 PRINT AT 10,5;"% % % %I%T% %W%O%N%T% %C%O%S%T% %Y%O%U% % % % % "
2210 PRINT AT 16,5;"% % % % % % % %A%N%Y%T%H%I%N%G% % % % % % % % % % "
2220 NEXT P
2230 CLS
2240 RAND USR 31028
2250 LET A=0
2260 LET B=42
2270 LET X=10
2280 LET Y=6
2290 PLOT A,B
2300 POKE 31733,X
2310 POKE 31732,Y
2320 RAND USR 31329
2330 LET A=12
2340 LET B=42
2350 LET X=35
2360 LET Y=29
2370 PLOT A,B
2380 POKE 31733,X
2390 POKE 31732,Y
2400 RAND USR 31329
2410 LET A=12
2420 LET B=23
2430 LET X=60
2440 LET Y=6
2450 PLOT A,B
2460 POKE 31733,X
2470 POKE 31732,Y
2480 RAND USR 31329
2490 PRINT AT 1,0;"% % % % % : % % % % % % % % % % % % "
2500 PRINT AT 2,0;": : : : : "
2510 PRINT AT 3,0;": :% % : % :' .: '''' : % % % :"
2520 PRINT AT 4,0;": : :' .:% .... : % % % :"
2530 PRINT AT 5,0;"% % % : : : : :"
2540 PRINT AT 6,0;": : % % % % % % % % % % % % "
2550 PRINT AT 7,0;"% % % % % "
2560 PRINT AT 8,0;": :"
2570 PRINT AT 9,0;"% : :% "
2580 PRINT AT 10,0;"% : :% : % % % % % % % % % % % % % % % % % % % % % % % % "
2590 PRINT AT 11,0;": :: : % % % % % % % "
2600 PRINT AT 12,0;"% % % % % : : % % % % % % % % % % % % % "
2610 PRINT AT 13,0;": :: : % % % % % % % % % % % % % "
2620 PRINT AT 14,0;": :% % % : : % % % % % % % % % % % "
2630 PRINT AT 15,0;": :% :. :: % : % % % % % % % % % % % % "
2640 PRINT AT 16,0;": :: % : % % % % % % % % % % % % "
2650 PRINT AT 17,0;":........:: : % % % % % : % % % % % ";AT 18,0;"% % % % % : % % % % % % % % % % % % % % % % % % % % % % % % "
2660 RETURN
4000 RAND USR 31465
4010 FOR I=1 TO 32
4020 RAND USR 30699
4030 NEXT I
4040 FOR I=1 TO 23
4050 RAND USR 30656
4060 NEXT I
4070 FOR I=1 TO 32
4080 RAND USR 30696
4090 NEXT I
4100 FOR I=1 TO 23
4110 RAND USR 31666
4120 NEXT I
4130 RETURN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
