This program implements a scrolling bulletin board display for the Synchro-Sette June 1983 issue. It uses a machine code routine embedded in the REM statement at line 10 — the bytes decode to a LDDR-based block memory copy, called via USR to scroll the display. The program builds a 24×32 string array Z$() pre-filled with alternating inverse-space patterns and checkerboard rows, then continuously scrolls rows upward by cycling through the array. Two ticker-tape style text strings A$ and B$ are scrolled horizontally across banner boxes drawn with block graphics characters. A keypress (detected via INKEY$) triggers a PAUSE 40000 hold, and the SAVE command at line 9998 uses an inverse-video character in the filename as an auto-run flag.
Program Analysis
Program Structure
The program divides into several functional phases:
- Initialisation (lines 20–80): Switches to FAST mode, calculates a base address offset into
X, builds the 24×32 display buffer arrayZ$()pre-filled with alternating inverse-space and checkerboard rows, then returns to SLOW mode. - Main scroll loop (lines 180–260): Cycles variable
Athrough rows 1–22, printing each row at the screen position returned byUSR 16514, creating a continuous vertical scroll effect. - Subroutine at 300 (lines 300–340): Manages a counter
Dto phase in title text intoZ$(1)at specific thresholds, then falls through to the banner/box drawing sequence onceD>65. - Banner display (lines 350–620): Clears the screen with scrolls and PRINT, draws a decorative box using block graphics, animates the title string sideways across row 1, and prints the “JUNE 1983” date.
- Horizontal text scrollers (lines 3000–3080): Scroll strings
A$andB$character-by-character across the top and bottom banner boxes in an infinite loop. - Pause handler (lines 4000–4010): On any keypress, freezes display for approximately 40 seconds before returning.
Machine Code Routine in REM
Line 10 contains a machine code routine embedded directly in the REM statement body. The bytes are:
| Offset | Hex | Mnemonic | Notes |
|---|---|---|---|
| 0 | 01 D6 02 | LD BC, 02D6h | Byte count = 726 (approx. 22 text rows × 33 bytes) |
| 3 | 2A 0C 40 | LD HL, (400Ch) | Load HL from system variable (VARS area pointer) |
| 6 | 09 | ADD HL, BC | Advance HL by block count |
| 7 | 54 | LD D, H | |
| 8 | 5D | LD E, L | DE = HL (destination) |
| 9 | 01 B5 02 | LD BC, 02B5h | Second byte count |
| 12 | 2A 0C 40 | LD HL, (400Ch) | Reload HL from same system variable |
| 15 | 09 | ADD HL, BC | |
| 16 | ED B8 | LDDR | Block copy backwards |
| 18 | C9 | RET |
The routine performs a backwards block memory copy (LDDR) to shift a region of the display file or string array upward by one row. It is called indirectly via USR 16514 in the PRINT AT statement at lines 240 and 520 — 16514 (4002h) is the address of the second byte of the REM line’s data, i.e. the first byte of the machine code.
Display Buffer Technique
Rather than printing directly to the screen, the program maintains a 24×32 string array Z$() that acts as a software frame buffer. Each element holds one display row as a 32-character string. The main loop prints individual rows at the current screen position via PRINT AT USR 16514,0;Z$(C), where the machine code side-effect of USR provides the scroll, and the PRINT renders the next row.
Rows that are multiples of 3 are initialised (line 65) to a checkerboard pattern of alternating @ and # inverse-video pairs, providing a visual border between content rows. All other rows use the inverse-space pattern stored in Q$.
Key BASIC Idioms
- Inverse-video strings:
Q$at line 35 is built entirely from inverse-space characters, providing a filled background row. Titles at lines 300–310 use inverse letters throughout. - Wrap-around counter: Lines 210 and 230 wrap
BandCat the array boundaries (1–22) to achieve continuous circular scrolling without an array bounds error. - Horizontal scroll via substring: Lines 3000–3080 iterate
Nfrom 1 toLEN A$-28, printingA$(N TO N+27)to scroll a 28-character window across the full string one character per frame. - POKE 16418,0 at line 540 clears the ZX81 system variable
CDFLAG(or equivalent TS1000 flag), forcing the display back to a known state after mode transitions.
Block Graphics Box Drawing
Lines 570–610 draw two decorative rectangular boxes using ZX81 block graphic characters. The top and bottom edges use ▖▄▄▄…▄▖ style sequences, the sides use ▌ and ▐, and the corners are formed by appropriate quadrant characters. The inner box spanning rows 10–13 holds the “SYNCHRO-SETTE PRESENTS” / bulletin board title area, while the outer box spanning rows 2–21 frames the scrolling text display.
Notable Techniques
- The
Dcounter in the GOSUB 300 subroutine acts as a state machine: atD>1the first title line appears; atD>24it changes to the full bulletin board title; atD>65execution falls through to the banner drawing code rather than returning, effectively a computed GOTO via threshold comparison. - The
Xvariable computed at line 30 (PEEK 16404 + 256*PEEK 16405 - 794) calculates an offset into the display file based on the D-FILE pointer, butXis never subsequently used in the listing — it may be a remnant of an earlier version or used by the machine code to locate data. - The horizontal title animation at lines 460–500 prepends an extra inverse-space to
R$on each iteration while printing at column25down to column11(25 − 15 + 1 = 11), creating a slide-in effect from the right edge.
Bugs and Anomalies
A$andB$are referenced at lines 3000–3070 but never defined or loaded in the visible listing. They are presumably loaded from tape before this program runs, or the listing is incomplete.- The horizontal scroller loop at line 3000 uses
LEN A$-28without guarding againstLEN A$<28, which would cause a negative subscript error if a short string were loaded. - Line 380
PRINT AT 2,0;"";prints an empty string, which serves only to position the cursor — a common ZX81 idiom but unusual when followed immediately by a FOR/PRINT loop that positions its own output.
Content
Source Code
10 REM itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57613 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"\D6
Skip to content
Bulletin
This file is part of and Synchro-Sette June 1983. Download the collection to get this file.
This program implements a scrolling bulletin board display for the Synchro-Sette June 1983 issue. It uses a machine code routine embedded in the REM statement at line 10 — the bytes decode to a LDDR-based block memory copy, called via USR to scroll the display. The program builds a 24×32 string array Z$() pre-filled with alternating inverse-space patterns and checkerboard rows, then continuously scrolls rows upward by cycling through the array. Two ticker-tape style text strings A$ and B$ are scrolled horizontally across banner boxes drawn with block graphics characters. A keypress (detected via INKEY$) triggers a PAUSE 40000 hold, and the SAVE command at line 9998 uses an inverse-video character in the filename as an auto-run flag.
Program Analysis
Program Structure
The program divides into several functional phases:
- Initialisation (lines 20–80): Switches to FAST mode, calculates a base address offset into
X, builds the 24×32 display buffer array Z$() pre-filled with alternating inverse-space and checkerboard rows, then returns to SLOW mode.
- Main scroll loop (lines 180–260): Cycles variable
A through rows 1–22, printing each row at the screen position returned by USR 16514, creating a continuous vertical scroll effect.
- Subroutine at 300 (lines 300–340): Manages a counter
D to phase in title text into Z$(1) at specific thresholds, then falls through to the banner/box drawing sequence once D>65.
- Banner display (lines 350–620): Clears the screen with scrolls and PRINT, draws a decorative box using block graphics, animates the title string sideways across row 1, and prints the “JUNE 1983” date.
- Horizontal text scrollers (lines 3000–3080): Scroll strings
A$ and B$ character-by-character across the top and bottom banner boxes in an infinite loop.
- Pause handler (lines 4000–4010): On any keypress, freezes display for approximately 40 seconds before returning.
Machine Code Routine in REM
Line 10 contains a machine code routine embedded directly in the REM statement body. The bytes are:
Offset Hex Mnemonic Notes 0 01 D6 02LD BC, 02D6h Byte count = 726 (approx. 22 text rows × 33 bytes) 3 2A 0C 40LD HL, (400Ch) Load HL from system variable (VARS area pointer) 6 09ADD HL, BC Advance HL by block count 7 54LD D, H 8 5DLD E, L DE = HL (destination) 9 01 B5 02LD BC, 02B5h Second byte count 12 2A 0C 40LD HL, (400Ch) Reload HL from same system variable 15 09ADD HL, BC 16 ED B8LDDR Block copy backwards 18 C9RET
The routine performs a backwards block memory copy (LDDR) to shift a region of the display file or string array upward by one row. It is called indirectly via USR 16514 in the PRINT AT statement at lines 240 and 520 — 16514 (4002h) is the address of the second byte of the REM line’s data, i.e. the first byte of the machine code.
Display Buffer Technique
Rather than printing directly to the screen, the program maintains a 24×32 string array Z$() that acts as a software frame buffer. Each element holds one display row as a 32-character string. The main loop prints individual rows at the current screen position via PRINT AT USR 16514,0;Z$(C), where the machine code side-effect of USR provides the scroll, and the PRINT renders the next row.
Rows that are multiples of 3 are initialised (line 65) to a checkerboard pattern of alternating @ and # inverse-video pairs, providing a visual border between content rows. All other rows use the inverse-space pattern stored in Q$.
Key BASIC Idioms
- Inverse-video strings:
Q$ at line 35 is built entirely from inverse-space characters, providing a filled background row. Titles at lines 300–310 use inverse letters throughout.
- Wrap-around counter: Lines 210 and 230 wrap
B and C at the array boundaries (1–22) to achieve continuous circular scrolling without an array bounds error.
- Horizontal scroll via substring: Lines 3000–3080 iterate
N from 1 to LEN A$-28, printing A$(N TO N+27) to scroll a 28-character window across the full string one character per frame.
- POKE 16418,0 at line 540 clears the ZX81 system variable
CDFLAG (or equivalent TS1000 flag), forcing the display back to a known state after mode transitions.
Block Graphics Box Drawing
Lines 570–610 draw two decorative rectangular boxes using ZX81 block graphic characters. The top and bottom edges use ▖▄▄▄…▄▖ style sequences, the sides use ▌ and ▐, and the corners are formed by appropriate quadrant characters. The inner box spanning rows 10–13 holds the “SYNCHRO-SETTE PRESENTS” / bulletin board title area, while the outer box spanning rows 2–21 frames the scrolling text display.
Notable Techniques
- The
D counter in the GOSUB 300 subroutine acts as a state machine: at D>1 the first title line appears; at D>24 it changes to the full bulletin board title; at D>65 execution falls through to the banner drawing code rather than returning, effectively a computed GOTO via threshold comparison.
- The
X variable computed at line 30 (PEEK 16404 + 256*PEEK 16405 - 794) calculates an offset into the display file based on the D-FILE pointer, but X is never subsequently used in the listing — it may be a remnant of an earlier version or used by the machine code to locate data.
- The horizontal title animation at lines 460–500 prepends an extra inverse-space to
R$ on each iteration while printing at column 25 down to column 11 (25 − 15 + 1 = 11), creating a slide-in effect from the right edge.
Bugs and Anomalies
A$ and B$ are referenced at lines 3000–3070 but never defined or loaded in the visible listing. They are presumably loaded from tape before this program runs, or the listing is incomplete.
- The horizontal scroller loop at line 3000 uses
LEN A$-28 without guarding against LEN A$<28, which would cause a negative subscript error if a short string were loaded.
- Line 380
PRINT AT 2,0;""; prints an empty string, which serves only to position the cursor — a common ZX81 idiom but unusual when followed immediately by a FOR/PRINT loop that positions its own output.
Content
Source Code
10 REM \01\D6\02\2A\0C\40\09\54\5D\01\B5\02\2A\0C\40\09\ED\B8\C9
20 FAST
30 LET X=PEEK 16404+256*PEEK 16405-794
35 LET Q$="% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % "
40 DIM Z$(24,32)
50 FOR N=1 TO 22
60 LET Z$(N)=Q$
65 IF N/3=INT (N/3) THEN LET Z$(N)="\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##"
70 NEXT N
80 SLOW
180 LET D=0
190 LET A=1
200 LET B=A+1
205 GOSUB 300
210 IF B=23 THEN LET B=1
220 LET C=A-1
230 IF C=0 THEN LET C=22
240 PRINT AT USR 16514,0;Z$(C)
250 LET A=C
260 GOTO 200
300 IF D>1 THEN LET Z$(1)="% % % % % %S%Y%N%C%H%R%O%-%S%E%T%T%E% %P%R%E%S%E%N%T%S% % % % % "
310 IF D>24 THEN LET Z$(1)="%T%H%E% %S%Y%N%C%H%R%O%-%S%E%T%T%E% %B%U%L%L%E%T%I%N% %B%O%A%R%D"
320 LET D=D+1
330 IF D>65 THEN GOTO 350
340 RETURN
350 FOR N=1 TO 20
360 SCROLL
370 NEXT N
380 PRINT AT 2,0;"";
390 FOR N=1 TO 20
400 PRINT Q$
410 NEXT N
420 LET R$="% "+Z$(1)
430 FOR N=0 TO 6
440 PRINT AT 1,0+N;R$
450 NEXT N
460 LET R$="% %B%U%L%L%E%T%I%N% % %B%O%A%R%D% "
470 FOR N=1 TO 15
480 PRINT AT 1,25;R$
490 LET R$="% "+R$
500 NEXT N
510 FOR N=1 TO 10
520 PRINT AT USR 16514,0;Q$
530 NEXT N
540 POKE 16418,0
550 PRINT AT 22,0;Q$
560 PRINT AT 23,0;Q$
570 PRINT AT 10,6;"\ .\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\. ";AT 11,6;"\ :";AT 11,24;"\: ";AT 12,6;"\ :";AT 12,24;"\: ";AT 13,6;"\ '\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\' "
580 FOR N=1 TO 30
590 PRINT AT 2,N;"\''";AT 4,N;"\..";AT 19,N;"\''";AT 21,N;"\.."
600 NEXT N
610 PRINT AT 3,1;"\ :";AT 3,30;"\: ";AT 20,1;"\ :";AT 20,30;"\: "
620 PRINT AT 7,14;"%J%U%N%E";AT 16,14;"%1%9%8%3"
3000 FOR N=1 TO LEN A$-28
3010 PRINT AT 3,2;A$(N TO N+27)
3020 IF INKEY$<>"" THEN GOSUB 4000
3030 NEXT N
3040 FOR N=1 TO LEN B$-28
3050 PRINT AT 20,2;B$(N TO N+27)
3060 IF INKEY$<>"" THEN GOSUB 4000
3070 NEXT N
3080 GOTO 3000
4000 PAUSE 40000
4010 RETURN
9998 SAVE "BULLETI%N"
9999 GOTO 0
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
Skip to content
Bulletin
This file is part of and Synchro-Sette June 1983. Download the collection to get this file.
This program implements a scrolling bulletin board display for the Synchro-Sette June 1983 issue. It uses a machine code routine embedded in the REM statement at line 10 — the bytes decode to a LDDR-based block memory copy, called via USR to scroll the display. The program builds a 24×32 string array Z$() pre-filled with alternating inverse-space patterns and checkerboard rows, then continuously scrolls rows upward by cycling through the array. Two ticker-tape style text strings A$ and B$ are scrolled horizontally across banner boxes drawn with block graphics characters. A keypress (detected via INKEY$) triggers a PAUSE 40000 hold, and the SAVE command at line 9998 uses an inverse-video character in the filename as an auto-run flag.
Program Analysis
Program Structure
The program divides into several functional phases:
- Initialisation (lines 20–80): Switches to FAST mode, calculates a base address offset into
X, builds the 24×32 display buffer array Z$() pre-filled with alternating inverse-space and checkerboard rows, then returns to SLOW mode.
- Main scroll loop (lines 180–260): Cycles variable
A through rows 1–22, printing each row at the screen position returned by USR 16514, creating a continuous vertical scroll effect.
- Subroutine at 300 (lines 300–340): Manages a counter
D to phase in title text into Z$(1) at specific thresholds, then falls through to the banner/box drawing sequence once D>65.
- Banner display (lines 350–620): Clears the screen with scrolls and PRINT, draws a decorative box using block graphics, animates the title string sideways across row 1, and prints the “JUNE 1983” date.
- Horizontal text scrollers (lines 3000–3080): Scroll strings
A$ and B$ character-by-character across the top and bottom banner boxes in an infinite loop.
- Pause handler (lines 4000–4010): On any keypress, freezes display for approximately 40 seconds before returning.
Machine Code Routine in REM
Line 10 contains a machine code routine embedded directly in the REM statement body. The bytes are:
Offset Hex Mnemonic Notes 0 01 D6 02LD BC, 02D6h Byte count = 726 (approx. 22 text rows × 33 bytes) 3 2A 0C 40LD HL, (400Ch) Load HL from system variable (VARS area pointer) 6 09ADD HL, BC Advance HL by block count 7 54LD D, H 8 5DLD E, L DE = HL (destination) 9 01 B5 02LD BC, 02B5h Second byte count 12 2A 0C 40LD HL, (400Ch) Reload HL from same system variable 15 09ADD HL, BC 16 ED B8LDDR Block copy backwards 18 C9RET
The routine performs a backwards block memory copy (LDDR) to shift a region of the display file or string array upward by one row. It is called indirectly via USR 16514 in the PRINT AT statement at lines 240 and 520 — 16514 (4002h) is the address of the second byte of the REM line’s data, i.e. the first byte of the machine code.
Display Buffer Technique
Rather than printing directly to the screen, the program maintains a 24×32 string array Z$() that acts as a software frame buffer. Each element holds one display row as a 32-character string. The main loop prints individual rows at the current screen position via PRINT AT USR 16514,0;Z$(C), where the machine code side-effect of USR provides the scroll, and the PRINT renders the next row.
Rows that are multiples of 3 are initialised (line 65) to a checkerboard pattern of alternating @ and # inverse-video pairs, providing a visual border between content rows. All other rows use the inverse-space pattern stored in Q$.
Key BASIC Idioms
- Inverse-video strings:
Q$ at line 35 is built entirely from inverse-space characters, providing a filled background row. Titles at lines 300–310 use inverse letters throughout.
- Wrap-around counter: Lines 210 and 230 wrap
B and C at the array boundaries (1–22) to achieve continuous circular scrolling without an array bounds error.
- Horizontal scroll via substring: Lines 3000–3080 iterate
N from 1 to LEN A$-28, printing A$(N TO N+27) to scroll a 28-character window across the full string one character per frame.
- POKE 16418,0 at line 540 clears the ZX81 system variable
CDFLAG (or equivalent TS1000 flag), forcing the display back to a known state after mode transitions.
Block Graphics Box Drawing
Lines 570–610 draw two decorative rectangular boxes using ZX81 block graphic characters. The top and bottom edges use ▖▄▄▄…▄▖ style sequences, the sides use ▌ and ▐, and the corners are formed by appropriate quadrant characters. The inner box spanning rows 10–13 holds the “SYNCHRO-SETTE PRESENTS” / bulletin board title area, while the outer box spanning rows 2–21 frames the scrolling text display.
Notable Techniques
- The
D counter in the GOSUB 300 subroutine acts as a state machine: at D>1 the first title line appears; at D>24 it changes to the full bulletin board title; at D>65 execution falls through to the banner drawing code rather than returning, effectively a computed GOTO via threshold comparison.
- The
X variable computed at line 30 (PEEK 16404 + 256*PEEK 16405 - 794) calculates an offset into the display file based on the D-FILE pointer, but X is never subsequently used in the listing — it may be a remnant of an earlier version or used by the machine code to locate data.
- The horizontal title animation at lines 460–500 prepends an extra inverse-space to
R$ on each iteration while printing at column 25 down to column 11 (25 − 15 + 1 = 11), creating a slide-in effect from the right edge.
Bugs and Anomalies
A$ and B$ are referenced at lines 3000–3070 but never defined or loaded in the visible listing. They are presumably loaded from tape before this program runs, or the listing is incomplete.
- The horizontal scroller loop at line 3000 uses
LEN A$-28 without guarding against LEN A$<28, which would cause a negative subscript error if a short string were loaded.
- Line 380
PRINT AT 2,0;""; prints an empty string, which serves only to position the cursor — a common ZX81 idiom but unusual when followed immediately by a FOR/PRINT loop that positions its own output.
Content
Source Code
10 REM \01\D6\02\2A\0C\40\09\54\5D\01\B5\02\2A\0C\40\09\ED\B8\C9
20 FAST
30 LET X=PEEK 16404+256*PEEK 16405-794
35 LET Q$="% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % "
40 DIM Z$(24,32)
50 FOR N=1 TO 22
60 LET Z$(N)=Q$
65 IF N/3=INT (N/3) THEN LET Z$(N)="\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##"
70 NEXT N
80 SLOW
180 LET D=0
190 LET A=1
200 LET B=A+1
205 GOSUB 300
210 IF B=23 THEN LET B=1
220 LET C=A-1
230 IF C=0 THEN LET C=22
240 PRINT AT USR 16514,0;Z$(C)
250 LET A=C
260 GOTO 200
300 IF D>1 THEN LET Z$(1)="% % % % % %S%Y%N%C%H%R%O%-%S%E%T%T%E% %P%R%E%S%E%N%T%S% % % % % "
310 IF D>24 THEN LET Z$(1)="%T%H%E% %S%Y%N%C%H%R%O%-%S%E%T%T%E% %B%U%L%L%E%T%I%N% %B%O%A%R%D"
320 LET D=D+1
330 IF D>65 THEN GOTO 350
340 RETURN
350 FOR N=1 TO 20
360 SCROLL
370 NEXT N
380 PRINT AT 2,0;"";
390 FOR N=1 TO 20
400 PRINT Q$
410 NEXT N
420 LET R$="% "+Z$(1)
430 FOR N=0 TO 6
440 PRINT AT 1,0+N;R$
450 NEXT N
460 LET R$="% %B%U%L%L%E%T%I%N% % %B%O%A%R%D% "
470 FOR N=1 TO 15
480 PRINT AT 1,25;R$
490 LET R$="% "+R$
500 NEXT N
510 FOR N=1 TO 10
520 PRINT AT USR 16514,0;Q$
530 NEXT N
540 POKE 16418,0
550 PRINT AT 22,0;Q$
560 PRINT AT 23,0;Q$
570 PRINT AT 10,6;"\ .\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\. ";AT 11,6;"\ :";AT 11,24;"\: ";AT 12,6;"\ :";AT 12,24;"\: ";AT 13,6;"\ '\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\' "
580 FOR N=1 TO 30
590 PRINT AT 2,N;"\''";AT 4,N;"\..";AT 19,N;"\''";AT 21,N;"\.."
600 NEXT N
610 PRINT AT 3,1;"\ :";AT 3,30;"\: ";AT 20,1;"\ :";AT 20,30;"\: "
620 PRINT AT 7,14;"%J%U%N%E";AT 16,14;"%1%9%8%3"
3000 FOR N=1 TO LEN A$-28
3010 PRINT AT 3,2;A$(N TO N+27)
3020 IF INKEY$<>"" THEN GOSUB 4000
3030 NEXT N
3040 FOR N=1 TO LEN B$-28
3050 PRINT AT 20,2;B$(N TO N+27)
3060 IF INKEY$<>"" THEN GOSUB 4000
3070 NEXT N
3080 GOTO 3000
4000 PAUSE 40000
4010 RETURN
9998 SAVE "BULLETI%N"
9999 GOTO 0
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
A
Skip to content
Bulletin
This file is part of and Synchro-Sette June 1983. Download the collection to get this file.
This program implements a scrolling bulletin board display for the Synchro-Sette June 1983 issue. It uses a machine code routine embedded in the REM statement at line 10 — the bytes decode to a LDDR-based block memory copy, called via USR to scroll the display. The program builds a 24×32 string array Z$() pre-filled with alternating inverse-space patterns and checkerboard rows, then continuously scrolls rows upward by cycling through the array. Two ticker-tape style text strings A$ and B$ are scrolled horizontally across banner boxes drawn with block graphics characters. A keypress (detected via INKEY$) triggers a PAUSE 40000 hold, and the SAVE command at line 9998 uses an inverse-video character in the filename as an auto-run flag.
Program Analysis
Program Structure
The program divides into several functional phases:
- Initialisation (lines 20–80): Switches to FAST mode, calculates a base address offset into
X, builds the 24×32 display buffer array Z$() pre-filled with alternating inverse-space and checkerboard rows, then returns to SLOW mode.
- Main scroll loop (lines 180–260): Cycles variable
A through rows 1–22, printing each row at the screen position returned by USR 16514, creating a continuous vertical scroll effect.
- Subroutine at 300 (lines 300–340): Manages a counter
D to phase in title text into Z$(1) at specific thresholds, then falls through to the banner/box drawing sequence once D>65.
- Banner display (lines 350–620): Clears the screen with scrolls and PRINT, draws a decorative box using block graphics, animates the title string sideways across row 1, and prints the “JUNE 1983” date.
- Horizontal text scrollers (lines 3000–3080): Scroll strings
A$ and B$ character-by-character across the top and bottom banner boxes in an infinite loop.
- Pause handler (lines 4000–4010): On any keypress, freezes display for approximately 40 seconds before returning.
Machine Code Routine in REM
Line 10 contains a machine code routine embedded directly in the REM statement body. The bytes are:
Offset Hex Mnemonic Notes 0 01 D6 02LD BC, 02D6h Byte count = 726 (approx. 22 text rows × 33 bytes) 3 2A 0C 40LD HL, (400Ch) Load HL from system variable (VARS area pointer) 6 09ADD HL, BC Advance HL by block count 7 54LD D, H 8 5DLD E, L DE = HL (destination) 9 01 B5 02LD BC, 02B5h Second byte count 12 2A 0C 40LD HL, (400Ch) Reload HL from same system variable 15 09ADD HL, BC 16 ED B8LDDR Block copy backwards 18 C9RET
The routine performs a backwards block memory copy (LDDR) to shift a region of the display file or string array upward by one row. It is called indirectly via USR 16514 in the PRINT AT statement at lines 240 and 520 — 16514 (4002h) is the address of the second byte of the REM line’s data, i.e. the first byte of the machine code.
Display Buffer Technique
Rather than printing directly to the screen, the program maintains a 24×32 string array Z$() that acts as a software frame buffer. Each element holds one display row as a 32-character string. The main loop prints individual rows at the current screen position via PRINT AT USR 16514,0;Z$(C), where the machine code side-effect of USR provides the scroll, and the PRINT renders the next row.
Rows that are multiples of 3 are initialised (line 65) to a checkerboard pattern of alternating @ and # inverse-video pairs, providing a visual border between content rows. All other rows use the inverse-space pattern stored in Q$.
Key BASIC Idioms
- Inverse-video strings:
Q$ at line 35 is built entirely from inverse-space characters, providing a filled background row. Titles at lines 300–310 use inverse letters throughout.
- Wrap-around counter: Lines 210 and 230 wrap
B and C at the array boundaries (1–22) to achieve continuous circular scrolling without an array bounds error.
- Horizontal scroll via substring: Lines 3000–3080 iterate
N from 1 to LEN A$-28, printing A$(N TO N+27) to scroll a 28-character window across the full string one character per frame.
- POKE 16418,0 at line 540 clears the ZX81 system variable
CDFLAG (or equivalent TS1000 flag), forcing the display back to a known state after mode transitions.
Block Graphics Box Drawing
Lines 570–610 draw two decorative rectangular boxes using ZX81 block graphic characters. The top and bottom edges use ▖▄▄▄…▄▖ style sequences, the sides use ▌ and ▐, and the corners are formed by appropriate quadrant characters. The inner box spanning rows 10–13 holds the “SYNCHRO-SETTE PRESENTS” / bulletin board title area, while the outer box spanning rows 2–21 frames the scrolling text display.
Notable Techniques
- The
D counter in the GOSUB 300 subroutine acts as a state machine: at D>1 the first title line appears; at D>24 it changes to the full bulletin board title; at D>65 execution falls through to the banner drawing code rather than returning, effectively a computed GOTO via threshold comparison.
- The
X variable computed at line 30 (PEEK 16404 + 256*PEEK 16405 - 794) calculates an offset into the display file based on the D-FILE pointer, but X is never subsequently used in the listing — it may be a remnant of an earlier version or used by the machine code to locate data.
- The horizontal title animation at lines 460–500 prepends an extra inverse-space to
R$ on each iteration while printing at column 25 down to column 11 (25 − 15 + 1 = 11), creating a slide-in effect from the right edge.
Bugs and Anomalies
A$ and B$ are referenced at lines 3000–3070 but never defined or loaded in the visible listing. They are presumably loaded from tape before this program runs, or the listing is incomplete.
- The horizontal scroller loop at line 3000 uses
LEN A$-28 without guarding against LEN A$<28, which would cause a negative subscript error if a short string were loaded.
- Line 380
PRINT AT 2,0;""; prints an empty string, which serves only to position the cursor — a common ZX81 idiom but unusual when followed immediately by a FOR/PRINT loop that positions its own output.
Content
Source Code
10 REM \01\D6\02\2A\0C\40\09\54\5D\01\B5\02\2A\0C\40\09\ED\B8\C9
20 FAST
30 LET X=PEEK 16404+256*PEEK 16405-794
35 LET Q$="% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % "
40 DIM Z$(24,32)
50 FOR N=1 TO 22
60 LET Z$(N)=Q$
65 IF N/3=INT (N/3) THEN LET Z$(N)="\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##"
70 NEXT N
80 SLOW
180 LET D=0
190 LET A=1
200 LET B=A+1
205 GOSUB 300
210 IF B=23 THEN LET B=1
220 LET C=A-1
230 IF C=0 THEN LET C=22
240 PRINT AT USR 16514,0;Z$(C)
250 LET A=C
260 GOTO 200
300 IF D>1 THEN LET Z$(1)="% % % % % %S%Y%N%C%H%R%O%-%S%E%T%T%E% %P%R%E%S%E%N%T%S% % % % % "
310 IF D>24 THEN LET Z$(1)="%T%H%E% %S%Y%N%C%H%R%O%-%S%E%T%T%E% %B%U%L%L%E%T%I%N% %B%O%A%R%D"
320 LET D=D+1
330 IF D>65 THEN GOTO 350
340 RETURN
350 FOR N=1 TO 20
360 SCROLL
370 NEXT N
380 PRINT AT 2,0;"";
390 FOR N=1 TO 20
400 PRINT Q$
410 NEXT N
420 LET R$="% "+Z$(1)
430 FOR N=0 TO 6
440 PRINT AT 1,0+N;R$
450 NEXT N
460 LET R$="% %B%U%L%L%E%T%I%N% % %B%O%A%R%D% "
470 FOR N=1 TO 15
480 PRINT AT 1,25;R$
490 LET R$="% "+R$
500 NEXT N
510 FOR N=1 TO 10
520 PRINT AT USR 16514,0;Q$
530 NEXT N
540 POKE 16418,0
550 PRINT AT 22,0;Q$
560 PRINT AT 23,0;Q$
570 PRINT AT 10,6;"\ .\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\. ";AT 11,6;"\ :";AT 11,24;"\: ";AT 12,6;"\ :";AT 12,24;"\: ";AT 13,6;"\ '\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\' "
580 FOR N=1 TO 30
590 PRINT AT 2,N;"\''";AT 4,N;"\..";AT 19,N;"\''";AT 21,N;"\.."
600 NEXT N
610 PRINT AT 3,1;"\ :";AT 3,30;"\: ";AT 20,1;"\ :";AT 20,30;"\: "
620 PRINT AT 7,14;"%J%U%N%E";AT 16,14;"%1%9%8%3"
3000 FOR N=1 TO LEN A$-28
3010 PRINT AT 3,2;A$(N TO N+27)
3020 IF INKEY$<>"" THEN GOSUB 4000
3030 NEXT N
3040 FOR N=1 TO LEN B$-28
3050 PRINT AT 20,2;B$(N TO N+27)
3060 IF INKEY$<>"" THEN GOSUB 4000
3070 NEXT N
3080 GOTO 3000
4000 PAUSE 40000
4010 RETURN
9998 SAVE "BULLETI%N"
9999 GOTO 0
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
CD itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57613 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"\B5
Skip to content
Bulletin
This file is part of and Synchro-Sette June 1983. Download the collection to get this file.
This program implements a scrolling bulletin board display for the Synchro-Sette June 1983 issue. It uses a machine code routine embedded in the REM statement at line 10 — the bytes decode to a LDDR-based block memory copy, called via USR to scroll the display. The program builds a 24×32 string array Z$() pre-filled with alternating inverse-space patterns and checkerboard rows, then continuously scrolls rows upward by cycling through the array. Two ticker-tape style text strings A$ and B$ are scrolled horizontally across banner boxes drawn with block graphics characters. A keypress (detected via INKEY$) triggers a PAUSE 40000 hold, and the SAVE command at line 9998 uses an inverse-video character in the filename as an auto-run flag.
Program Analysis
Program Structure
The program divides into several functional phases:
- Initialisation (lines 20–80): Switches to FAST mode, calculates a base address offset into
X, builds the 24×32 display buffer array Z$() pre-filled with alternating inverse-space and checkerboard rows, then returns to SLOW mode.
- Main scroll loop (lines 180–260): Cycles variable
A through rows 1–22, printing each row at the screen position returned by USR 16514, creating a continuous vertical scroll effect.
- Subroutine at 300 (lines 300–340): Manages a counter
D to phase in title text into Z$(1) at specific thresholds, then falls through to the banner/box drawing sequence once D>65.
- Banner display (lines 350–620): Clears the screen with scrolls and PRINT, draws a decorative box using block graphics, animates the title string sideways across row 1, and prints the “JUNE 1983” date.
- Horizontal text scrollers (lines 3000–3080): Scroll strings
A$ and B$ character-by-character across the top and bottom banner boxes in an infinite loop.
- Pause handler (lines 4000–4010): On any keypress, freezes display for approximately 40 seconds before returning.
Machine Code Routine in REM
Line 10 contains a machine code routine embedded directly in the REM statement body. The bytes are:
Offset Hex Mnemonic Notes 0 01 D6 02LD BC, 02D6h Byte count = 726 (approx. 22 text rows × 33 bytes) 3 2A 0C 40LD HL, (400Ch) Load HL from system variable (VARS area pointer) 6 09ADD HL, BC Advance HL by block count 7 54LD D, H 8 5DLD E, L DE = HL (destination) 9 01 B5 02LD BC, 02B5h Second byte count 12 2A 0C 40LD HL, (400Ch) Reload HL from same system variable 15 09ADD HL, BC 16 ED B8LDDR Block copy backwards 18 C9RET
The routine performs a backwards block memory copy (LDDR) to shift a region of the display file or string array upward by one row. It is called indirectly via USR 16514 in the PRINT AT statement at lines 240 and 520 — 16514 (4002h) is the address of the second byte of the REM line’s data, i.e. the first byte of the machine code.
Display Buffer Technique
Rather than printing directly to the screen, the program maintains a 24×32 string array Z$() that acts as a software frame buffer. Each element holds one display row as a 32-character string. The main loop prints individual rows at the current screen position via PRINT AT USR 16514,0;Z$(C), where the machine code side-effect of USR provides the scroll, and the PRINT renders the next row.
Rows that are multiples of 3 are initialised (line 65) to a checkerboard pattern of alternating @ and # inverse-video pairs, providing a visual border between content rows. All other rows use the inverse-space pattern stored in Q$.
Key BASIC Idioms
- Inverse-video strings:
Q$ at line 35 is built entirely from inverse-space characters, providing a filled background row. Titles at lines 300–310 use inverse letters throughout.
- Wrap-around counter: Lines 210 and 230 wrap
B and C at the array boundaries (1–22) to achieve continuous circular scrolling without an array bounds error.
- Horizontal scroll via substring: Lines 3000–3080 iterate
N from 1 to LEN A$-28, printing A$(N TO N+27) to scroll a 28-character window across the full string one character per frame.
- POKE 16418,0 at line 540 clears the ZX81 system variable
CDFLAG (or equivalent TS1000 flag), forcing the display back to a known state after mode transitions.
Block Graphics Box Drawing
Lines 570–610 draw two decorative rectangular boxes using ZX81 block graphic characters. The top and bottom edges use ▖▄▄▄…▄▖ style sequences, the sides use ▌ and ▐, and the corners are formed by appropriate quadrant characters. The inner box spanning rows 10–13 holds the “SYNCHRO-SETTE PRESENTS” / bulletin board title area, while the outer box spanning rows 2–21 frames the scrolling text display.
Notable Techniques
- The
D counter in the GOSUB 300 subroutine acts as a state machine: at D>1 the first title line appears; at D>24 it changes to the full bulletin board title; at D>65 execution falls through to the banner drawing code rather than returning, effectively a computed GOTO via threshold comparison.
- The
X variable computed at line 30 (PEEK 16404 + 256*PEEK 16405 - 794) calculates an offset into the display file based on the D-FILE pointer, but X is never subsequently used in the listing — it may be a remnant of an earlier version or used by the machine code to locate data.
- The horizontal title animation at lines 460–500 prepends an extra inverse-space to
R$ on each iteration while printing at column 25 down to column 11 (25 − 15 + 1 = 11), creating a slide-in effect from the right edge.
Bugs and Anomalies
A$ and B$ are referenced at lines 3000–3070 but never defined or loaded in the visible listing. They are presumably loaded from tape before this program runs, or the listing is incomplete.
- The horizontal scroller loop at line 3000 uses
LEN A$-28 without guarding against LEN A$<28, which would cause a negative subscript error if a short string were loaded.
- Line 380
PRINT AT 2,0;""; prints an empty string, which serves only to position the cursor — a common ZX81 idiom but unusual when followed immediately by a FOR/PRINT loop that positions its own output.
Content
Source Code
10 REM \01\D6\02\2A\0C\40\09\54\5D\01\B5\02\2A\0C\40\09\ED\B8\C9
20 FAST
30 LET X=PEEK 16404+256*PEEK 16405-794
35 LET Q$="% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % "
40 DIM Z$(24,32)
50 FOR N=1 TO 22
60 LET Z$(N)=Q$
65 IF N/3=INT (N/3) THEN LET Z$(N)="\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##"
70 NEXT N
80 SLOW
180 LET D=0
190 LET A=1
200 LET B=A+1
205 GOSUB 300
210 IF B=23 THEN LET B=1
220 LET C=A-1
230 IF C=0 THEN LET C=22
240 PRINT AT USR 16514,0;Z$(C)
250 LET A=C
260 GOTO 200
300 IF D>1 THEN LET Z$(1)="% % % % % %S%Y%N%C%H%R%O%-%S%E%T%T%E% %P%R%E%S%E%N%T%S% % % % % "
310 IF D>24 THEN LET Z$(1)="%T%H%E% %S%Y%N%C%H%R%O%-%S%E%T%T%E% %B%U%L%L%E%T%I%N% %B%O%A%R%D"
320 LET D=D+1
330 IF D>65 THEN GOTO 350
340 RETURN
350 FOR N=1 TO 20
360 SCROLL
370 NEXT N
380 PRINT AT 2,0;"";
390 FOR N=1 TO 20
400 PRINT Q$
410 NEXT N
420 LET R$="% "+Z$(1)
430 FOR N=0 TO 6
440 PRINT AT 1,0+N;R$
450 NEXT N
460 LET R$="% %B%U%L%L%E%T%I%N% % %B%O%A%R%D% "
470 FOR N=1 TO 15
480 PRINT AT 1,25;R$
490 LET R$="% "+R$
500 NEXT N
510 FOR N=1 TO 10
520 PRINT AT USR 16514,0;Q$
530 NEXT N
540 POKE 16418,0
550 PRINT AT 22,0;Q$
560 PRINT AT 23,0;Q$
570 PRINT AT 10,6;"\ .\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\. ";AT 11,6;"\ :";AT 11,24;"\: ";AT 12,6;"\ :";AT 12,24;"\: ";AT 13,6;"\ '\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\' "
580 FOR N=1 TO 30
590 PRINT AT 2,N;"\''";AT 4,N;"\..";AT 19,N;"\''";AT 21,N;"\.."
600 NEXT N
610 PRINT AT 3,1;"\ :";AT 3,30;"\: ";AT 20,1;"\ :";AT 20,30;"\: "
620 PRINT AT 7,14;"%J%U%N%E";AT 16,14;"%1%9%8%3"
3000 FOR N=1 TO LEN A$-28
3010 PRINT AT 3,2;A$(N TO N+27)
3020 IF INKEY$<>"" THEN GOSUB 4000
3030 NEXT N
3040 FOR N=1 TO LEN B$-28
3050 PRINT AT 20,2;B$(N TO N+27)
3060 IF INKEY$<>"" THEN GOSUB 4000
3070 NEXT N
3080 GOTO 3000
4000 PAUSE 40000
4010 RETURN
9998 SAVE "BULLETI%N"
9999 GOTO 0
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
Skip to content
Bulletin
This file is part of and Synchro-Sette June 1983. Download the collection to get this file.
This program implements a scrolling bulletin board display for the Synchro-Sette June 1983 issue. It uses a machine code routine embedded in the REM statement at line 10 — the bytes decode to a LDDR-based block memory copy, called via USR to scroll the display. The program builds a 24×32 string array Z$() pre-filled with alternating inverse-space patterns and checkerboard rows, then continuously scrolls rows upward by cycling through the array. Two ticker-tape style text strings A$ and B$ are scrolled horizontally across banner boxes drawn with block graphics characters. A keypress (detected via INKEY$) triggers a PAUSE 40000 hold, and the SAVE command at line 9998 uses an inverse-video character in the filename as an auto-run flag.
Program Analysis
Program Structure
The program divides into several functional phases:
- Initialisation (lines 20–80): Switches to FAST mode, calculates a base address offset into
X, builds the 24×32 display buffer array Z$() pre-filled with alternating inverse-space and checkerboard rows, then returns to SLOW mode.
- Main scroll loop (lines 180–260): Cycles variable
A through rows 1–22, printing each row at the screen position returned by USR 16514, creating a continuous vertical scroll effect.
- Subroutine at 300 (lines 300–340): Manages a counter
D to phase in title text into Z$(1) at specific thresholds, then falls through to the banner/box drawing sequence once D>65.
- Banner display (lines 350–620): Clears the screen with scrolls and PRINT, draws a decorative box using block graphics, animates the title string sideways across row 1, and prints the “JUNE 1983” date.
- Horizontal text scrollers (lines 3000–3080): Scroll strings
A$ and B$ character-by-character across the top and bottom banner boxes in an infinite loop.
- Pause handler (lines 4000–4010): On any keypress, freezes display for approximately 40 seconds before returning.
Machine Code Routine in REM
Line 10 contains a machine code routine embedded directly in the REM statement body. The bytes are:
Offset Hex Mnemonic Notes 0 01 D6 02LD BC, 02D6h Byte count = 726 (approx. 22 text rows × 33 bytes) 3 2A 0C 40LD HL, (400Ch) Load HL from system variable (VARS area pointer) 6 09ADD HL, BC Advance HL by block count 7 54LD D, H 8 5DLD E, L DE = HL (destination) 9 01 B5 02LD BC, 02B5h Second byte count 12 2A 0C 40LD HL, (400Ch) Reload HL from same system variable 15 09ADD HL, BC 16 ED B8LDDR Block copy backwards 18 C9RET
The routine performs a backwards block memory copy (LDDR) to shift a region of the display file or string array upward by one row. It is called indirectly via USR 16514 in the PRINT AT statement at lines 240 and 520 — 16514 (4002h) is the address of the second byte of the REM line’s data, i.e. the first byte of the machine code.
Display Buffer Technique
Rather than printing directly to the screen, the program maintains a 24×32 string array Z$() that acts as a software frame buffer. Each element holds one display row as a 32-character string. The main loop prints individual rows at the current screen position via PRINT AT USR 16514,0;Z$(C), where the machine code side-effect of USR provides the scroll, and the PRINT renders the next row.
Rows that are multiples of 3 are initialised (line 65) to a checkerboard pattern of alternating @ and # inverse-video pairs, providing a visual border between content rows. All other rows use the inverse-space pattern stored in Q$.
Key BASIC Idioms
- Inverse-video strings:
Q$ at line 35 is built entirely from inverse-space characters, providing a filled background row. Titles at lines 300–310 use inverse letters throughout.
- Wrap-around counter: Lines 210 and 230 wrap
B and C at the array boundaries (1–22) to achieve continuous circular scrolling without an array bounds error.
- Horizontal scroll via substring: Lines 3000–3080 iterate
N from 1 to LEN A$-28, printing A$(N TO N+27) to scroll a 28-character window across the full string one character per frame.
- POKE 16418,0 at line 540 clears the ZX81 system variable
CDFLAG (or equivalent TS1000 flag), forcing the display back to a known state after mode transitions.
Block Graphics Box Drawing
Lines 570–610 draw two decorative rectangular boxes using ZX81 block graphic characters. The top and bottom edges use ▖▄▄▄…▄▖ style sequences, the sides use ▌ and ▐, and the corners are formed by appropriate quadrant characters. The inner box spanning rows 10–13 holds the “SYNCHRO-SETTE PRESENTS” / bulletin board title area, while the outer box spanning rows 2–21 frames the scrolling text display.
Notable Techniques
- The
D counter in the GOSUB 300 subroutine acts as a state machine: at D>1 the first title line appears; at D>24 it changes to the full bulletin board title; at D>65 execution falls through to the banner drawing code rather than returning, effectively a computed GOTO via threshold comparison.
- The
X variable computed at line 30 (PEEK 16404 + 256*PEEK 16405 - 794) calculates an offset into the display file based on the D-FILE pointer, but X is never subsequently used in the listing — it may be a remnant of an earlier version or used by the machine code to locate data.
- The horizontal title animation at lines 460–500 prepends an extra inverse-space to
R$ on each iteration while printing at column 25 down to column 11 (25 − 15 + 1 = 11), creating a slide-in effect from the right edge.
Bugs and Anomalies
A$ and B$ are referenced at lines 3000–3070 but never defined or loaded in the visible listing. They are presumably loaded from tape before this program runs, or the listing is incomplete.
- The horizontal scroller loop at line 3000 uses
LEN A$-28 without guarding against LEN A$<28, which would cause a negative subscript error if a short string were loaded.
- Line 380
PRINT AT 2,0;""; prints an empty string, which serves only to position the cursor — a common ZX81 idiom but unusual when followed immediately by a FOR/PRINT loop that positions its own output.
Content
Source Code
10 REM \01\D6\02\2A\0C\40\09\54\5D\01\B5\02\2A\0C\40\09\ED\B8\C9
20 FAST
30 LET X=PEEK 16404+256*PEEK 16405-794
35 LET Q$="% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % "
40 DIM Z$(24,32)
50 FOR N=1 TO 22
60 LET Z$(N)=Q$
65 IF N/3=INT (N/3) THEN LET Z$(N)="\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##"
70 NEXT N
80 SLOW
180 LET D=0
190 LET A=1
200 LET B=A+1
205 GOSUB 300
210 IF B=23 THEN LET B=1
220 LET C=A-1
230 IF C=0 THEN LET C=22
240 PRINT AT USR 16514,0;Z$(C)
250 LET A=C
260 GOTO 200
300 IF D>1 THEN LET Z$(1)="% % % % % %S%Y%N%C%H%R%O%-%S%E%T%T%E% %P%R%E%S%E%N%T%S% % % % % "
310 IF D>24 THEN LET Z$(1)="%T%H%E% %S%Y%N%C%H%R%O%-%S%E%T%T%E% %B%U%L%L%E%T%I%N% %B%O%A%R%D"
320 LET D=D+1
330 IF D>65 THEN GOTO 350
340 RETURN
350 FOR N=1 TO 20
360 SCROLL
370 NEXT N
380 PRINT AT 2,0;"";
390 FOR N=1 TO 20
400 PRINT Q$
410 NEXT N
420 LET R$="% "+Z$(1)
430 FOR N=0 TO 6
440 PRINT AT 1,0+N;R$
450 NEXT N
460 LET R$="% %B%U%L%L%E%T%I%N% % %B%O%A%R%D% "
470 FOR N=1 TO 15
480 PRINT AT 1,25;R$
490 LET R$="% "+R$
500 NEXT N
510 FOR N=1 TO 10
520 PRINT AT USR 16514,0;Q$
530 NEXT N
540 POKE 16418,0
550 PRINT AT 22,0;Q$
560 PRINT AT 23,0;Q$
570 PRINT AT 10,6;"\ .\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\. ";AT 11,6;"\ :";AT 11,24;"\: ";AT 12,6;"\ :";AT 12,24;"\: ";AT 13,6;"\ '\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\' "
580 FOR N=1 TO 30
590 PRINT AT 2,N;"\''";AT 4,N;"\..";AT 19,N;"\''";AT 21,N;"\.."
600 NEXT N
610 PRINT AT 3,1;"\ :";AT 3,30;"\: ";AT 20,1;"\ :";AT 20,30;"\: "
620 PRINT AT 7,14;"%J%U%N%E";AT 16,14;"%1%9%8%3"
3000 FOR N=1 TO LEN A$-28
3010 PRINT AT 3,2;A$(N TO N+27)
3020 IF INKEY$<>"" THEN GOSUB 4000
3030 NEXT N
3040 FOR N=1 TO LEN B$-28
3050 PRINT AT 20,2;B$(N TO N+27)
3060 IF INKEY$<>"" THEN GOSUB 4000
3070 NEXT N
3080 GOTO 3000
4000 PAUSE 40000
4010 RETURN
9998 SAVE "BULLETI%N"
9999 GOTO 0
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
A
Skip to content
Bulletin
This file is part of and Synchro-Sette June 1983. Download the collection to get this file.
This program implements a scrolling bulletin board display for the Synchro-Sette June 1983 issue. It uses a machine code routine embedded in the REM statement at line 10 — the bytes decode to a LDDR-based block memory copy, called via USR to scroll the display. The program builds a 24×32 string array Z$() pre-filled with alternating inverse-space patterns and checkerboard rows, then continuously scrolls rows upward by cycling through the array. Two ticker-tape style text strings A$ and B$ are scrolled horizontally across banner boxes drawn with block graphics characters. A keypress (detected via INKEY$) triggers a PAUSE 40000 hold, and the SAVE command at line 9998 uses an inverse-video character in the filename as an auto-run flag.
Program Analysis
Program Structure
The program divides into several functional phases:
- Initialisation (lines 20–80): Switches to FAST mode, calculates a base address offset into
X, builds the 24×32 display buffer array Z$() pre-filled with alternating inverse-space and checkerboard rows, then returns to SLOW mode.
- Main scroll loop (lines 180–260): Cycles variable
A through rows 1–22, printing each row at the screen position returned by USR 16514, creating a continuous vertical scroll effect.
- Subroutine at 300 (lines 300–340): Manages a counter
D to phase in title text into Z$(1) at specific thresholds, then falls through to the banner/box drawing sequence once D>65.
- Banner display (lines 350–620): Clears the screen with scrolls and PRINT, draws a decorative box using block graphics, animates the title string sideways across row 1, and prints the “JUNE 1983” date.
- Horizontal text scrollers (lines 3000–3080): Scroll strings
A$ and B$ character-by-character across the top and bottom banner boxes in an infinite loop.
- Pause handler (lines 4000–4010): On any keypress, freezes display for approximately 40 seconds before returning.
Machine Code Routine in REM
Line 10 contains a machine code routine embedded directly in the REM statement body. The bytes are:
Offset Hex Mnemonic Notes 0 01 D6 02LD BC, 02D6h Byte count = 726 (approx. 22 text rows × 33 bytes) 3 2A 0C 40LD HL, (400Ch) Load HL from system variable (VARS area pointer) 6 09ADD HL, BC Advance HL by block count 7 54LD D, H 8 5DLD E, L DE = HL (destination) 9 01 B5 02LD BC, 02B5h Second byte count 12 2A 0C 40LD HL, (400Ch) Reload HL from same system variable 15 09ADD HL, BC 16 ED B8LDDR Block copy backwards 18 C9RET
The routine performs a backwards block memory copy (LDDR) to shift a region of the display file or string array upward by one row. It is called indirectly via USR 16514 in the PRINT AT statement at lines 240 and 520 — 16514 (4002h) is the address of the second byte of the REM line’s data, i.e. the first byte of the machine code.
Display Buffer Technique
Rather than printing directly to the screen, the program maintains a 24×32 string array Z$() that acts as a software frame buffer. Each element holds one display row as a 32-character string. The main loop prints individual rows at the current screen position via PRINT AT USR 16514,0;Z$(C), where the machine code side-effect of USR provides the scroll, and the PRINT renders the next row.
Rows that are multiples of 3 are initialised (line 65) to a checkerboard pattern of alternating @ and # inverse-video pairs, providing a visual border between content rows. All other rows use the inverse-space pattern stored in Q$.
Key BASIC Idioms
- Inverse-video strings:
Q$ at line 35 is built entirely from inverse-space characters, providing a filled background row. Titles at lines 300–310 use inverse letters throughout.
- Wrap-around counter: Lines 210 and 230 wrap
B and C at the array boundaries (1–22) to achieve continuous circular scrolling without an array bounds error.
- Horizontal scroll via substring: Lines 3000–3080 iterate
N from 1 to LEN A$-28, printing A$(N TO N+27) to scroll a 28-character window across the full string one character per frame.
- POKE 16418,0 at line 540 clears the ZX81 system variable
CDFLAG (or equivalent TS1000 flag), forcing the display back to a known state after mode transitions.
Block Graphics Box Drawing
Lines 570–610 draw two decorative rectangular boxes using ZX81 block graphic characters. The top and bottom edges use ▖▄▄▄…▄▖ style sequences, the sides use ▌ and ▐, and the corners are formed by appropriate quadrant characters. The inner box spanning rows 10–13 holds the “SYNCHRO-SETTE PRESENTS” / bulletin board title area, while the outer box spanning rows 2–21 frames the scrolling text display.
Notable Techniques
- The
D counter in the GOSUB 300 subroutine acts as a state machine: at D>1 the first title line appears; at D>24 it changes to the full bulletin board title; at D>65 execution falls through to the banner drawing code rather than returning, effectively a computed GOTO via threshold comparison.
- The
X variable computed at line 30 (PEEK 16404 + 256*PEEK 16405 - 794) calculates an offset into the display file based on the D-FILE pointer, but X is never subsequently used in the listing — it may be a remnant of an earlier version or used by the machine code to locate data.
- The horizontal title animation at lines 460–500 prepends an extra inverse-space to
R$ on each iteration while printing at column 25 down to column 11 (25 − 15 + 1 = 11), creating a slide-in effect from the right edge.
Bugs and Anomalies
A$ and B$ are referenced at lines 3000–3070 but never defined or loaded in the visible listing. They are presumably loaded from tape before this program runs, or the listing is incomplete.
- The horizontal scroller loop at line 3000 uses
LEN A$-28 without guarding against LEN A$<28, which would cause a negative subscript error if a short string were loaded.
- Line 380
PRINT AT 2,0;""; prints an empty string, which serves only to position the cursor — a common ZX81 idiom but unusual when followed immediately by a FOR/PRINT loop that positions its own output.
Content
Source Code
10 REM \01\D6\02\2A\0C\40\09\54\5D\01\B5\02\2A\0C\40\09\ED\B8\C9
20 FAST
30 LET X=PEEK 16404+256*PEEK 16405-794
35 LET Q$="% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % "
40 DIM Z$(24,32)
50 FOR N=1 TO 22
60 LET Z$(N)=Q$
65 IF N/3=INT (N/3) THEN LET Z$(N)="\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##"
70 NEXT N
80 SLOW
180 LET D=0
190 LET A=1
200 LET B=A+1
205 GOSUB 300
210 IF B=23 THEN LET B=1
220 LET C=A-1
230 IF C=0 THEN LET C=22
240 PRINT AT USR 16514,0;Z$(C)
250 LET A=C
260 GOTO 200
300 IF D>1 THEN LET Z$(1)="% % % % % %S%Y%N%C%H%R%O%-%S%E%T%T%E% %P%R%E%S%E%N%T%S% % % % % "
310 IF D>24 THEN LET Z$(1)="%T%H%E% %S%Y%N%C%H%R%O%-%S%E%T%T%E% %B%U%L%L%E%T%I%N% %B%O%A%R%D"
320 LET D=D+1
330 IF D>65 THEN GOTO 350
340 RETURN
350 FOR N=1 TO 20
360 SCROLL
370 NEXT N
380 PRINT AT 2,0;"";
390 FOR N=1 TO 20
400 PRINT Q$
410 NEXT N
420 LET R$="% "+Z$(1)
430 FOR N=0 TO 6
440 PRINT AT 1,0+N;R$
450 NEXT N
460 LET R$="% %B%U%L%L%E%T%I%N% % %B%O%A%R%D% "
470 FOR N=1 TO 15
480 PRINT AT 1,25;R$
490 LET R$="% "+R$
500 NEXT N
510 FOR N=1 TO 10
520 PRINT AT USR 16514,0;Q$
530 NEXT N
540 POKE 16418,0
550 PRINT AT 22,0;Q$
560 PRINT AT 23,0;Q$
570 PRINT AT 10,6;"\ .\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\. ";AT 11,6;"\ :";AT 11,24;"\: ";AT 12,6;"\ :";AT 12,24;"\: ";AT 13,6;"\ '\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\' "
580 FOR N=1 TO 30
590 PRINT AT 2,N;"\''";AT 4,N;"\..";AT 19,N;"\''";AT 21,N;"\.."
600 NEXT N
610 PRINT AT 3,1;"\ :";AT 3,30;"\: ";AT 20,1;"\ :";AT 20,30;"\: "
620 PRINT AT 7,14;"%J%U%N%E";AT 16,14;"%1%9%8%3"
3000 FOR N=1 TO LEN A$-28
3010 PRINT AT 3,2;A$(N TO N+27)
3020 IF INKEY$<>"" THEN GOSUB 4000
3030 NEXT N
3040 FOR N=1 TO LEN B$-28
3050 PRINT AT 20,2;B$(N TO N+27)
3060 IF INKEY$<>"" THEN GOSUB 4000
3070 NEXT N
3080 GOTO 3000
4000 PAUSE 40000
4010 RETURN
9998 SAVE "BULLETI%N"
9999 GOTO 0
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
C\ED\B8\C9
20 FAST
30 LET X=PEEK 16404+256*PEEK 16405-794
35 LET Q$="% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % "
40 DIM Z$(24,32)
50 FOR N=1 TO 22
60 LET Z$(N)=Q$
65 IF N/3=INT (N/3) THEN LET Z$(N)="\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##\@@\##"
70 NEXT N
80 SLOW
180 LET D=0
190 LET A=1
200 LET B=A+1
205 GOSUB 300
210 IF B=23 THEN LET B=1
220 LET C=A-1
230 IF C=0 THEN LET C=22
240 PRINT AT USR 16514,0;Z$(C)
250 LET A=C
260 GOTO 200
300 IF D>1 THEN LET Z$(1)="% % % % % %S%Y%N%C%H%R%O%-%S%E%T%T%E% %P%R%E%S%E%N%T%S% % % % % "
310 IF D>24 THEN LET Z$(1)="%T%H%E% %S%Y%N%C%H%R%O%-%S%E%T%T%E% %B%U%L%L%E%T%I%N% %B%O%A%R%D"
320 LET D=D+1
330 IF D>65 THEN GOTO 350
340 RETURN
350 FOR N=1 TO 20
360 SCROLL
370 NEXT N
380 PRINT AT 2,0;"";
390 FOR N=1 TO 20
400 PRINT Q$
410 NEXT N
420 LET R$="% "+Z$(1)
430 FOR N=0 TO 6
440 PRINT AT 1,0+N;R$
450 NEXT N
460 LET R$="% %B%U%L%L%E%T%I%N% % %B%O%A%R%D% "
470 FOR N=1 TO 15
480 PRINT AT 1,25;R$
490 LET R$="% "+R$
500 NEXT N
510 FOR N=1 TO 10
520 PRINT AT USR 16514,0;Q$
530 NEXT N
540 POKE 16418,0
550 PRINT AT 22,0;Q$
560 PRINT AT 23,0;Q$
570 PRINT AT 10,6;"\ .\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\. ";AT 11,6;"\ :";AT 11,24;"\: ";AT 12,6;"\ :";AT 12,24;"\: ";AT 13,6;"\ '\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\' "
580 FOR N=1 TO 30
590 PRINT AT 2,N;"\''";AT 4,N;"\..";AT 19,N;"\''";AT 21,N;"\.."
600 NEXT N
610 PRINT AT 3,1;"\ :";AT 3,30;"\: ";AT 20,1;"\ :";AT 20,30;"\: "
620 PRINT AT 7,14;"%J%U%N%E";AT 16,14;"%1%9%8%3"
\n3000 FOR N=1 TO LEN A$-28
\n3010 PRINT AT 3,2;A$(N TO N+27)
\n3020 IF INKEY$<>"" THEN GOSUB 4000
\n3030 NEXT N
\n3040 FOR N=1 TO LEN B$-28
\n3050 PRINT AT 20,2;B$(N TO N+27)
\n3060 IF INKEY$<>"" THEN GOSUB 4000
\n3070 NEXT N
\n3080 GOTO 3000
\n4000 PAUSE 40000
\n4010 RETURN
\n9998 SAVE "BULLETI%N"
\n9999 GOTO 0
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
