Bulletin

This file is part of and Synchro-Sette March 1984. Download the collection to get this file.
Date: March 1984
Type: Program
Platform(s): TS 1000

This program implements a scrolling bulletin board display, showing an animated star-field introduction followed by marquee-style text scrolling in two separate horizontal windows. The intro uses a machine-code routine POKEd into memory at address 30000, assembled from a hex string in line 9020; the hex encodes a LDIR-based block-copy operation used to implement smooth upward scrolling of a 23-row by 32-column character array stored in X$. Inverse-video characters (rendered via % escapes) are used throughout for the star-field backdrop and title banners, with block-graphic border frames drawn around two text windows using PLOT/UNPLOT and AT-positioned strings. The scrolling windows independently support pause (“P”), backward (“B”), and forward (“F”) key controls for reader navigation.


Program Analysis

Program Structure

The program is divided into clearly separated functional blocks:

  1. Lines 10–40: Initialisation and brief startup pause.
  2. Lines 100–220: Animated star-field introduction with rotating screen rows and title reveal.
  3. Lines 230–430: Title scroll and PLOT/UNPLOT box-drawing for two display windows.
  4. Lines 4000–4540: Upper window forward/backward text scroller for string A$.
  5. Lines 5000–5540: Lower window forward/backward text scroller for string B$.
  6. Lines 6000–7110: Keyboard-polling service routines for each window.
  7. Lines 9000–9190: Subroutine: machine-code installation, array initialisation, star-field seeding.
  8. Lines 9997–9999: STOP guards, SAVE statement, and restart loop.

Machine Code Routine

The subroutine at line 9000 POKEs 19 bytes of Z80 machine code into RAM starting at address 30000. The hex string in line 9020 is decoded two nibbles at a time in lines 9030–9060 using the expression 16*CODE Z$(N)+CODE Z$(N+1)-476, which converts ASCII hex digit pairs to byte values (subtracting 476 accounts for the ASCII offsets of two ‘0’ characters: 2×(‘0’=48) × some factor — effectively mapping “00”–”FF” to 0–255).

The hex string 01D6022A0C4009545D01B5022A0C4009EDB8C9 disassembles as Z80 code:

HexMnemonicComment
01 D6 02LD BC, 02D6hByte count (726 bytes = 23 rows × 32 chars — 2)
2A 0C 40LD HL, (400Ch)Load source address from system variable area
09ADD HL, BCOffset HL forward
54LD D, HCopy HL to DE (destination)
5DLD E, L
01 B5 02LD BC, 02B5hCount for LDIR (one row less)
2A 0C 40LD HL, (400Ch)Reload source (base of X$ data)
09ADD HL, BCAdjust HL
ED B8LDDRBlock-copy downward (scroll rows up)
C9RETReturn

The routine is called via USR X (where X=30000) inside PRINT AT USR X,0 at line 170. This is an unusual dual-use: the return value of USR becomes the row argument for PRINT AT, while the primary purpose is executing the block-copy scroll. The LDDR instruction copies the array content upward by one row, implementing hardware-assisted smooth scrolling of X$.

Star-Field Introduction

The 23×32 array X$ is filled in the subroutine (lines 9080–9160) with inverse spaces (% ) and occasional inverse asterisks (%*, probability 1-in-10), creating a random star field. The main intro loop (lines 130–220) iterates 89 times, each pass calling the machine-code scroller via PRINT AT USR X,0;X$(C) to rotate rows. SLOW mode is engaged at iteration 2 to control display speed.

At fixed iteration counts, text is injected into row 22 of the array to reveal the title sequence:

  • N=23: SYNCHRO-SETTE (inverse video)
  • N=45: PRESENTS (inverse video)
  • N=67: A row of inverse asterisks/spaces

Window Borders and Block Graphics

Lines 500–510 draw two decorative border boxes using PRINT AT with ZX block-graphic escape sequences. Each box comprises three rows: a top row of ▛▀▀…▀▀▜ characters, a blank middle row with side bars, and a bottom row of ▙▄▄…▄▄▟ characters. Lines 320–430 additionally use PLOT and UNPLOT to draw pixel-level horizontal and vertical lines, forming a secondary frame around the upper window area.

Dual Scrolling Windows

Two independent text marquees scroll 28-character windows through strings A$ (upper, row 4) and B$ (lower, row 17). Each window has its own forward loop (4000/5000), backward loop (4500/5500), and keyboard service routine (6000/7000). The scrollers use substring slicing: A$(N TO N+27) advances one character per frame.

Keyboard Control Idiom

The service routines at 6000 and 7000 poll INKEY$ without a preceding PAUSE 0, meaning keys are sampled once per scroll step rather than blocking. Supported keys are:

  • PPAUSE 40000 (long freeze, effectively stops until key released)
  • B — jump to backward-scroll loop
  • F — forward (skip ahead); however, lines 6100 and 7100 assign N=I, where I is not defined in the forward loop scope, which is a latent bug

