Scroller is a ZX81/TS1000 program that creates a checkerboard pattern in display memory and then uses embedded machine code to scroll the screen in four directions under keyboard control. The machine code routine is stored in the REM statement at line 1, beginning at address 16514, and is called via RAND USR 16514. The BASIC initialization loop at lines 15–85 fills the 24×64 video RAM region starting at address 20480 with alternating byte values (8 and 2) to produce a two-tone checkerboard. Keys 5, 6, 7, and 8 (the ZX81’s cursor keys) control horizontal and vertical scrolling, with boundary checks at lines 149–150 preventing the scroll position from going outside the valid display memory range. Line 300–320 provides a diagnostic routine that LPRINTs the contents and ASCII equivalents of the machine code bytes stored in the REM statement.
Program Analysis
Program Structure
The program divides into four functional sections:
- Lines 1: A
REMstatement acting as machine code storage, holding the scroll routine at addresses 16514 onward. - Lines 10–85: BASIC initialization — fills display RAM (starting at 20480) with a checkerboard pattern using alternating byte values.
- Lines 90–230: Main interactive loop — reads cursor keys (5/6/7/8), validates boundaries, updates the scroll pointer, and calls the machine code display routine via
RAND USR 16514. - Lines 300–320: A standalone diagnostic utility that
LPRINTs the address, byte value, and ASCII character of each byte in the machine code REM block.
Machine Code in REM Statement
The REM at line 1 stores 57 bytes of Z80 machine code beginning at address 16514 (the first byte after the line’s length bytes and REM token). The routine is invoked with RAND USR 16514, which transfers execution to that address without disturbing the BASIC stack in a disruptive way. The low and high bytes of the target display address are pre-loaded into memory locations 16524 and 16525 (two bytes within the REM data itself, acting as a self-modifying code parameter), set by POKE statements at lines 100–105 and 200–210.
The decoded Z80 sequence begins:
21 21 40—LD HL, $4021(points into the REM data for the address parameter)3E 18—LD A, $1877—LD (HL), A11 00 60—LD DE, $6000(destination buffer)21 00 50—LD HL, $5000C3 93 40—JP $4093(jump further into the routine)
The routine copies a region of display memory to a buffer, performs the scroll, and returns. The use of ED B0 (LDIR) is visible in the byte sequence, confirming block memory copy operations for efficiency.
Checkerboard Initialization
Lines 15–85 fill 24 rows × 64 columns (1536 bytes) of video RAM with alternating values. Variable A starts at 8. For each row of 64 columns, when Y>32 the value toggles via A=10-A (swapping between 8 and 2, since 10−8=2 and 10−2=8). The toggle is applied before the POKE at line 38 and then reversed after at line 48, so only the second half of each row uses the alternate value. The outer loop FOR Z=1 TO 2 at line 25 resets A to 3 at line 65 on the second pass, which shifts the phase of the pattern to create the checkerboard effect across rows.
Scroll Pointer and Boundary Checking
The current top-left display address is held in N. Variable A (reused from initialization) tracks the horizontal byte offset within a row (0–32). Variable K holds the scroll delta: ±1 for left/right, ±64 for up/down.
Two boundary guards are applied before any scroll:
- Line 149: For horizontal scrolls (
K=±1), checks thatA+Kremains within 0–32, preventing wrapping across row boundaries. - Line 150: Checks that the new address
N+Kstays within 20480–22015 (the valid 1.5 KB display RAM window), preventing scrolling outside the initialized region.
Address Passing to Machine Code
Because the machine code routine reads the scroll target address from fixed locations within its own code (at offsets corresponding to addresses 16524–16525), the BASIC layer must write the low byte (256*(N/256-INT(N/256))) and high byte (INT N/256) to those locations before each call. This is a self-modifying code pattern — the POKEs at lines 100/105 and 200/210 patch operand bytes directly inside the REM-stored machine code before invoking it.
Key Mapping
| Key | Character Code | K value | Direction |
|---|---|---|---|
| 5 | 33 | −1 | Left |
| 8 | 36 | +1 | Right |
| 6 | 34 | +64 | Down |
| 7 | 35 | −64 | Up |
Line 125 filters for character codes 33–36 (i.e., “5”, “6”, “7”, “8”), rejecting all other keypresses and looping back to INKEY$ polling. This is a compact range-check idiom avoiding four separate IF tests.
Diagnostic Routine
Lines 300–320 are not called from the main program flow and serve as a developer tool. The loop iterates over addresses 16514–16570, printing each address, its raw byte value via PEEK, and the corresponding CHR$ representation to the printer. This allows the programmer to verify the machine code bytes stored in the REM statement are intact after loading.
Notable Techniques
REMas machine code storage: the standard ZX81 technique for embedding Z80 routines without a separate loader or character RAM area.- Self-modifying machine code: address parameters are patched via
POKEbefore eachRAND USRcall. FAST/SLOWbracketing of the initialization loop (lines 10, 90) speeds up the POKE-fill stage while restoring display output for interactive use.- The reuse of variable
Afor both pattern generation (lines 15–85) and horizontal offset tracking (lines 115–157) requires careful reading — after initialization,Ais reset to 0 at line 115 for its new role.
Content
Source Code
1 REM E
Skip to content
Scroller
Scroller is a ZX81/TS1000 program that creates a checkerboard pattern in display memory and then uses embedded machine code to scroll the screen in four directions under keyboard control. The machine code routine is stored in the REM statement at line 1, beginning at address 16514, and is called via RAND USR 16514. The BASIC initialization loop at lines 15–85 fills the 24×64 video RAM region starting at address 20480 with alternating byte values (8 and 2) to produce a two-tone checkerboard. Keys 5, 6, 7, and 8 (the ZX81’s cursor keys) control horizontal and vertical scrolling, with boundary checks at lines 149–150 preventing the scroll position from going outside the valid display memory range. Line 300–320 provides a diagnostic routine that LPRINTs the contents and ASCII equivalents of the machine code bytes stored in the REM statement.
Program Analysis
Program Structure
The program divides into four functional sections:
- Lines 1: A
REM statement acting as machine code storage, holding the scroll routine at addresses 16514 onward.
- Lines 10–85: BASIC initialization — fills display RAM (starting at 20480) with a checkerboard pattern using alternating byte values.
- Lines 90–230: Main interactive loop — reads cursor keys (5/6/7/8), validates boundaries, updates the scroll pointer, and calls the machine code display routine via
RAND USR 16514.
- Lines 300–320: A standalone diagnostic utility that
LPRINTs the address, byte value, and ASCII character of each byte in the machine code REM block.
Machine Code in REM Statement
The REM at line 1 stores 57 bytes of Z80 machine code beginning at address 16514 (the first byte after the line’s length bytes and REM token). The routine is invoked with RAND USR 16514, which transfers execution to that address without disturbing the BASIC stack in a disruptive way. The low and high bytes of the target display address are pre-loaded into memory locations 16524 and 16525 (two bytes within the REM data itself, acting as a self-modifying code parameter), set by POKE statements at lines 100–105 and 200–210.
The decoded Z80 sequence begins:
21 21 40 — LD HL, $4021 (points into the REM data for the address parameter)
3E 18 — LD A, $18
77 — LD (HL), A
11 00 60 — LD DE, $6000 (destination buffer)
21 00 50 — LD HL, $5000
C3 93 40 — JP $4093 (jump further into the routine)
The routine copies a region of display memory to a buffer, performs the scroll, and returns. The use of ED B0 (LDIR) is visible in the byte sequence, confirming block memory copy operations for efficiency.
Checkerboard Initialization
Lines 15–85 fill 24 rows × 64 columns (1536 bytes) of video RAM with alternating values. Variable A starts at 8. For each row of 64 columns, when Y>32 the value toggles via A=10-A (swapping between 8 and 2, since 10−8=2 and 10−2=8). The toggle is applied before the POKE at line 38 and then reversed after at line 48, so only the second half of each row uses the alternate value. The outer loop FOR Z=1 TO 2 at line 25 resets A to 3 at line 65 on the second pass, which shifts the phase of the pattern to create the checkerboard effect across rows.
Scroll Pointer and Boundary Checking
The current top-left display address is held in N. Variable A (reused from initialization) tracks the horizontal byte offset within a row (0–32). Variable K holds the scroll delta: ±1 for left/right, ±64 for up/down.
Two boundary guards are applied before any scroll:
- Line 149: For horizontal scrolls (
K=±1), checks that A+K remains within 0–32, preventing wrapping across row boundaries.
- Line 150: Checks that the new address
N+K stays within 20480–22015 (the valid 1.5 KB display RAM window), preventing scrolling outside the initialized region.
Address Passing to Machine Code
Because the machine code routine reads the scroll target address from fixed locations within its own code (at offsets corresponding to addresses 16524–16525), the BASIC layer must write the low byte (256*(N/256-INT(N/256))) and high byte (INT N/256) to those locations before each call. This is a self-modifying code pattern — the POKEs at lines 100/105 and 200/210 patch operand bytes directly inside the REM-stored machine code before invoking it.
Key Mapping
Key Character Code K value Direction 5 33 −1 Left 8 36 +1 Right 6 34 +64 Down 7 35 −64 Up
Line 125 filters for character codes 33–36 (i.e., “5”, “6”, “7”, “8”), rejecting all other keypresses and looping back to INKEY$ polling. This is a compact range-check idiom avoiding four separate IF tests.
Diagnostic Routine
Lines 300–320 are not called from the main program flow and serve as a developer tool. The loop iterates over addresses 16514–16570, printing each address, its raw byte value via PEEK, and the corresponding CHR$ representation to the printer. This allows the programmer to verify the machine code bytes stored in the REM statement are intact after loading.
Notable Techniques
REM as machine code storage: the standard ZX81 technique for embedding Z80 routines without a separate loader or character RAM area.
- Self-modifying machine code: address parameters are patched via
POKE before each RAND USR call.
FAST/SLOW bracketing of the initialization loop (lines 10, 90) speeds up the POKE-fill stage while restoring display output for interactive use.
- The reuse of variable
A for both pattern generation (lines 15–85) and horizontal offset tracking (lines 115–157) requires careful reading — after initialization, A is reset to 0 at line 115 for its new role.
Content
Source Code
1 REM \21\21\40\3E\18\77\11\00\60\21\00\50\C3\93\40\35\E1\01\20\00\ED\B0\3E\76\12\1C\06\00\0E\20\09\E5\21\21\40\3E\00\BE\C2\91\40\E1\01\18\03\2A\0C\40\2C\E5\D1\21\00\60\ED\B0\C9\1B\1B\1B
10 FAST
15 LET N=20480
20 LET A=8
25 FOR Z=1 TO 2
30 FOR X=1 TO 24
35 FOR Y=1 TO 64
38 IF Y>32 THEN LET A=10-A
40 POKE N,A
45 LET N=N+1
48 IF Y>32 THEN LET A=10-A
50 NEXT Y
55 NEXT X
65 LET A=3
85 NEXT Z
90 SLOW
95 LET N=20480
100 POKE 16524,256*(N/256-INT (N/256))
105 POKE 16525,INT N/256
110 RAND USR 16514
115 LET A=0
120 LET K$=INKEY$
125 IF CODE K$<33 OR CODE K$>36 THEN GOTO 120
130 IF K$="5" THEN LET K=-1
135 IF K$="8" THEN LET K=1
140 IF K$="6" THEN LET K=64
145 IF K$="7" THEN LET K=-64
149 IF (K=1 OR K=-1) AND (K+A<0 OR K+A>32) THEN GOTO 120
150 IF N+K<20480 OR N+K>22015 THEN GOTO 120
155 LET N=N+K
157 IF K=1 OR K=-1 THEN LET A=A+K
160 GOSUB 200
165 GOTO 120
200 POKE 16524,256*(N/256-INT (N/256))
210 POKE 16525,INT N/256
220 RAND USR 16514
230 RETURN
300 FOR N=16514 TO 16570
310 LPRINT N;TAB 10;PEEK N;TAB 15;CHR$ PEEK N
320 NEXT N
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
Skip to content
Scroller
Scroller is a ZX81/TS1000 program that creates a checkerboard pattern in display memory and then uses embedded machine code to scroll the screen in four directions under keyboard control. The machine code routine is stored in the REM statement at line 1, beginning at address 16514, and is called via RAND USR 16514. The BASIC initialization loop at lines 15–85 fills the 24×64 video RAM region starting at address 20480 with alternating byte values (8 and 2) to produce a two-tone checkerboard. Keys 5, 6, 7, and 8 (the ZX81’s cursor keys) control horizontal and vertical scrolling, with boundary checks at lines 149–150 preventing the scroll position from going outside the valid display memory range. Line 300–320 provides a diagnostic routine that LPRINTs the contents and ASCII equivalents of the machine code bytes stored in the REM statement.
Program Analysis
Program Structure
The program divides into four functional sections:
- Lines 1: A
REM statement acting as machine code storage, holding the scroll routine at addresses 16514 onward.
- Lines 10–85: BASIC initialization — fills display RAM (starting at 20480) with a checkerboard pattern using alternating byte values.
- Lines 90–230: Main interactive loop — reads cursor keys (5/6/7/8), validates boundaries, updates the scroll pointer, and calls the machine code display routine via
RAND USR 16514.
- Lines 300–320: A standalone diagnostic utility that
LPRINTs the address, byte value, and ASCII character of each byte in the machine code REM block.
Machine Code in REM Statement
The REM at line 1 stores 57 bytes of Z80 machine code beginning at address 16514 (the first byte after the line’s length bytes and REM token). The routine is invoked with RAND USR 16514, which transfers execution to that address without disturbing the BASIC stack in a disruptive way. The low and high bytes of the target display address are pre-loaded into memory locations 16524 and 16525 (two bytes within the REM data itself, acting as a self-modifying code parameter), set by POKE statements at lines 100–105 and 200–210.
The decoded Z80 sequence begins:
21 21 40 — LD HL, $4021 (points into the REM data for the address parameter)
3E 18 — LD A, $18
77 — LD (HL), A
11 00 60 — LD DE, $6000 (destination buffer)
21 00 50 — LD HL, $5000
C3 93 40 — JP $4093 (jump further into the routine)
The routine copies a region of display memory to a buffer, performs the scroll, and returns. The use of ED B0 (LDIR) is visible in the byte sequence, confirming block memory copy operations for efficiency.
Checkerboard Initialization
Lines 15–85 fill 24 rows × 64 columns (1536 bytes) of video RAM with alternating values. Variable A starts at 8. For each row of 64 columns, when Y>32 the value toggles via A=10-A (swapping between 8 and 2, since 10−8=2 and 10−2=8). The toggle is applied before the POKE at line 38 and then reversed after at line 48, so only the second half of each row uses the alternate value. The outer loop FOR Z=1 TO 2 at line 25 resets A to 3 at line 65 on the second pass, which shifts the phase of the pattern to create the checkerboard effect across rows.
Scroll Pointer and Boundary Checking
The current top-left display address is held in N. Variable A (reused from initialization) tracks the horizontal byte offset within a row (0–32). Variable K holds the scroll delta: ±1 for left/right, ±64 for up/down.
Two boundary guards are applied before any scroll:
- Line 149: For horizontal scrolls (
K=±1), checks that A+K remains within 0–32, preventing wrapping across row boundaries.
- Line 150: Checks that the new address
N+K stays within 20480–22015 (the valid 1.5 KB display RAM window), preventing scrolling outside the initialized region.
Address Passing to Machine Code
Because the machine code routine reads the scroll target address from fixed locations within its own code (at offsets corresponding to addresses 16524–16525), the BASIC layer must write the low byte (256*(N/256-INT(N/256))) and high byte (INT N/256) to those locations before each call. This is a self-modifying code pattern — the POKEs at lines 100/105 and 200/210 patch operand bytes directly inside the REM-stored machine code before invoking it.
Key Mapping
Key Character Code K value Direction 5 33 −1 Left 8 36 +1 Right 6 34 +64 Down 7 35 −64 Up
Line 125 filters for character codes 33–36 (i.e., “5”, “6”, “7”, “8”), rejecting all other keypresses and looping back to INKEY$ polling. This is a compact range-check idiom avoiding four separate IF tests.
Diagnostic Routine
Lines 300–320 are not called from the main program flow and serve as a developer tool. The loop iterates over addresses 16514–16570, printing each address, its raw byte value via PEEK, and the corresponding CHR$ representation to the printer. This allows the programmer to verify the machine code bytes stored in the REM statement are intact after loading.
Notable Techniques
REM as machine code storage: the standard ZX81 technique for embedding Z80 routines without a separate loader or character RAM area.
- Self-modifying machine code: address parameters are patched via
POKE before each RAND USR call.
FAST/SLOW bracketing of the initialization loop (lines 10, 90) speeds up the POKE-fill stage while restoring display output for interactive use.
- The reuse of variable
A for both pattern generation (lines 15–85) and horizontal offset tracking (lines 115–157) requires careful reading — after initialization, A is reset to 0 at line 115 for its new role.
Content
Source Code
1 REM \21\21\40\3E\18\77\11\00\60\21\00\50\C3\93\40\35\E1\01\20\00\ED\B0\3E\76\12\1C\06\00\0E\20\09\E5\21\21\40\3E\00\BE\C2\91\40\E1\01\18\03\2A\0C\40\2C\E5\D1\21\00\60\ED\B0\C9\1B\1B\1B
10 FAST
15 LET N=20480
20 LET A=8
25 FOR Z=1 TO 2
30 FOR X=1 TO 24
35 FOR Y=1 TO 64
38 IF Y>32 THEN LET A=10-A
40 POKE N,A
45 LET N=N+1
48 IF Y>32 THEN LET A=10-A
50 NEXT Y
55 NEXT X
65 LET A=3
85 NEXT Z
90 SLOW
95 LET N=20480
100 POKE 16524,256*(N/256-INT (N/256))
105 POKE 16525,INT N/256
110 RAND USR 16514
115 LET A=0
120 LET K$=INKEY$
125 IF CODE K$<33 OR CODE K$>36 THEN GOTO 120
130 IF K$="5" THEN LET K=-1
135 IF K$="8" THEN LET K=1
140 IF K$="6" THEN LET K=64
145 IF K$="7" THEN LET K=-64
149 IF (K=1 OR K=-1) AND (K+A<0 OR K+A>32) THEN GOTO 120
150 IF N+K<20480 OR N+K>22015 THEN GOTO 120
155 LET N=N+K
157 IF K=1 OR K=-1 THEN LET A=A+K
160 GOSUB 200
165 GOTO 120
200 POKE 16524,256*(N/256-INT (N/256))
210 POKE 16525,INT N/256
220 RAND USR 16514
230 RETURN
300 FOR N=16514 TO 16570
310 LPRINT N;TAB 10;PEEK N;TAB 15;CHR$ PEEK N
320 NEXT N
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
\C3\E1 itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56711 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.7 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.5"
Skip to content
Scroller
Scroller is a ZX81/TS1000 program that creates a checkerboard pattern in display memory and then uses embedded machine code to scroll the screen in four directions under keyboard control. The machine code routine is stored in the REM statement at line 1, beginning at address 16514, and is called via RAND USR 16514. The BASIC initialization loop at lines 15–85 fills the 24×64 video RAM region starting at address 20480 with alternating byte values (8 and 2) to produce a two-tone checkerboard. Keys 5, 6, 7, and 8 (the ZX81’s cursor keys) control horizontal and vertical scrolling, with boundary checks at lines 149–150 preventing the scroll position from going outside the valid display memory range. Line 300–320 provides a diagnostic routine that LPRINTs the contents and ASCII equivalents of the machine code bytes stored in the REM statement.
Program Analysis
Program Structure
The program divides into four functional sections:
- Lines 1: A
REM statement acting as machine code storage, holding the scroll routine at addresses 16514 onward.
- Lines 10–85: BASIC initialization — fills display RAM (starting at 20480) with a checkerboard pattern using alternating byte values.
- Lines 90–230: Main interactive loop — reads cursor keys (5/6/7/8), validates boundaries, updates the scroll pointer, and calls the machine code display routine via
RAND USR 16514.
- Lines 300–320: A standalone diagnostic utility that
LPRINTs the address, byte value, and ASCII character of each byte in the machine code REM block.
Machine Code in REM Statement
The REM at line 1 stores 57 bytes of Z80 machine code beginning at address 16514 (the first byte after the line’s length bytes and REM token). The routine is invoked with RAND USR 16514, which transfers execution to that address without disturbing the BASIC stack in a disruptive way. The low and high bytes of the target display address are pre-loaded into memory locations 16524 and 16525 (two bytes within the REM data itself, acting as a self-modifying code parameter), set by POKE statements at lines 100–105 and 200–210.
The decoded Z80 sequence begins:
21 21 40 — LD HL, $4021 (points into the REM data for the address parameter)
3E 18 — LD A, $18
77 — LD (HL), A
11 00 60 — LD DE, $6000 (destination buffer)
21 00 50 — LD HL, $5000
C3 93 40 — JP $4093 (jump further into the routine)
The routine copies a region of display memory to a buffer, performs the scroll, and returns. The use of ED B0 (LDIR) is visible in the byte sequence, confirming block memory copy operations for efficiency.
Checkerboard Initialization
Lines 15–85 fill 24 rows × 64 columns (1536 bytes) of video RAM with alternating values. Variable A starts at 8. For each row of 64 columns, when Y>32 the value toggles via A=10-A (swapping between 8 and 2, since 10−8=2 and 10−2=8). The toggle is applied before the POKE at line 38 and then reversed after at line 48, so only the second half of each row uses the alternate value. The outer loop FOR Z=1 TO 2 at line 25 resets A to 3 at line 65 on the second pass, which shifts the phase of the pattern to create the checkerboard effect across rows.
Scroll Pointer and Boundary Checking
The current top-left display address is held in N. Variable A (reused from initialization) tracks the horizontal byte offset within a row (0–32). Variable K holds the scroll delta: ±1 for left/right, ±64 for up/down.
Two boundary guards are applied before any scroll:
- Line 149: For horizontal scrolls (
K=±1), checks that A+K remains within 0–32, preventing wrapping across row boundaries.
- Line 150: Checks that the new address
N+K stays within 20480–22015 (the valid 1.5 KB display RAM window), preventing scrolling outside the initialized region.
Address Passing to Machine Code
Because the machine code routine reads the scroll target address from fixed locations within its own code (at offsets corresponding to addresses 16524–16525), the BASIC layer must write the low byte (256*(N/256-INT(N/256))) and high byte (INT N/256) to those locations before each call. This is a self-modifying code pattern — the POKEs at lines 100/105 and 200/210 patch operand bytes directly inside the REM-stored machine code before invoking it.
Key Mapping
Key Character Code K value Direction 5 33 −1 Left 8 36 +1 Right 6 34 +64 Down 7 35 −64 Up
Line 125 filters for character codes 33–36 (i.e., “5”, “6”, “7”, “8”), rejecting all other keypresses and looping back to INKEY$ polling. This is a compact range-check idiom avoiding four separate IF tests.
Diagnostic Routine
Lines 300–320 are not called from the main program flow and serve as a developer tool. The loop iterates over addresses 16514–16570, printing each address, its raw byte value via PEEK, and the corresponding CHR$ representation to the printer. This allows the programmer to verify the machine code bytes stored in the REM statement are intact after loading.
Notable Techniques
REM as machine code storage: the standard ZX81 technique for embedding Z80 routines without a separate loader or character RAM area.
- Self-modifying machine code: address parameters are patched via
POKE before each RAND USR call.
FAST/SLOW bracketing of the initialization loop (lines 10, 90) speeds up the POKE-fill stage while restoring display output for interactive use.
- The reuse of variable
A for both pattern generation (lines 15–85) and horizontal offset tracking (lines 115–157) requires careful reading — after initialization, A is reset to 0 at line 115 for its new role.
Content
Source Code
1 REM \21\21\40\3E\18\77\11\00\60\21\00\50\C3\93\40\35\E1\01\20\00\ED\B0\3E\76\12\1C\06\00\0E\20\09\E5\21\21\40\3E\00\BE\C2\91\40\E1\01\18\03\2A\0C\40\2C\E5\D1\21\00\60\ED\B0\C9\1B\1B\1B
10 FAST
15 LET N=20480
20 LET A=8
25 FOR Z=1 TO 2
30 FOR X=1 TO 24
35 FOR Y=1 TO 64
38 IF Y>32 THEN LET A=10-A
40 POKE N,A
45 LET N=N+1
48 IF Y>32 THEN LET A=10-A
50 NEXT Y
55 NEXT X
65 LET A=3
85 NEXT Z
90 SLOW
95 LET N=20480
100 POKE 16524,256*(N/256-INT (N/256))
105 POKE 16525,INT N/256
110 RAND USR 16514
115 LET A=0
120 LET K$=INKEY$
125 IF CODE K$<33 OR CODE K$>36 THEN GOTO 120
130 IF K$="5" THEN LET K=-1
135 IF K$="8" THEN LET K=1
140 IF K$="6" THEN LET K=64
145 IF K$="7" THEN LET K=-64
149 IF (K=1 OR K=-1) AND (K+A<0 OR K+A>32) THEN GOTO 120
150 IF N+K<20480 OR N+K>22015 THEN GOTO 120
155 LET N=N+K
157 IF K=1 OR K=-1 THEN LET A=A+K
160 GOSUB 200
165 GOTO 120
200 POKE 16524,256*(N/256-INT (N/256))
210 POKE 16525,INT N/256
220 RAND USR 16514
230 RETURN
300 FOR N=16514 TO 16570
310 LPRINT N;TAB 10;PEEK N;TAB 15;CHR$ PEEK N
320 NEXT N
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
\ED\B0E itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56711 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.7 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.5"C
Skip to content
Scroller
Scroller is a ZX81/TS1000 program that creates a checkerboard pattern in display memory and then uses embedded machine code to scroll the screen in four directions under keyboard control. The machine code routine is stored in the REM statement at line 1, beginning at address 16514, and is called via RAND USR 16514. The BASIC initialization loop at lines 15–85 fills the 24×64 video RAM region starting at address 20480 with alternating byte values (8 and 2) to produce a two-tone checkerboard. Keys 5, 6, 7, and 8 (the ZX81’s cursor keys) control horizontal and vertical scrolling, with boundary checks at lines 149–150 preventing the scroll position from going outside the valid display memory range. Line 300–320 provides a diagnostic routine that LPRINTs the contents and ASCII equivalents of the machine code bytes stored in the REM statement.
Program Analysis
Program Structure
The program divides into four functional sections:
- Lines 1: A
REM statement acting as machine code storage, holding the scroll routine at addresses 16514 onward.
- Lines 10–85: BASIC initialization — fills display RAM (starting at 20480) with a checkerboard pattern using alternating byte values.
- Lines 90–230: Main interactive loop — reads cursor keys (5/6/7/8), validates boundaries, updates the scroll pointer, and calls the machine code display routine via
RAND USR 16514.
- Lines 300–320: A standalone diagnostic utility that
LPRINTs the address, byte value, and ASCII character of each byte in the machine code REM block.
Machine Code in REM Statement
The REM at line 1 stores 57 bytes of Z80 machine code beginning at address 16514 (the first byte after the line’s length bytes and REM token). The routine is invoked with RAND USR 16514, which transfers execution to that address without disturbing the BASIC stack in a disruptive way. The low and high bytes of the target display address are pre-loaded into memory locations 16524 and 16525 (two bytes within the REM data itself, acting as a self-modifying code parameter), set by POKE statements at lines 100–105 and 200–210.
The decoded Z80 sequence begins:
21 21 40 — LD HL, $4021 (points into the REM data for the address parameter)
3E 18 — LD A, $18
77 — LD (HL), A
11 00 60 — LD DE, $6000 (destination buffer)
21 00 50 — LD HL, $5000
C3 93 40 — JP $4093 (jump further into the routine)
The routine copies a region of display memory to a buffer, performs the scroll, and returns. The use of ED B0 (LDIR) is visible in the byte sequence, confirming block memory copy operations for efficiency.
Checkerboard Initialization
Lines 15–85 fill 24 rows × 64 columns (1536 bytes) of video RAM with alternating values. Variable A starts at 8. For each row of 64 columns, when Y>32 the value toggles via A=10-A (swapping between 8 and 2, since 10−8=2 and 10−2=8). The toggle is applied before the POKE at line 38 and then reversed after at line 48, so only the second half of each row uses the alternate value. The outer loop FOR Z=1 TO 2 at line 25 resets A to 3 at line 65 on the second pass, which shifts the phase of the pattern to create the checkerboard effect across rows.
Scroll Pointer and Boundary Checking
The current top-left display address is held in N. Variable A (reused from initialization) tracks the horizontal byte offset within a row (0–32). Variable K holds the scroll delta: ±1 for left/right, ±64 for up/down.
Two boundary guards are applied before any scroll:
- Line 149: For horizontal scrolls (
K=±1), checks that A+K remains within 0–32, preventing wrapping across row boundaries.
- Line 150: Checks that the new address
N+K stays within 20480–22015 (the valid 1.5 KB display RAM window), preventing scrolling outside the initialized region.
Address Passing to Machine Code
Because the machine code routine reads the scroll target address from fixed locations within its own code (at offsets corresponding to addresses 16524–16525), the BASIC layer must write the low byte (256*(N/256-INT(N/256))) and high byte (INT N/256) to those locations before each call. This is a self-modifying code pattern — the POKEs at lines 100/105 and 200/210 patch operand bytes directly inside the REM-stored machine code before invoking it.
Key Mapping
Key Character Code K value Direction 5 33 −1 Left 8 36 +1 Right 6 34 +64 Down 7 35 −64 Up
Line 125 filters for character codes 33–36 (i.e., “5”, “6”, “7”, “8”), rejecting all other keypresses and looping back to INKEY$ polling. This is a compact range-check idiom avoiding four separate IF tests.
Diagnostic Routine
Lines 300–320 are not called from the main program flow and serve as a developer tool. The loop iterates over addresses 16514–16570, printing each address, its raw byte value via PEEK, and the corresponding CHR$ representation to the printer. This allows the programmer to verify the machine code bytes stored in the REM statement are intact after loading.
Notable Techniques
REM as machine code storage: the standard ZX81 technique for embedding Z80 routines without a separate loader or character RAM area.
- Self-modifying machine code: address parameters are patched via
POKE before each RAND USR call.
FAST/SLOW bracketing of the initialization loop (lines 10, 90) speeds up the POKE-fill stage while restoring display output for interactive use.
- The reuse of variable
A for both pattern generation (lines 15–85) and horizontal offset tracking (lines 115–157) requires careful reading — after initialization, A is reset to 0 at line 115 for its new role.
Content
Source Code
1 REM \21\21\40\3E\18\77\11\00\60\21\00\50\C3\93\40\35\E1\01\20\00\ED\B0\3E\76\12\1C\06\00\0E\20\09\E5\21\21\40\3E\00\BE\C2\91\40\E1\01\18\03\2A\0C\40\2C\E5\D1\21\00\60\ED\B0\C9\1B\1B\1B
10 FAST
15 LET N=20480
20 LET A=8
25 FOR Z=1 TO 2
30 FOR X=1 TO 24
35 FOR Y=1 TO 64
38 IF Y>32 THEN LET A=10-A
40 POKE N,A
45 LET N=N+1
48 IF Y>32 THEN LET A=10-A
50 NEXT Y
55 NEXT X
65 LET A=3
85 NEXT Z
90 SLOW
95 LET N=20480
100 POKE 16524,256*(N/256-INT (N/256))
105 POKE 16525,INT N/256
110 RAND USR 16514
115 LET A=0
120 LET K$=INKEY$
125 IF CODE K$<33 OR CODE K$>36 THEN GOTO 120
130 IF K$="5" THEN LET K=-1
135 IF K$="8" THEN LET K=1
140 IF K$="6" THEN LET K=64
145 IF K$="7" THEN LET K=-64
149 IF (K=1 OR K=-1) AND (K+A<0 OR K+A>32) THEN GOTO 120
150 IF N+K<20480 OR N+K>22015 THEN GOTO 120
155 LET N=N+K
157 IF K=1 OR K=-1 THEN LET A=A+K
160 GOSUB 200
165 GOTO 120
200 POKE 16524,256*(N/256-INT (N/256))
210 POKE 16525,INT N/256
220 RAND USR 16514
230 RETURN
300 FOR N=16514 TO 16570
310 LPRINT N;TAB 10;PEEK N;TAB 15;CHR$ PEEK N
320 NEXT N
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
Skip to content
Scroller
Scroller is a ZX81/TS1000 program that creates a checkerboard pattern in display memory and then uses embedded machine code to scroll the screen in four directions under keyboard control. The machine code routine is stored in the REM statement at line 1, beginning at address 16514, and is called via RAND USR 16514. The BASIC initialization loop at lines 15–85 fills the 24×64 video RAM region starting at address 20480 with alternating byte values (8 and 2) to produce a two-tone checkerboard. Keys 5, 6, 7, and 8 (the ZX81’s cursor keys) control horizontal and vertical scrolling, with boundary checks at lines 149–150 preventing the scroll position from going outside the valid display memory range. Line 300–320 provides a diagnostic routine that LPRINTs the contents and ASCII equivalents of the machine code bytes stored in the REM statement.
Program Analysis
Program Structure
The program divides into four functional sections:
- Lines 1: A
REM statement acting as machine code storage, holding the scroll routine at addresses 16514 onward.
- Lines 10–85: BASIC initialization — fills display RAM (starting at 20480) with a checkerboard pattern using alternating byte values.
- Lines 90–230: Main interactive loop — reads cursor keys (5/6/7/8), validates boundaries, updates the scroll pointer, and calls the machine code display routine via
RAND USR 16514.
- Lines 300–320: A standalone diagnostic utility that
LPRINTs the address, byte value, and ASCII character of each byte in the machine code REM block.
Machine Code in REM Statement
The REM at line 1 stores 57 bytes of Z80 machine code beginning at address 16514 (the first byte after the line’s length bytes and REM token). The routine is invoked with RAND USR 16514, which transfers execution to that address without disturbing the BASIC stack in a disruptive way. The low and high bytes of the target display address are pre-loaded into memory locations 16524 and 16525 (two bytes within the REM data itself, acting as a self-modifying code parameter), set by POKE statements at lines 100–105 and 200–210.
The decoded Z80 sequence begins:
21 21 40 — LD HL, $4021 (points into the REM data for the address parameter)
3E 18 — LD A, $18
77 — LD (HL), A
11 00 60 — LD DE, $6000 (destination buffer)
21 00 50 — LD HL, $5000
C3 93 40 — JP $4093 (jump further into the routine)
The routine copies a region of display memory to a buffer, performs the scroll, and returns. The use of ED B0 (LDIR) is visible in the byte sequence, confirming block memory copy operations for efficiency.
Checkerboard Initialization
Lines 15–85 fill 24 rows × 64 columns (1536 bytes) of video RAM with alternating values. Variable A starts at 8. For each row of 64 columns, when Y>32 the value toggles via A=10-A (swapping between 8 and 2, since 10−8=2 and 10−2=8). The toggle is applied before the POKE at line 38 and then reversed after at line 48, so only the second half of each row uses the alternate value. The outer loop FOR Z=1 TO 2 at line 25 resets A to 3 at line 65 on the second pass, which shifts the phase of the pattern to create the checkerboard effect across rows.
Scroll Pointer and Boundary Checking
The current top-left display address is held in N. Variable A (reused from initialization) tracks the horizontal byte offset within a row (0–32). Variable K holds the scroll delta: ±1 for left/right, ±64 for up/down.
Two boundary guards are applied before any scroll:
- Line 149: For horizontal scrolls (
K=±1), checks that A+K remains within 0–32, preventing wrapping across row boundaries.
- Line 150: Checks that the new address
N+K stays within 20480–22015 (the valid 1.5 KB display RAM window), preventing scrolling outside the initialized region.
Address Passing to Machine Code
Because the machine code routine reads the scroll target address from fixed locations within its own code (at offsets corresponding to addresses 16524–16525), the BASIC layer must write the low byte (256*(N/256-INT(N/256))) and high byte (INT N/256) to those locations before each call. This is a self-modifying code pattern — the POKEs at lines 100/105 and 200/210 patch operand bytes directly inside the REM-stored machine code before invoking it.
Key Mapping
Key Character Code K value Direction 5 33 −1 Left 8 36 +1 Right 6 34 +64 Down 7 35 −64 Up
Line 125 filters for character codes 33–36 (i.e., “5”, “6”, “7”, “8”), rejecting all other keypresses and looping back to INKEY$ polling. This is a compact range-check idiom avoiding four separate IF tests.
Diagnostic Routine
Lines 300–320 are not called from the main program flow and serve as a developer tool. The loop iterates over addresses 16514–16570, printing each address, its raw byte value via PEEK, and the corresponding CHR$ representation to the printer. This allows the programmer to verify the machine code bytes stored in the REM statement are intact after loading.
Notable Techniques
REM as machine code storage: the standard ZX81 technique for embedding Z80 routines without a separate loader or character RAM area.
- Self-modifying machine code: address parameters are patched via
POKE before each RAND USR call.
FAST/SLOW bracketing of the initialization loop (lines 10, 90) speeds up the POKE-fill stage while restoring display output for interactive use.
- The reuse of variable
A for both pattern generation (lines 15–85) and horizontal offset tracking (lines 115–157) requires careful reading — after initialization, A is reset to 0 at line 115 for its new role.
Content
Source Code
1 REM \21\21\40\3E\18\77\11\00\60\21\00\50\C3\93\40\35\E1\01\20\00\ED\B0\3E\76\12\1C\06\00\0E\20\09\E5\21\21\40\3E\00\BE\C2\91\40\E1\01\18\03\2A\0C\40\2C\E5\D1\21\00\60\ED\B0\C9\1B\1B\1B
10 FAST
15 LET N=20480
20 LET A=8
25 FOR Z=1 TO 2
30 FOR X=1 TO 24
35 FOR Y=1 TO 64
38 IF Y>32 THEN LET A=10-A
40 POKE N,A
45 LET N=N+1
48 IF Y>32 THEN LET A=10-A
50 NEXT Y
55 NEXT X
65 LET A=3
85 NEXT Z
90 SLOW
95 LET N=20480
100 POKE 16524,256*(N/256-INT (N/256))
105 POKE 16525,INT N/256
110 RAND USR 16514
115 LET A=0
120 LET K$=INKEY$
125 IF CODE K$<33 OR CODE K$>36 THEN GOTO 120
130 IF K$="5" THEN LET K=-1
135 IF K$="8" THEN LET K=1
140 IF K$="6" THEN LET K=64
145 IF K$="7" THEN LET K=-64
149 IF (K=1 OR K=-1) AND (K+A<0 OR K+A>32) THEN GOTO 120
150 IF N+K<20480 OR N+K>22015 THEN GOTO 120
155 LET N=N+K
157 IF K=1 OR K=-1 THEN LET A=A+K
160 GOSUB 200
165 GOTO 120
200 POKE 16524,256*(N/256-INT (N/256))
210 POKE 16525,INT N/256
220 RAND USR 16514
230 RETURN
300 FOR N=16514 TO 16570
310 LPRINT N;TAB 10;PEEK N;TAB 15;CHR$ PEEK N
320 NEXT N
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
E\E5E
Skip to content
Scroller
Scroller is a ZX81/TS1000 program that creates a checkerboard pattern in display memory and then uses embedded machine code to scroll the screen in four directions under keyboard control. The machine code routine is stored in the REM statement at line 1, beginning at address 16514, and is called via RAND USR 16514. The BASIC initialization loop at lines 15–85 fills the 24×64 video RAM region starting at address 20480 with alternating byte values (8 and 2) to produce a two-tone checkerboard. Keys 5, 6, 7, and 8 (the ZX81’s cursor keys) control horizontal and vertical scrolling, with boundary checks at lines 149–150 preventing the scroll position from going outside the valid display memory range. Line 300–320 provides a diagnostic routine that LPRINTs the contents and ASCII equivalents of the machine code bytes stored in the REM statement.
Program Analysis
Program Structure
The program divides into four functional sections:
- Lines 1: A
REM statement acting as machine code storage, holding the scroll routine at addresses 16514 onward.
- Lines 10–85: BASIC initialization — fills display RAM (starting at 20480) with a checkerboard pattern using alternating byte values.
- Lines 90–230: Main interactive loop — reads cursor keys (5/6/7/8), validates boundaries, updates the scroll pointer, and calls the machine code display routine via
RAND USR 16514.
- Lines 300–320: A standalone diagnostic utility that
LPRINTs the address, byte value, and ASCII character of each byte in the machine code REM block.
Machine Code in REM Statement
The REM at line 1 stores 57 bytes of Z80 machine code beginning at address 16514 (the first byte after the line’s length bytes and REM token). The routine is invoked with RAND USR 16514, which transfers execution to that address without disturbing the BASIC stack in a disruptive way. The low and high bytes of the target display address are pre-loaded into memory locations 16524 and 16525 (two bytes within the REM data itself, acting as a self-modifying code parameter), set by POKE statements at lines 100–105 and 200–210.
The decoded Z80 sequence begins:
21 21 40 — LD HL, $4021 (points into the REM data for the address parameter)
3E 18 — LD A, $18
77 — LD (HL), A
11 00 60 — LD DE, $6000 (destination buffer)
21 00 50 — LD HL, $5000
C3 93 40 — JP $4093 (jump further into the routine)
The routine copies a region of display memory to a buffer, performs the scroll, and returns. The use of ED B0 (LDIR) is visible in the byte sequence, confirming block memory copy operations for efficiency.
Checkerboard Initialization
Lines 15–85 fill 24 rows × 64 columns (1536 bytes) of video RAM with alternating values. Variable A starts at 8. For each row of 64 columns, when Y>32 the value toggles via A=10-A (swapping between 8 and 2, since 10−8=2 and 10−2=8). The toggle is applied before the POKE at line 38 and then reversed after at line 48, so only the second half of each row uses the alternate value. The outer loop FOR Z=1 TO 2 at line 25 resets A to 3 at line 65 on the second pass, which shifts the phase of the pattern to create the checkerboard effect across rows.
Scroll Pointer and Boundary Checking
The current top-left display address is held in N. Variable A (reused from initialization) tracks the horizontal byte offset within a row (0–32). Variable K holds the scroll delta: ±1 for left/right, ±64 for up/down.
Two boundary guards are applied before any scroll:
- Line 149: For horizontal scrolls (
K=±1), checks that A+K remains within 0–32, preventing wrapping across row boundaries.
- Line 150: Checks that the new address
N+K stays within 20480–22015 (the valid 1.5 KB display RAM window), preventing scrolling outside the initialized region.
Address Passing to Machine Code
Because the machine code routine reads the scroll target address from fixed locations within its own code (at offsets corresponding to addresses 16524–16525), the BASIC layer must write the low byte (256*(N/256-INT(N/256))) and high byte (INT N/256) to those locations before each call. This is a self-modifying code pattern — the POKEs at lines 100/105 and 200/210 patch operand bytes directly inside the REM-stored machine code before invoking it.
Key Mapping
Key Character Code K value Direction 5 33 −1 Left 8 36 +1 Right 6 34 +64 Down 7 35 −64 Up
Line 125 filters for character codes 33–36 (i.e., “5”, “6”, “7”, “8”), rejecting all other keypresses and looping back to INKEY$ polling. This is a compact range-check idiom avoiding four separate IF tests.
Diagnostic Routine
Lines 300–320 are not called from the main program flow and serve as a developer tool. The loop iterates over addresses 16514–16570, printing each address, its raw byte value via PEEK, and the corresponding CHR$ representation to the printer. This allows the programmer to verify the machine code bytes stored in the REM statement are intact after loading.
Notable Techniques
REM as machine code storage: the standard ZX81 technique for embedding Z80 routines without a separate loader or character RAM area.
- Self-modifying machine code: address parameters are patched via
POKE before each RAND USR call.
FAST/SLOW bracketing of the initialization loop (lines 10, 90) speeds up the POKE-fill stage while restoring display output for interactive use.
- The reuse of variable
A for both pattern generation (lines 15–85) and horizontal offset tracking (lines 115–157) requires careful reading — after initialization, A is reset to 0 at line 115 for its new role.
Content
Source Code
1 REM \21\21\40\3E\18\77\11\00\60\21\00\50\C3\93\40\35\E1\01\20\00\ED\B0\3E\76\12\1C\06\00\0E\20\09\E5\21\21\40\3E\00\BE\C2\91\40\E1\01\18\03\2A\0C\40\2C\E5\D1\21\00\60\ED\B0\C9\1B\1B\1B
10 FAST
15 LET N=20480
20 LET A=8
25 FOR Z=1 TO 2
30 FOR X=1 TO 24
35 FOR Y=1 TO 64
38 IF Y>32 THEN LET A=10-A
40 POKE N,A
45 LET N=N+1
48 IF Y>32 THEN LET A=10-A
50 NEXT Y
55 NEXT X
65 LET A=3
85 NEXT Z
90 SLOW
95 LET N=20480
100 POKE 16524,256*(N/256-INT (N/256))
105 POKE 16525,INT N/256
110 RAND USR 16514
115 LET A=0
120 LET K$=INKEY$
125 IF CODE K$<33 OR CODE K$>36 THEN GOTO 120
130 IF K$="5" THEN LET K=-1
135 IF K$="8" THEN LET K=1
140 IF K$="6" THEN LET K=64
145 IF K$="7" THEN LET K=-64
149 IF (K=1 OR K=-1) AND (K+A<0 OR K+A>32) THEN GOTO 120
150 IF N+K<20480 OR N+K>22015 THEN GOTO 120
155 LET N=N+K
157 IF K=1 OR K=-1 THEN LET A=A+K
160 GOSUB 200
165 GOTO 120
200 POKE 16524,256*(N/256-INT (N/256))
210 POKE 16525,INT N/256
220 RAND USR 16514
230 RETURN
300 FOR N=16514 TO 16570
310 LPRINT N;TAB 10;PEEK N;TAB 15;CHR$ PEEK N
320 NEXT N
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
\BE\C2\E1 itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56711 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.7 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.5"
Skip to content
Scroller
Scroller is a ZX81/TS1000 program that creates a checkerboard pattern in display memory and then uses embedded machine code to scroll the screen in four directions under keyboard control. The machine code routine is stored in the REM statement at line 1, beginning at address 16514, and is called via RAND USR 16514. The BASIC initialization loop at lines 15–85 fills the 24×64 video RAM region starting at address 20480 with alternating byte values (8 and 2) to produce a two-tone checkerboard. Keys 5, 6, 7, and 8 (the ZX81’s cursor keys) control horizontal and vertical scrolling, with boundary checks at lines 149–150 preventing the scroll position from going outside the valid display memory range. Line 300–320 provides a diagnostic routine that LPRINTs the contents and ASCII equivalents of the machine code bytes stored in the REM statement.
Program Analysis
Program Structure
The program divides into four functional sections:
- Lines 1: A
REM statement acting as machine code storage, holding the scroll routine at addresses 16514 onward.
- Lines 10–85: BASIC initialization — fills display RAM (starting at 20480) with a checkerboard pattern using alternating byte values.
- Lines 90–230: Main interactive loop — reads cursor keys (5/6/7/8), validates boundaries, updates the scroll pointer, and calls the machine code display routine via
RAND USR 16514.
- Lines 300–320: A standalone diagnostic utility that
LPRINTs the address, byte value, and ASCII character of each byte in the machine code REM block.
Machine Code in REM Statement
The REM at line 1 stores 57 bytes of Z80 machine code beginning at address 16514 (the first byte after the line’s length bytes and REM token). The routine is invoked with RAND USR 16514, which transfers execution to that address without disturbing the BASIC stack in a disruptive way. The low and high bytes of the target display address are pre-loaded into memory locations 16524 and 16525 (two bytes within the REM data itself, acting as a self-modifying code parameter), set by POKE statements at lines 100–105 and 200–210.
The decoded Z80 sequence begins:
21 21 40 — LD HL, $4021 (points into the REM data for the address parameter)
3E 18 — LD A, $18
77 — LD (HL), A
11 00 60 — LD DE, $6000 (destination buffer)
21 00 50 — LD HL, $5000
C3 93 40 — JP $4093 (jump further into the routine)
The routine copies a region of display memory to a buffer, performs the scroll, and returns. The use of ED B0 (LDIR) is visible in the byte sequence, confirming block memory copy operations for efficiency.
Checkerboard Initialization
Lines 15–85 fill 24 rows × 64 columns (1536 bytes) of video RAM with alternating values. Variable A starts at 8. For each row of 64 columns, when Y>32 the value toggles via A=10-A (swapping between 8 and 2, since 10−8=2 and 10−2=8). The toggle is applied before the POKE at line 38 and then reversed after at line 48, so only the second half of each row uses the alternate value. The outer loop FOR Z=1 TO 2 at line 25 resets A to 3 at line 65 on the second pass, which shifts the phase of the pattern to create the checkerboard effect across rows.
Scroll Pointer and Boundary Checking
The current top-left display address is held in N. Variable A (reused from initialization) tracks the horizontal byte offset within a row (0–32). Variable K holds the scroll delta: ±1 for left/right, ±64 for up/down.
Two boundary guards are applied before any scroll:
- Line 149: For horizontal scrolls (
K=±1), checks that A+K remains within 0–32, preventing wrapping across row boundaries.
- Line 150: Checks that the new address
N+K stays within 20480–22015 (the valid 1.5 KB display RAM window), preventing scrolling outside the initialized region.
Address Passing to Machine Code
Because the machine code routine reads the scroll target address from fixed locations within its own code (at offsets corresponding to addresses 16524–16525), the BASIC layer must write the low byte (256*(N/256-INT(N/256))) and high byte (INT N/256) to those locations before each call. This is a self-modifying code pattern — the POKEs at lines 100/105 and 200/210 patch operand bytes directly inside the REM-stored machine code before invoking it.
Key Mapping
Key Character Code K value Direction 5 33 −1 Left 8 36 +1 Right 6 34 +64 Down 7 35 −64 Up
Line 125 filters for character codes 33–36 (i.e., “5”, “6”, “7”, “8”), rejecting all other keypresses and looping back to INKEY$ polling. This is a compact range-check idiom avoiding four separate IF tests.
Diagnostic Routine
Lines 300–320 are not called from the main program flow and serve as a developer tool. The loop iterates over addresses 16514–16570, printing each address, its raw byte value via PEEK, and the corresponding CHR$ representation to the printer. This allows the programmer to verify the machine code bytes stored in the REM statement are intact after loading.
Notable Techniques
REM as machine code storage: the standard ZX81 technique for embedding Z80 routines without a separate loader or character RAM area.
- Self-modifying machine code: address parameters are patched via
POKE before each RAND USR call.
FAST/SLOW bracketing of the initialization loop (lines 10, 90) speeds up the POKE-fill stage while restoring display output for interactive use.
- The reuse of variable
A for both pattern generation (lines 15–85) and horizontal offset tracking (lines 115–157) requires careful reading — after initialization, A is reset to 0 at line 115 for its new role.
Content
Source Code
1 REM \21\21\40\3E\18\77\11\00\60\21\00\50\C3\93\40\35\E1\01\20\00\ED\B0\3E\76\12\1C\06\00\0E\20\09\E5\21\21\40\3E\00\BE\C2\91\40\E1\01\18\03\2A\0C\40\2C\E5\D1\21\00\60\ED\B0\C9\1B\1B\1B
10 FAST
15 LET N=20480
20 LET A=8
25 FOR Z=1 TO 2
30 FOR X=1 TO 24
35 FOR Y=1 TO 64
38 IF Y>32 THEN LET A=10-A
40 POKE N,A
45 LET N=N+1
48 IF Y>32 THEN LET A=10-A
50 NEXT Y
55 NEXT X
65 LET A=3
85 NEXT Z
90 SLOW
95 LET N=20480
100 POKE 16524,256*(N/256-INT (N/256))
105 POKE 16525,INT N/256
110 RAND USR 16514
115 LET A=0
120 LET K$=INKEY$
125 IF CODE K$<33 OR CODE K$>36 THEN GOTO 120
130 IF K$="5" THEN LET K=-1
135 IF K$="8" THEN LET K=1
140 IF K$="6" THEN LET K=64
145 IF K$="7" THEN LET K=-64
149 IF (K=1 OR K=-1) AND (K+A<0 OR K+A>32) THEN GOTO 120
150 IF N+K<20480 OR N+K>22015 THEN GOTO 120
155 LET N=N+K
157 IF K=1 OR K=-1 THEN LET A=A+K
160 GOSUB 200
165 GOTO 120
200 POKE 16524,256*(N/256-INT (N/256))
210 POKE 16525,INT N/256
220 RAND USR 16514
230 RETURN
300 FOR N=16514 TO 16570
310 LPRINT N;TAB 10;PEEK N;TAB 15;CHR$ PEEK N
320 NEXT N
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
A
Skip to content
Scroller
Scroller is a ZX81/TS1000 program that creates a checkerboard pattern in display memory and then uses embedded machine code to scroll the screen in four directions under keyboard control. The machine code routine is stored in the REM statement at line 1, beginning at address 16514, and is called via RAND USR 16514. The BASIC initialization loop at lines 15–85 fills the 24×64 video RAM region starting at address 20480 with alternating byte values (8 and 2) to produce a two-tone checkerboard. Keys 5, 6, 7, and 8 (the ZX81’s cursor keys) control horizontal and vertical scrolling, with boundary checks at lines 149–150 preventing the scroll position from going outside the valid display memory range. Line 300–320 provides a diagnostic routine that LPRINTs the contents and ASCII equivalents of the machine code bytes stored in the REM statement.
Program Analysis
Program Structure
The program divides into four functional sections:
- Lines 1: A
REM statement acting as machine code storage, holding the scroll routine at addresses 16514 onward.
- Lines 10–85: BASIC initialization — fills display RAM (starting at 20480) with a checkerboard pattern using alternating byte values.
- Lines 90–230: Main interactive loop — reads cursor keys (5/6/7/8), validates boundaries, updates the scroll pointer, and calls the machine code display routine via
RAND USR 16514.
- Lines 300–320: A standalone diagnostic utility that
LPRINTs the address, byte value, and ASCII character of each byte in the machine code REM block.
Machine Code in REM Statement
The REM at line 1 stores 57 bytes of Z80 machine code beginning at address 16514 (the first byte after the line’s length bytes and REM token). The routine is invoked with RAND USR 16514, which transfers execution to that address without disturbing the BASIC stack in a disruptive way. The low and high bytes of the target display address are pre-loaded into memory locations 16524 and 16525 (two bytes within the REM data itself, acting as a self-modifying code parameter), set by POKE statements at lines 100–105 and 200–210.
The decoded Z80 sequence begins:
21 21 40 — LD HL, $4021 (points into the REM data for the address parameter)
3E 18 — LD A, $18
77 — LD (HL), A
11 00 60 — LD DE, $6000 (destination buffer)
21 00 50 — LD HL, $5000
C3 93 40 — JP $4093 (jump further into the routine)
The routine copies a region of display memory to a buffer, performs the scroll, and returns. The use of ED B0 (LDIR) is visible in the byte sequence, confirming block memory copy operations for efficiency.
Checkerboard Initialization
Lines 15–85 fill 24 rows × 64 columns (1536 bytes) of video RAM with alternating values. Variable A starts at 8. For each row of 64 columns, when Y>32 the value toggles via A=10-A (swapping between 8 and 2, since 10−8=2 and 10−2=8). The toggle is applied before the POKE at line 38 and then reversed after at line 48, so only the second half of each row uses the alternate value. The outer loop FOR Z=1 TO 2 at line 25 resets A to 3 at line 65 on the second pass, which shifts the phase of the pattern to create the checkerboard effect across rows.
Scroll Pointer and Boundary Checking
The current top-left display address is held in N. Variable A (reused from initialization) tracks the horizontal byte offset within a row (0–32). Variable K holds the scroll delta: ±1 for left/right, ±64 for up/down.
Two boundary guards are applied before any scroll:
- Line 149: For horizontal scrolls (
K=±1), checks that A+K remains within 0–32, preventing wrapping across row boundaries.
- Line 150: Checks that the new address
N+K stays within 20480–22015 (the valid 1.5 KB display RAM window), preventing scrolling outside the initialized region.
Address Passing to Machine Code
Because the machine code routine reads the scroll target address from fixed locations within its own code (at offsets corresponding to addresses 16524–16525), the BASIC layer must write the low byte (256*(N/256-INT(N/256))) and high byte (INT N/256) to those locations before each call. This is a self-modifying code pattern — the POKEs at lines 100/105 and 200/210 patch operand bytes directly inside the REM-stored machine code before invoking it.
Key Mapping
Key Character Code K value Direction 5 33 −1 Left 8 36 +1 Right 6 34 +64 Down 7 35 −64 Up
Line 125 filters for character codes 33–36 (i.e., “5”, “6”, “7”, “8”), rejecting all other keypresses and looping back to INKEY$ polling. This is a compact range-check idiom avoiding four separate IF tests.
Diagnostic Routine
Lines 300–320 are not called from the main program flow and serve as a developer tool. The loop iterates over addresses 16514–16570, printing each address, its raw byte value via PEEK, and the corresponding CHR$ representation to the printer. This allows the programmer to verify the machine code bytes stored in the REM statement are intact after loading.
Notable Techniques
REM as machine code storage: the standard ZX81 technique for embedding Z80 routines without a separate loader or character RAM area.
- Self-modifying machine code: address parameters are patched via
POKE before each RAND USR call.
FAST/SLOW bracketing of the initialization loop (lines 10, 90) speeds up the POKE-fill stage while restoring display output for interactive use.
- The reuse of variable
A for both pattern generation (lines 15–85) and horizontal offset tracking (lines 115–157) requires careful reading — after initialization, A is reset to 0 at line 115 for its new role.
Content
Source Code
1 REM \21\21\40\3E\18\77\11\00\60\21\00\50\C3\93\40\35\E1\01\20\00\ED\B0\3E\76\12\1C\06\00\0E\20\09\E5\21\21\40\3E\00\BE\C2\91\40\E1\01\18\03\2A\0C\40\2C\E5\D1\21\00\60\ED\B0\C9\1B\1B\1B
10 FAST
15 LET N=20480
20 LET A=8
25 FOR Z=1 TO 2
30 FOR X=1 TO 24
35 FOR Y=1 TO 64
38 IF Y>32 THEN LET A=10-A
40 POKE N,A
45 LET N=N+1
48 IF Y>32 THEN LET A=10-A
50 NEXT Y
55 NEXT X
65 LET A=3
85 NEXT Z
90 SLOW
95 LET N=20480
100 POKE 16524,256*(N/256-INT (N/256))
105 POKE 16525,INT N/256
110 RAND USR 16514
115 LET A=0
120 LET K$=INKEY$
125 IF CODE K$<33 OR CODE K$>36 THEN GOTO 120
130 IF K$="5" THEN LET K=-1
135 IF K$="8" THEN LET K=1
140 IF K$="6" THEN LET K=64
145 IF K$="7" THEN LET K=-64
149 IF (K=1 OR K=-1) AND (K+A<0 OR K+A>32) THEN GOTO 120
150 IF N+K<20480 OR N+K>22015 THEN GOTO 120
155 LET N=N+K
157 IF K=1 OR K=-1 THEN LET A=A+K
160 GOSUB 200
165 GOTO 120
200 POKE 16524,256*(N/256-INT (N/256))
210 POKE 16525,INT N/256
220 RAND USR 16514
230 RETURN
300 FOR N=16514 TO 16570
310 LPRINT N;TAB 10;PEEK N;TAB 15;CHR$ PEEK N
320 NEXT N
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
C
Skip to content
Scroller
Scroller is a ZX81/TS1000 program that creates a checkerboard pattern in display memory and then uses embedded machine code to scroll the screen in four directions under keyboard control. The machine code routine is stored in the REM statement at line 1, beginning at address 16514, and is called via RAND USR 16514. The BASIC initialization loop at lines 15–85 fills the 24×64 video RAM region starting at address 20480 with alternating byte values (8 and 2) to produce a two-tone checkerboard. Keys 5, 6, 7, and 8 (the ZX81’s cursor keys) control horizontal and vertical scrolling, with boundary checks at lines 149–150 preventing the scroll position from going outside the valid display memory range. Line 300–320 provides a diagnostic routine that LPRINTs the contents and ASCII equivalents of the machine code bytes stored in the REM statement.
Program Analysis
Program Structure
The program divides into four functional sections:
- Lines 1: A
REM statement acting as machine code storage, holding the scroll routine at addresses 16514 onward.
- Lines 10–85: BASIC initialization — fills display RAM (starting at 20480) with a checkerboard pattern using alternating byte values.
- Lines 90–230: Main interactive loop — reads cursor keys (5/6/7/8), validates boundaries, updates the scroll pointer, and calls the machine code display routine via
RAND USR 16514.
- Lines 300–320: A standalone diagnostic utility that
LPRINTs the address, byte value, and ASCII character of each byte in the machine code REM block.
Machine Code in REM Statement
The REM at line 1 stores 57 bytes of Z80 machine code beginning at address 16514 (the first byte after the line’s length bytes and REM token). The routine is invoked with RAND USR 16514, which transfers execution to that address without disturbing the BASIC stack in a disruptive way. The low and high bytes of the target display address are pre-loaded into memory locations 16524 and 16525 (two bytes within the REM data itself, acting as a self-modifying code parameter), set by POKE statements at lines 100–105 and 200–210.
The decoded Z80 sequence begins:
21 21 40 — LD HL, $4021 (points into the REM data for the address parameter)
3E 18 — LD A, $18
77 — LD (HL), A
11 00 60 — LD DE, $6000 (destination buffer)
21 00 50 — LD HL, $5000
C3 93 40 — JP $4093 (jump further into the routine)
The routine copies a region of display memory to a buffer, performs the scroll, and returns. The use of ED B0 (LDIR) is visible in the byte sequence, confirming block memory copy operations for efficiency.
Checkerboard Initialization
Lines 15–85 fill 24 rows × 64 columns (1536 bytes) of video RAM with alternating values. Variable A starts at 8. For each row of 64 columns, when Y>32 the value toggles via A=10-A (swapping between 8 and 2, since 10−8=2 and 10−2=8). The toggle is applied before the POKE at line 38 and then reversed after at line 48, so only the second half of each row uses the alternate value. The outer loop FOR Z=1 TO 2 at line 25 resets A to 3 at line 65 on the second pass, which shifts the phase of the pattern to create the checkerboard effect across rows.
Scroll Pointer and Boundary Checking
The current top-left display address is held in N. Variable A (reused from initialization) tracks the horizontal byte offset within a row (0–32). Variable K holds the scroll delta: ±1 for left/right, ±64 for up/down.
Two boundary guards are applied before any scroll:
- Line 149: For horizontal scrolls (
K=±1), checks that A+K remains within 0–32, preventing wrapping across row boundaries.
- Line 150: Checks that the new address
N+K stays within 20480–22015 (the valid 1.5 KB display RAM window), preventing scrolling outside the initialized region.
Address Passing to Machine Code
Because the machine code routine reads the scroll target address from fixed locations within its own code (at offsets corresponding to addresses 16524–16525), the BASIC layer must write the low byte (256*(N/256-INT(N/256))) and high byte (INT N/256) to those locations before each call. This is a self-modifying code pattern — the POKEs at lines 100/105 and 200/210 patch operand bytes directly inside the REM-stored machine code before invoking it.
Key Mapping
Key Character Code K value Direction 5 33 −1 Left 8 36 +1 Right 6 34 +64 Down 7 35 −64 Up
Line 125 filters for character codes 33–36 (i.e., “5”, “6”, “7”, “8”), rejecting all other keypresses and looping back to INKEY$ polling. This is a compact range-check idiom avoiding four separate IF tests.
Diagnostic Routine
Lines 300–320 are not called from the main program flow and serve as a developer tool. The loop iterates over addresses 16514–16570, printing each address, its raw byte value via PEEK, and the corresponding CHR$ representation to the printer. This allows the programmer to verify the machine code bytes stored in the REM statement are intact after loading.
Notable Techniques
REM as machine code storage: the standard ZX81 technique for embedding Z80 routines without a separate loader or character RAM area.
- Self-modifying machine code: address parameters are patched via
POKE before each RAND USR call.
FAST/SLOW bracketing of the initialization loop (lines 10, 90) speeds up the POKE-fill stage while restoring display output for interactive use.
- The reuse of variable
A for both pattern generation (lines 15–85) and horizontal offset tracking (lines 115–157) requires careful reading — after initialization, A is reset to 0 at line 115 for its new role.
Content
Source Code
1 REM \21\21\40\3E\18\77\11\00\60\21\00\50\C3\93\40\35\E1\01\20\00\ED\B0\3E\76\12\1C\06\00\0E\20\09\E5\21\21\40\3E\00\BE\C2\91\40\E1\01\18\03\2A\0C\40\2C\E5\D1\21\00\60\ED\B0\C9\1B\1B\1B
10 FAST
15 LET N=20480
20 LET A=8
25 FOR Z=1 TO 2
30 FOR X=1 TO 24
35 FOR Y=1 TO 64
38 IF Y>32 THEN LET A=10-A
40 POKE N,A
45 LET N=N+1
48 IF Y>32 THEN LET A=10-A
50 NEXT Y
55 NEXT X
65 LET A=3
85 NEXT Z
90 SLOW
95 LET N=20480
100 POKE 16524,256*(N/256-INT (N/256))
105 POKE 16525,INT N/256
110 RAND USR 16514
115 LET A=0
120 LET K$=INKEY$
125 IF CODE K$<33 OR CODE K$>36 THEN GOTO 120
130 IF K$="5" THEN LET K=-1
135 IF K$="8" THEN LET K=1
140 IF K$="6" THEN LET K=64
145 IF K$="7" THEN LET K=-64
149 IF (K=1 OR K=-1) AND (K+A<0 OR K+A>32) THEN GOTO 120
150 IF N+K<20480 OR N+K>22015 THEN GOTO 120
155 LET N=N+K
157 IF K=1 OR K=-1 THEN LET A=A+K
160 GOSUB 200
165 GOTO 120
200 POKE 16524,256*(N/256-INT (N/256))
210 POKE 16525,INT N/256
220 RAND USR 16514
230 RETURN
300 FOR N=16514 TO 16570
310 LPRINT N;TAB 10;PEEK N;TAB 15;CHR$ PEEK N
320 NEXT N
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
C\E5\D1
Skip to content
Scroller
Scroller is a ZX81/TS1000 program that creates a checkerboard pattern in display memory and then uses embedded machine code to scroll the screen in four directions under keyboard control. The machine code routine is stored in the REM statement at line 1, beginning at address 16514, and is called via RAND USR 16514. The BASIC initialization loop at lines 15–85 fills the 24×64 video RAM region starting at address 20480 with alternating byte values (8 and 2) to produce a two-tone checkerboard. Keys 5, 6, 7, and 8 (the ZX81’s cursor keys) control horizontal and vertical scrolling, with boundary checks at lines 149–150 preventing the scroll position from going outside the valid display memory range. Line 300–320 provides a diagnostic routine that LPRINTs the contents and ASCII equivalents of the machine code bytes stored in the REM statement.
Program Analysis
Program Structure
The program divides into four functional sections:
- Lines 1: A
REM statement acting as machine code storage, holding the scroll routine at addresses 16514 onward.
- Lines 10–85: BASIC initialization — fills display RAM (starting at 20480) with a checkerboard pattern using alternating byte values.
- Lines 90–230: Main interactive loop — reads cursor keys (5/6/7/8), validates boundaries, updates the scroll pointer, and calls the machine code display routine via
RAND USR 16514.
- Lines 300–320: A standalone diagnostic utility that
LPRINTs the address, byte value, and ASCII character of each byte in the machine code REM block.
Machine Code in REM Statement
The REM at line 1 stores 57 bytes of Z80 machine code beginning at address 16514 (the first byte after the line’s length bytes and REM token). The routine is invoked with RAND USR 16514, which transfers execution to that address without disturbing the BASIC stack in a disruptive way. The low and high bytes of the target display address are pre-loaded into memory locations 16524 and 16525 (two bytes within the REM data itself, acting as a self-modifying code parameter), set by POKE statements at lines 100–105 and 200–210.
The decoded Z80 sequence begins:
21 21 40 — LD HL, $4021 (points into the REM data for the address parameter)
3E 18 — LD A, $18
77 — LD (HL), A
11 00 60 — LD DE, $6000 (destination buffer)
21 00 50 — LD HL, $5000
C3 93 40 — JP $4093 (jump further into the routine)
The routine copies a region of display memory to a buffer, performs the scroll, and returns. The use of ED B0 (LDIR) is visible in the byte sequence, confirming block memory copy operations for efficiency.
Checkerboard Initialization
Lines 15–85 fill 24 rows × 64 columns (1536 bytes) of video RAM with alternating values. Variable A starts at 8. For each row of 64 columns, when Y>32 the value toggles via A=10-A (swapping between 8 and 2, since 10−8=2 and 10−2=8). The toggle is applied before the POKE at line 38 and then reversed after at line 48, so only the second half of each row uses the alternate value. The outer loop FOR Z=1 TO 2 at line 25 resets A to 3 at line 65 on the second pass, which shifts the phase of the pattern to create the checkerboard effect across rows.
Scroll Pointer and Boundary Checking
The current top-left display address is held in N. Variable A (reused from initialization) tracks the horizontal byte offset within a row (0–32). Variable K holds the scroll delta: ±1 for left/right, ±64 for up/down.
Two boundary guards are applied before any scroll:
- Line 149: For horizontal scrolls (
K=±1), checks that A+K remains within 0–32, preventing wrapping across row boundaries.
- Line 150: Checks that the new address
N+K stays within 20480–22015 (the valid 1.5 KB display RAM window), preventing scrolling outside the initialized region.
Address Passing to Machine Code
Because the machine code routine reads the scroll target address from fixed locations within its own code (at offsets corresponding to addresses 16524–16525), the BASIC layer must write the low byte (256*(N/256-INT(N/256))) and high byte (INT N/256) to those locations before each call. This is a self-modifying code pattern — the POKEs at lines 100/105 and 200/210 patch operand bytes directly inside the REM-stored machine code before invoking it.
Key Mapping
Key Character Code K value Direction 5 33 −1 Left 8 36 +1 Right 6 34 +64 Down 7 35 −64 Up
Line 125 filters for character codes 33–36 (i.e., “5”, “6”, “7”, “8”), rejecting all other keypresses and looping back to INKEY$ polling. This is a compact range-check idiom avoiding four separate IF tests.
Diagnostic Routine
Lines 300–320 are not called from the main program flow and serve as a developer tool. The loop iterates over addresses 16514–16570, printing each address, its raw byte value via PEEK, and the corresponding CHR$ representation to the printer. This allows the programmer to verify the machine code bytes stored in the REM statement are intact after loading.
Notable Techniques
REM as machine code storage: the standard ZX81 technique for embedding Z80 routines without a separate loader or character RAM area.
- Self-modifying machine code: address parameters are patched via
POKE before each RAND USR call.
FAST/SLOW bracketing of the initialization loop (lines 10, 90) speeds up the POKE-fill stage while restoring display output for interactive use.
- The reuse of variable
A for both pattern generation (lines 15–85) and horizontal offset tracking (lines 115–157) requires careful reading — after initialization, A is reset to 0 at line 115 for its new role.
Content
Source Code
1 REM \21\21\40\3E\18\77\11\00\60\21\00\50\C3\93\40\35\E1\01\20\00\ED\B0\3E\76\12\1C\06\00\0E\20\09\E5\21\21\40\3E\00\BE\C2\91\40\E1\01\18\03\2A\0C\40\2C\E5\D1\21\00\60\ED\B0\C9\1B\1B\1B
10 FAST
15 LET N=20480
20 LET A=8
25 FOR Z=1 TO 2
30 FOR X=1 TO 24
35 FOR Y=1 TO 64
38 IF Y>32 THEN LET A=10-A
40 POKE N,A
45 LET N=N+1
48 IF Y>32 THEN LET A=10-A
50 NEXT Y
55 NEXT X
65 LET A=3
85 NEXT Z
90 SLOW
95 LET N=20480
100 POKE 16524,256*(N/256-INT (N/256))
105 POKE 16525,INT N/256
110 RAND USR 16514
115 LET A=0
120 LET K$=INKEY$
125 IF CODE K$<33 OR CODE K$>36 THEN GOTO 120
130 IF K$="5" THEN LET K=-1
135 IF K$="8" THEN LET K=1
140 IF K$="6" THEN LET K=64
145 IF K$="7" THEN LET K=-64
149 IF (K=1 OR K=-1) AND (K+A<0 OR K+A>32) THEN GOTO 120
150 IF N+K<20480 OR N+K>22015 THEN GOTO 120
155 LET N=N+K
157 IF K=1 OR K=-1 THEN LET A=A+K
160 GOSUB 200
165 GOTO 120
200 POKE 16524,256*(N/256-INT (N/256))
210 POKE 16525,INT N/256
220 RAND USR 16514
230 RETURN
300 FOR N=16514 TO 16570
310 LPRINT N;TAB 10;PEEK N;TAB 15;CHR$ PEEK N
320 NEXT N
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
\ED\B0\C9 itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56711 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.7 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.5"B itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56711 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.7 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.5"B itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56711 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.7 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.5"B
10 FAST
15 LET N=20480
20 LET A=8
25 FOR Z=1 TO 2
30 FOR X=1 TO 24
35 FOR Y=1 TO 64
38 IF Y>32 THEN LET A=10-A
40 POKE N,A
45 LET N=N+1
48 IF Y>32 THEN LET A=10-A
50 NEXT Y
55 NEXT X
65 LET A=3
85 NEXT Z
90 SLOW
95 LET N=20480
100 POKE 16524,256*(N/256-INT (N/256))
105 POKE 16525,INT N/256
110 RAND USR 16514
115 LET A=0
120 LET K$=INKEY$
125 IF CODE K$<33 OR CODE K$>36 THEN GOTO 120
130 IF K$="5" THEN LET K=-1
135 IF K$="8" THEN LET K=1
140 IF K$="6" THEN LET K=64
145 IF K$="7" THEN LET K=-64
149 IF (K=1 OR K=-1) AND (K+A<0 OR K+A>32) THEN GOTO 120
150 IF N+K<20480 OR N+K>22015 THEN GOTO 120
155 LET N=N+K
157 IF K=1 OR K=-1 THEN LET A=A+K
160 GOSUB 200
165 GOTO 120
200 POKE 16524,256*(N/256-INT (N/256))
210 POKE 16525,INT N/256
220 RAND USR 16514
230 RETURN
300 FOR N=16514 TO 16570
310 LPRINT N;TAB 10;PEEK N;TAB 15;CHR$ PEEK N
320 NEXT N
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