Notable Techniques

  • Using PRINT AT USR addr, col; string to invoke machine code while simultaneously positioning the cursor — the MC return value doubles as the AT row parameter.
  • Hex string decoding via character arithmetic: 16*CODE Z$(N)+CODE Z$(N+1)-476 is a compact inline hex-to-byte converter.
  • LDDR (decrement block copy) for upward array scrolling without moving the array base pointer.
  • The SAVE "BULLETI%N" at line 9998 uses an inverse-video N in the filename, which is an aesthetic choice visible on directory listings.

Content

Appears On

Cassette to accompany the March 1984 issue of Synchro-Sette.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

  10 LET P=11
  20 LET Q=14
  30 PRINT AT 11,14;"WAIT"
  40 PAUSE 20
 100 CLS 
 110 GOSUB 9000
 120 LET A=1
 130 FOR N=1 TO 89
 135 LET B=A+1
 140 IF B=23 THEN LET B=1
 150 LET C=A-1
 160 IF C=0 THEN LET C=22
 170 PRINT AT USR X,0;X$(C)
 180 LET A=C
 190 IF N=2 THEN SLOW 
 200 IF N=23 THEN LET X$(22,10 TO 22)="%S%Y%N%C%H%R%O%-%S%E%T%T%E"
 210 IF N=45 THEN LET X$(22,10 TO 22)="% % %P%R%E%S%E%N%T%S% % % "
 215 IF N=67 THEN LET X$(22,10 TO 22)="% % % % %*% % % % % % % % "
 220 NEXT N
 230 SCROLL 
 240 PRINT "% % %*% % %*% %T%H%E% %B%U%L%L%E%T%I%N% %B%O%A%R%D% %*% % % % % "
 250 SCROLL 
 260 PRINT "% % % % % %*% % % % % %M%A%R%C%H% %1%9%8%4% % % % % %*% % % % % "
 280 FOR N=1 TO 10
 290 SCROLL 
 300 PRINT X$(N)
 310 NEXT N
 320 FOR N=13 TO 50
 330 UNPLOT N,19
 340 UNPLOT N,24
 350 PLOT N,18
 360 PLOT N,25
 370 NEXT N
 380 FOR N=19 TO 24
 390 UNPLOT 12,N
 400 UNPLOT 51,N
 430 NEXT N
 500 PRINT AT 3,1;"\:'\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\':";AT 4,1;"\: ";AT 4,30;"\ :";AT 5,1;"\:.\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\.:"
 510 PRINT AT 16,1;"\:'\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\':";AT 17,1;"\: ";AT 17,30;"\ :";AT 18,1;"\:.\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\.:"
\n4000 FOR N=1 TO LEN A$-28
\n4010 PRINT AT 4,2;A$(N TO N+27)
\n4020 GOSUB 6000
\n4030 NEXT N
\n4040 GOTO 5000
\n4500 FOR I=N TO 1 STEP -1
\n4510 PRINT AT 4,2;A$(I TO I+27)
\n4520 GOSUB 6000
\n4530 NEXT I
\n4540 GOTO 4000
\n5000 FOR N=1 TO LEN B$-28
\n5010 PRINT AT 17,2;B$(N TO N+27)
\n5020 GOSUB 7000
\n5030 NEXT N
\n5040 GOTO 4000
\n5500 FOR I=N TO 1 STEP -1
\n5510 PRINT AT 17,2;B$(I TO I+27)
\n5520 GOSUB 7000
\n5530 NEXT I
\n5540 GOTO 5000
\n6000 IF INKEY$="P" THEN PAUSE 40000
\n6010 IF INKEY$="B" THEN GOTO 4500
\n6020 IF INKEY$="F" THEN GOTO 6100
\n6090 RETURN 
\n6100 LET N=I
\n6110 GOTO 4030
\n7000 IF INKEY$="P" THEN PAUSE 40000
\n7010 IF INKEY$="B" THEN GOTO 5500
\n7020 IF INKEY$="F" THEN GOTO 7100
\n7090 RETURN 
\n7100 LET N=I
\n7110 GOTO 5030
\n7500 FOR I=N TO 1 STEP -1
\n7520 PRINT AT 17,2;B$(I TO I+27)
\n8999 STOP 
\n9000 FAST 
\n9010 LET X=30000
\n9020 LET Z$="01D6022A0C4009545D01B5022A0C4009EDB8C9"
\n9030 FOR N=1 TO LEN Z$-1 STEP 2
\n9040 POKE X,16*CODE Z$(N)+CODE Z$(N+1)-476
\n9050 LET X=X+1
\n9060 NEXT N
\n9070 LET X=30000
\n9080 DIM X$(23,32)
\n9090 FOR N=1 TO 23
\n9100 FOR I=1 TO 32
\n9110 LET J=INT (RND*10)
\n9120 LET X$(N,I)="% "
\n9130 IF J=5 THEN LET X$(N,I)="%*"
\n9140 NEXT I
\n9150 IF N<>23 THEN PRINT X$(N)
\n9160 NEXT N
\n9170 LET XX=INT (RND*26)+4
\n9190 RETURN 
\n9997 STOP 
\n9998 SAVE "BULLETI%N"
\n9999 GOTO 1

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

People

No people associated with this content.

Scroll to Top