Screen Scrolling Routine

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

This program implements a character-movement or screen-scrolling system driven entirely by machine code routines embedded in the REM statement at line 1. The BASIC shell reads a keypress via INKEY$ and dispatches to one of four machine code entry points (USR 16514, 16538, 16567, 16588) depending on the key pressed, covering eight directions: J, M, I, K for cardinal directions and U, O, ., N for diagonals (combining two cardinal calls). The machine code, stored beginning at address 16514 (0x4082, just inside the REM statement data), performs direct memory operations including LDIR and LDDR block moves, consistent with scrolling a screen region or shifting a sprite/character buffer. The SAVE at line 70 uses an inverse-video character in the filename as an auto-run marker.


Program Analysis

Program Structure

The program has three logical layers:

  1. Machine code store — Line 1 is a REM statement whose body contains raw Z80 opcodes. Because the ZX Spectrum/TS2068 stores REM data verbatim in RAM, the bytes are directly executable starting at the address of the first byte after the REM token.
  2. Input loop — Lines 20–60 form a tight polling loop: INKEY$ is sampled at line 20, then a cascade of IF/GOTO chains dispatches to the appropriate machine code entry point(s).
  3. Housekeeping — Lines 70–80 provide a SAVE and a GOTO 5 (which jumps to LIST 35) for re-entry/display purposes.

Machine Code Entry Points

Line 1 begins at address 16384 (0x4000). The REM token occupies one byte and the two-byte length field two more, placing the first opcode at 0x4003 (16387). However, the BASIC calls target four distinct addresses:

USR AddressHexKey(s)Role (inferred)
165140x4082I, U, OScroll/move up
165380x409AM, ., NScroll/move down
165670x40B7K, ., NScroll/move right
165880x40CCJ, U, NScroll/move left

The REM data is 59 bytes long (the trailing bytes itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57148 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.5 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"D itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57148 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.5 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"E itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57148 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.5 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"F itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57148 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.5 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"C are likely padding or lookup data). The entry points are therefore spread across the REM body and each routine ends with a C9 (RET) opcode.

Z80 Routine Analysis

Disassembling the REM bytes reveals four subroutines that use the Z80 block-move instructions LDIR (ED B0) and LDDR (ED B8) to shift screen memory. Common patterns observed:

  • 2A 0C 40LD HL,(0x400C): loads a pointer from within the REM area itself (self-referential data).
  • 11 21 00LD DE,0x0021 (33 decimal): one character row width on a 32-column display plus one, used as an offset for vertical scrolling.
  • ED B0 / ED B8LDIR/LDDR: bulk copy forward/backward for up/down scroll directions.
  • 01 B5 02LD BC,0x02B5 (693): the byte count, matching the number of bytes in roughly 21.6 character rows — consistent with scrolling most of the display.
  • 36 00 inside a DJNZ loop — LD (HL),0: clears the vacated edge row/column after a scroll.
  • 06 20LD B,0x20 (32): loop counter for clearing 32 columns.
  • 06 16LD B,0x16 (22): loop counter for clearing 22 rows.

Key Mapping and Diagonal Movement

The eight keys map naturally to a numeric-keypad layout:

KeyDirectionRoutines called
IUpUSR 16514
KRightUSR 16567
MDownUSR 16538
JLeftUSR 16588
UUp-LeftUSR 16514 + USR 16588
OUp-RightUSR 16514 + USR 16567
.Down-RightUSR 16538 + USR 16567
NDown-LeftUSR 16538 + USR 16588

Diagonal movement is achieved by sequentially calling two cardinal-direction routines in BASIC rather than implementing combined diagonals in machine code, keeping the MC routines simple and orthogonal.

Notable Techniques

  • REM-as-code store: embedding machine code in a REM line is a standard technique that keeps the code in a known, fixed address and prevents the BASIC editor from interpreting the bytes.
  • Self-referential data pointer: LD HL,(0x400C) reads a word from within the REM statement itself, allowing the routine to find its own working data without hardcoding a separate address.
  • LDIR/LDDR for scrolling: using the Z80 block-copy instructions is the fastest pure-Z80 approach to scrolling a rectangular region of screen memory.
  • DJNZ clear loop: after a scroll, a DJNZ loop with LD (HL),0 efficiently blanks the newly exposed row or column.
  • Line 5 LIST 35: GOTO 5 at line 80 causes the program listing to scroll to line 35, effectively hiding the machine code REM from casual view on restart.
  • INKEY$ polling without PAUSE: line 20 samples the keyboard every BASIC iteration with no delay, giving the fastest possible response at the cost of no key-repeat debounce.

Potential Anomalies

  • Line 57 is referenced by GOTO 57 (line 54) but does not exist. After the cascade of diagonal-key checks, control falls through to GOTO 20 at line 60 — the missing line 57 simply causes BASIC to continue to the next higher line, which is line 60. This is intentional and well-understood behaviour.
  • The trailing bytes itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57148 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.5 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"D itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57148 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.5 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"E itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57148 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.5 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"F itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57148 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.5 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"C at the end of the REM (control codes 28–37) are not reachable as code; they appear to be a lookup table or padding used as data by the routines.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10051 – 10121.

Related Products

Related Articles

Related Content

Image Gallery

Screen Scrolling Routine

Source Code

   1 REM 



Screen Scrolling Routine

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

This program implements a character-movement or screen-scrolling system driven entirely by machine code routines embedded in the REM statement at line 1. The BASIC shell reads a keypress via INKEY$ and dispatches to one of four machine code entry points (USR 16514, 16538, 16567, 16588) depending on the key pressed, covering eight directions: J, M, I, K for cardinal directions and U, O, ., N for diagonals (combining two cardinal calls). The machine code, stored beginning at address 16514 (0x4082, just inside the REM statement data), performs direct memory operations including LDIR and LDDR block moves, consistent with scrolling a screen region or shifting a sprite/character buffer. The SAVE at line 70 uses an inverse-video character in the filename as an auto-run marker.


Program Analysis

Program Structure

The program has three logical layers:

  1. Machine code store — Line 1 is a REM statement whose body contains raw Z80 opcodes. Because the ZX Spectrum/TS2068 stores REM data verbatim in RAM, the bytes are directly executable starting at the address of the first byte after the REM token.
  2. Input loop — Lines 20–60 form a tight polling loop: INKEY$ is sampled at line 20, then a cascade of IF/GOTO chains dispatches to the appropriate machine code entry point(s).
  3. Housekeeping — Lines 70–80 provide a SAVE and a GOTO 5 (which jumps to LIST 35) for re-entry/display purposes.

Machine Code Entry Points

Line 1 begins at address 16384 (0x4000). The REM token occupies one byte and the two-byte length field two more, placing the first opcode at 0x4003 (16387). However, the BASIC calls target four distinct addresses:

USR AddressHexKey(s)Role (inferred)
165140x4082I, U, OScroll/move up
165380x409AM, ., NScroll/move down
165670x40B7K, ., NScroll/move right
165880x40CCJ, U, NScroll/move left

The REM data is 59 bytes long (the trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C are likely padding or lookup data). The entry points are therefore spread across the REM body and each routine ends with a C9 (RET) opcode.

Z80 Routine Analysis

Disassembling the REM bytes reveals four subroutines that use the Z80 block-move instructions LDIR (ED B0) and LDDR (ED B8) to shift screen memory. Common patterns observed:

  • 2A 0C 40LD HL,(0x400C): loads a pointer from within the REM area itself (self-referential data).
  • 11 21 00LD DE,0x0021 (33 decimal): one character row width on a 32-column display plus one, used as an offset for vertical scrolling.
  • ED B0 / ED B8LDIR/LDDR: bulk copy forward/backward for up/down scroll directions.
  • 01 B5 02LD BC,0x02B5 (693): the byte count, matching the number of bytes in roughly 21.6 character rows — consistent with scrolling most of the display.
  • 36 00 inside a DJNZ loop — LD (HL),0: clears the vacated edge row/column after a scroll.
  • 06 20LD B,0x20 (32): loop counter for clearing 32 columns.
  • 06 16LD B,0x16 (22): loop counter for clearing 22 rows.

Key Mapping and Diagonal Movement

The eight keys map naturally to a numeric-keypad layout:

KeyDirectionRoutines called
IUpUSR 16514
KRightUSR 16567
MDownUSR 16538
JLeftUSR 16588
UUp-LeftUSR 16514 + USR 16588
OUp-RightUSR 16514 + USR 16567
.Down-RightUSR 16538 + USR 16567
NDown-LeftUSR 16538 + USR 16588

Diagonal movement is achieved by sequentially calling two cardinal-direction routines in BASIC rather than implementing combined diagonals in machine code, keeping the MC routines simple and orthogonal.

Notable Techniques

  • REM-as-code store: embedding machine code in a REM line is a standard technique that keeps the code in a known, fixed address and prevents the BASIC editor from interpreting the bytes.
  • Self-referential data pointer: LD HL,(0x400C) reads a word from within the REM statement itself, allowing the routine to find its own working data without hardcoding a separate address.
  • LDIR/LDDR for scrolling: using the Z80 block-copy instructions is the fastest pure-Z80 approach to scrolling a rectangular region of screen memory.
  • DJNZ clear loop: after a scroll, a DJNZ loop with LD (HL),0 efficiently blanks the newly exposed row or column.
  • Line 5 LIST 35: GOTO 5 at line 80 causes the program listing to scroll to line 35, effectively hiding the machine code REM from casual view on restart.
  • INKEY$ polling without PAUSE: line 20 samples the keyboard every BASIC iteration with no delay, giving the fastest possible response at the cost of no key-repeat debounce.

Potential Anomalies

  • Line 57 is referenced by GOTO 57 (line 54) but does not exist. After the cascade of diagonal-key checks, control falls through to GOTO 20 at line 60 — the missing line 57 simply causes BASIC to continue to the next higher line, which is line 60. This is intentional and well-understood behaviour.
  • The trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C at the end of the REM (control codes 28–37) are not reachable as code; they appear to be a lookup table or padding used as data by the routines.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10051 – 10121.

Related Products

Related Articles

Related Content

Image Gallery

Screen Scrolling Routine

Source Code

   1 REM \2A\0C\40\23\E5\11\21\00\19\D1\01\B5\02\ED\B0\EB\06\20\36\00\23\10\FB\C9\2A\10\40\11\43\00\ED\52\E5\11\21\00\ED\52\D1\01\B5\02\ED\B8\EB\06\20\2B\36\00\10\FB\C9\2A\0C\40\06\16\C5\06\20\3E\00\23\4F\7E\71\10\FA\23\C1\10\F1\C9\2A\10\40\11\43\00\ED\52\06\16\C5\06\20\3E\00\2B\4F\7E\71\10\FA\2B\C1\10\F1\C9\1D\1E\1F\20\21\22\23\24\25\1C
   5 LIST 35
  20 LET D$=INKEY$
  25 IF D$="J" THEN RAND USR 16588
  30 IF D$="M" THEN RAND USR 16538
  35 IF D$="I" THEN RAND USR 16514
  40 IF D$="K" THEN RAND USR 16567
  41 IF D$="U" THEN GOTO 43
  42 GOTO 45
  43 RAND USR 16514
  44 RAND USR 16588
  45 IF D$="O" THEN GOTO 47
  46 GOTO 49
  47 RAND USR 16514
  48 RAND USR 16567
  49 IF D$="." THEN GOTO 51
  50 GOTO 53
  51 RAND USR 16538
  52 RAND USR 16567
  53 IF D$="N" THEN GOTO 55
  54 GOTO 57
  55 RAND USR 16538
  56 RAND USR 16588
  60 GOTO 20
  70 SAVE "1009%7"
  80 GOTO 5

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

People

No people associated with this content.

Scroll to Top
A

Screen Scrolling Routine

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

This program implements a character-movement or screen-scrolling system driven entirely by machine code routines embedded in the REM statement at line 1. The BASIC shell reads a keypress via INKEY$ and dispatches to one of four machine code entry points (USR 16514, 16538, 16567, 16588) depending on the key pressed, covering eight directions: J, M, I, K for cardinal directions and U, O, ., N for diagonals (combining two cardinal calls). The machine code, stored beginning at address 16514 (0x4082, just inside the REM statement data), performs direct memory operations including LDIR and LDDR block moves, consistent with scrolling a screen region or shifting a sprite/character buffer. The SAVE at line 70 uses an inverse-video character in the filename as an auto-run marker.


Program Analysis

Program Structure

The program has three logical layers:

  1. Machine code store — Line 1 is a REM statement whose body contains raw Z80 opcodes. Because the ZX Spectrum/TS2068 stores REM data verbatim in RAM, the bytes are directly executable starting at the address of the first byte after the REM token.
  2. Input loop — Lines 20–60 form a tight polling loop: INKEY$ is sampled at line 20, then a cascade of IF/GOTO chains dispatches to the appropriate machine code entry point(s).
  3. Housekeeping — Lines 70–80 provide a SAVE and a GOTO 5 (which jumps to LIST 35) for re-entry/display purposes.

Machine Code Entry Points

Line 1 begins at address 16384 (0x4000). The REM token occupies one byte and the two-byte length field two more, placing the first opcode at 0x4003 (16387). However, the BASIC calls target four distinct addresses:

USR AddressHexKey(s)Role (inferred)
165140x4082I, U, OScroll/move up
165380x409AM, ., NScroll/move down
165670x40B7K, ., NScroll/move right
165880x40CCJ, U, NScroll/move left

The REM data is 59 bytes long (the trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C are likely padding or lookup data). The entry points are therefore spread across the REM body and each routine ends with a C9 (RET) opcode.

Z80 Routine Analysis

Disassembling the REM bytes reveals four subroutines that use the Z80 block-move instructions LDIR (ED B0) and LDDR (ED B8) to shift screen memory. Common patterns observed:

  • 2A 0C 40LD HL,(0x400C): loads a pointer from within the REM area itself (self-referential data).
  • 11 21 00LD DE,0x0021 (33 decimal): one character row width on a 32-column display plus one, used as an offset for vertical scrolling.
  • ED B0 / ED B8LDIR/LDDR: bulk copy forward/backward for up/down scroll directions.
  • 01 B5 02LD BC,0x02B5 (693): the byte count, matching the number of bytes in roughly 21.6 character rows — consistent with scrolling most of the display.
  • 36 00 inside a DJNZ loop — LD (HL),0: clears the vacated edge row/column after a scroll.
  • 06 20LD B,0x20 (32): loop counter for clearing 32 columns.
  • 06 16LD B,0x16 (22): loop counter for clearing 22 rows.

Key Mapping and Diagonal Movement

The eight keys map naturally to a numeric-keypad layout:

KeyDirectionRoutines called
IUpUSR 16514
KRightUSR 16567
MDownUSR 16538
JLeftUSR 16588
UUp-LeftUSR 16514 + USR 16588
OUp-RightUSR 16514 + USR 16567
.Down-RightUSR 16538 + USR 16567
NDown-LeftUSR 16538 + USR 16588

Diagonal movement is achieved by sequentially calling two cardinal-direction routines in BASIC rather than implementing combined diagonals in machine code, keeping the MC routines simple and orthogonal.

Notable Techniques

  • REM-as-code store: embedding machine code in a REM line is a standard technique that keeps the code in a known, fixed address and prevents the BASIC editor from interpreting the bytes.
  • Self-referential data pointer: LD HL,(0x400C) reads a word from within the REM statement itself, allowing the routine to find its own working data without hardcoding a separate address.
  • LDIR/LDDR for scrolling: using the Z80 block-copy instructions is the fastest pure-Z80 approach to scrolling a rectangular region of screen memory.
  • DJNZ clear loop: after a scroll, a DJNZ loop with LD (HL),0 efficiently blanks the newly exposed row or column.
  • Line 5 LIST 35: GOTO 5 at line 80 causes the program listing to scroll to line 35, effectively hiding the machine code REM from casual view on restart.
  • INKEY$ polling without PAUSE: line 20 samples the keyboard every BASIC iteration with no delay, giving the fastest possible response at the cost of no key-repeat debounce.

Potential Anomalies

  • Line 57 is referenced by GOTO 57 (line 54) but does not exist. After the cascade of diagonal-key checks, control falls through to GOTO 20 at line 60 — the missing line 57 simply causes BASIC to continue to the next higher line, which is line 60. This is intentional and well-understood behaviour.
  • The trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C at the end of the REM (control codes 28–37) are not reachable as code; they appear to be a lookup table or padding used as data by the routines.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10051 – 10121.

Related Products

Related Articles

Related Content

Image Gallery

Screen Scrolling Routine

Source Code

   1 REM \2A\0C\40\23\E5\11\21\00\19\D1\01\B5\02\ED\B0\EB\06\20\36\00\23\10\FB\C9\2A\10\40\11\43\00\ED\52\E5\11\21\00\ED\52\D1\01\B5\02\ED\B8\EB\06\20\2B\36\00\10\FB\C9\2A\0C\40\06\16\C5\06\20\3E\00\23\4F\7E\71\10\FA\23\C1\10\F1\C9\2A\10\40\11\43\00\ED\52\06\16\C5\06\20\3E\00\2B\4F\7E\71\10\FA\2B\C1\10\F1\C9\1D\1E\1F\20\21\22\23\24\25\1C
   5 LIST 35
  20 LET D$=INKEY$
  25 IF D$="J" THEN RAND USR 16588
  30 IF D$="M" THEN RAND USR 16538
  35 IF D$="I" THEN RAND USR 16514
  40 IF D$="K" THEN RAND USR 16567
  41 IF D$="U" THEN GOTO 43
  42 GOTO 45
  43 RAND USR 16514
  44 RAND USR 16588
  45 IF D$="O" THEN GOTO 47
  46 GOTO 49
  47 RAND USR 16514
  48 RAND USR 16567
  49 IF D$="." THEN GOTO 51
  50 GOTO 53
  51 RAND USR 16538
  52 RAND USR 16567
  53 IF D$="N" THEN GOTO 55
  54 GOTO 57
  55 RAND USR 16538
  56 RAND USR 16588
  60 GOTO 20
  70 SAVE "1009%7"
  80 GOTO 5

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

People

No people associated with this content.

Scroll to Top
C\E5

Screen Scrolling Routine

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

This program implements a character-movement or screen-scrolling system driven entirely by machine code routines embedded in the REM statement at line 1. The BASIC shell reads a keypress via INKEY$ and dispatches to one of four machine code entry points (USR 16514, 16538, 16567, 16588) depending on the key pressed, covering eight directions: J, M, I, K for cardinal directions and U, O, ., N for diagonals (combining two cardinal calls). The machine code, stored beginning at address 16514 (0x4082, just inside the REM statement data), performs direct memory operations including LDIR and LDDR block moves, consistent with scrolling a screen region or shifting a sprite/character buffer. The SAVE at line 70 uses an inverse-video character in the filename as an auto-run marker.


Program Analysis

Program Structure

The program has three logical layers:

  1. Machine code store — Line 1 is a REM statement whose body contains raw Z80 opcodes. Because the ZX Spectrum/TS2068 stores REM data verbatim in RAM, the bytes are directly executable starting at the address of the first byte after the REM token.
  2. Input loop — Lines 20–60 form a tight polling loop: INKEY$ is sampled at line 20, then a cascade of IF/GOTO chains dispatches to the appropriate machine code entry point(s).
  3. Housekeeping — Lines 70–80 provide a SAVE and a GOTO 5 (which jumps to LIST 35) for re-entry/display purposes.

Machine Code Entry Points

Line 1 begins at address 16384 (0x4000). The REM token occupies one byte and the two-byte length field two more, placing the first opcode at 0x4003 (16387). However, the BASIC calls target four distinct addresses:

USR AddressHexKey(s)Role (inferred)
165140x4082I, U, OScroll/move up
165380x409AM, ., NScroll/move down
165670x40B7K, ., NScroll/move right
165880x40CCJ, U, NScroll/move left

The REM data is 59 bytes long (the trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C are likely padding or lookup data). The entry points are therefore spread across the REM body and each routine ends with a C9 (RET) opcode.

Z80 Routine Analysis

Disassembling the REM bytes reveals four subroutines that use the Z80 block-move instructions LDIR (ED B0) and LDDR (ED B8) to shift screen memory. Common patterns observed:

  • 2A 0C 40LD HL,(0x400C): loads a pointer from within the REM area itself (self-referential data).
  • 11 21 00LD DE,0x0021 (33 decimal): one character row width on a 32-column display plus one, used as an offset for vertical scrolling.
  • ED B0 / ED B8LDIR/LDDR: bulk copy forward/backward for up/down scroll directions.
  • 01 B5 02LD BC,0x02B5 (693): the byte count, matching the number of bytes in roughly 21.6 character rows — consistent with scrolling most of the display.
  • 36 00 inside a DJNZ loop — LD (HL),0: clears the vacated edge row/column after a scroll.
  • 06 20LD B,0x20 (32): loop counter for clearing 32 columns.
  • 06 16LD B,0x16 (22): loop counter for clearing 22 rows.

Key Mapping and Diagonal Movement

The eight keys map naturally to a numeric-keypad layout:

KeyDirectionRoutines called
IUpUSR 16514
KRightUSR 16567
MDownUSR 16538
JLeftUSR 16588
UUp-LeftUSR 16514 + USR 16588
OUp-RightUSR 16514 + USR 16567
.Down-RightUSR 16538 + USR 16567
NDown-LeftUSR 16538 + USR 16588

Diagonal movement is achieved by sequentially calling two cardinal-direction routines in BASIC rather than implementing combined diagonals in machine code, keeping the MC routines simple and orthogonal.

Notable Techniques

  • REM-as-code store: embedding machine code in a REM line is a standard technique that keeps the code in a known, fixed address and prevents the BASIC editor from interpreting the bytes.
  • Self-referential data pointer: LD HL,(0x400C) reads a word from within the REM statement itself, allowing the routine to find its own working data without hardcoding a separate address.
  • LDIR/LDDR for scrolling: using the Z80 block-copy instructions is the fastest pure-Z80 approach to scrolling a rectangular region of screen memory.
  • DJNZ clear loop: after a scroll, a DJNZ loop with LD (HL),0 efficiently blanks the newly exposed row or column.
  • Line 5 LIST 35: GOTO 5 at line 80 causes the program listing to scroll to line 35, effectively hiding the machine code REM from casual view on restart.
  • INKEY$ polling without PAUSE: line 20 samples the keyboard every BASIC iteration with no delay, giving the fastest possible response at the cost of no key-repeat debounce.

Potential Anomalies

  • Line 57 is referenced by GOTO 57 (line 54) but does not exist. After the cascade of diagonal-key checks, control falls through to GOTO 20 at line 60 — the missing line 57 simply causes BASIC to continue to the next higher line, which is line 60. This is intentional and well-understood behaviour.
  • The trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C at the end of the REM (control codes 28–37) are not reachable as code; they appear to be a lookup table or padding used as data by the routines.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10051 – 10121.

Related Products

Related Articles

Related Content

Image Gallery

Screen Scrolling Routine

Source Code

   1 REM \2A\0C\40\23\E5\11\21\00\19\D1\01\B5\02\ED\B0\EB\06\20\36\00\23\10\FB\C9\2A\10\40\11\43\00\ED\52\E5\11\21\00\ED\52\D1\01\B5\02\ED\B8\EB\06\20\2B\36\00\10\FB\C9\2A\0C\40\06\16\C5\06\20\3E\00\23\4F\7E\71\10\FA\23\C1\10\F1\C9\2A\10\40\11\43\00\ED\52\06\16\C5\06\20\3E\00\2B\4F\7E\71\10\FA\2B\C1\10\F1\C9\1D\1E\1F\20\21\22\23\24\25\1C
   5 LIST 35
  20 LET D$=INKEY$
  25 IF D$="J" THEN RAND USR 16588
  30 IF D$="M" THEN RAND USR 16538
  35 IF D$="I" THEN RAND USR 16514
  40 IF D$="K" THEN RAND USR 16567
  41 IF D$="U" THEN GOTO 43
  42 GOTO 45
  43 RAND USR 16514
  44 RAND USR 16588
  45 IF D$="O" THEN GOTO 47
  46 GOTO 49
  47 RAND USR 16514
  48 RAND USR 16567
  49 IF D$="." THEN GOTO 51
  50 GOTO 53
  51 RAND USR 16538
  52 RAND USR 16567
  53 IF D$="N" THEN GOTO 55
  54 GOTO 57
  55 RAND USR 16538
  56 RAND USR 16588
  60 GOTO 20
  70 SAVE "1009%7"
  80 GOTO 5

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

People

No people associated with this content.

Scroll to Top
\D1 itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57148 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.5 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

Screen Scrolling Routine

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

This program implements a character-movement or screen-scrolling system driven entirely by machine code routines embedded in the REM statement at line 1. The BASIC shell reads a keypress via INKEY$ and dispatches to one of four machine code entry points (USR 16514, 16538, 16567, 16588) depending on the key pressed, covering eight directions: J, M, I, K for cardinal directions and U, O, ., N for diagonals (combining two cardinal calls). The machine code, stored beginning at address 16514 (0x4082, just inside the REM statement data), performs direct memory operations including LDIR and LDDR block moves, consistent with scrolling a screen region or shifting a sprite/character buffer. The SAVE at line 70 uses an inverse-video character in the filename as an auto-run marker.


Program Analysis

Program Structure

The program has three logical layers:

  1. Machine code store — Line 1 is a REM statement whose body contains raw Z80 opcodes. Because the ZX Spectrum/TS2068 stores REM data verbatim in RAM, the bytes are directly executable starting at the address of the first byte after the REM token.
  2. Input loop — Lines 20–60 form a tight polling loop: INKEY$ is sampled at line 20, then a cascade of IF/GOTO chains dispatches to the appropriate machine code entry point(s).
  3. Housekeeping — Lines 70–80 provide a SAVE and a GOTO 5 (which jumps to LIST 35) for re-entry/display purposes.

Machine Code Entry Points

Line 1 begins at address 16384 (0x4000). The REM token occupies one byte and the two-byte length field two more, placing the first opcode at 0x4003 (16387). However, the BASIC calls target four distinct addresses:

USR AddressHexKey(s)Role (inferred)
165140x4082I, U, OScroll/move up
165380x409AM, ., NScroll/move down
165670x40B7K, ., NScroll/move right
165880x40CCJ, U, NScroll/move left

The REM data is 59 bytes long (the trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C are likely padding or lookup data). The entry points are therefore spread across the REM body and each routine ends with a C9 (RET) opcode.

Z80 Routine Analysis

Disassembling the REM bytes reveals four subroutines that use the Z80 block-move instructions LDIR (ED B0) and LDDR (ED B8) to shift screen memory. Common patterns observed:

  • 2A 0C 40LD HL,(0x400C): loads a pointer from within the REM area itself (self-referential data).
  • 11 21 00LD DE,0x0021 (33 decimal): one character row width on a 32-column display plus one, used as an offset for vertical scrolling.
  • ED B0 / ED B8LDIR/LDDR: bulk copy forward/backward for up/down scroll directions.
  • 01 B5 02LD BC,0x02B5 (693): the byte count, matching the number of bytes in roughly 21.6 character rows — consistent with scrolling most of the display.
  • 36 00 inside a DJNZ loop — LD (HL),0: clears the vacated edge row/column after a scroll.
  • 06 20LD B,0x20 (32): loop counter for clearing 32 columns.
  • 06 16LD B,0x16 (22): loop counter for clearing 22 rows.

Key Mapping and Diagonal Movement

The eight keys map naturally to a numeric-keypad layout:

KeyDirectionRoutines called
IUpUSR 16514
KRightUSR 16567
MDownUSR 16538
JLeftUSR 16588
UUp-LeftUSR 16514 + USR 16588
OUp-RightUSR 16514 + USR 16567
.Down-RightUSR 16538 + USR 16567
NDown-LeftUSR 16538 + USR 16588

Diagonal movement is achieved by sequentially calling two cardinal-direction routines in BASIC rather than implementing combined diagonals in machine code, keeping the MC routines simple and orthogonal.

Notable Techniques

  • REM-as-code store: embedding machine code in a REM line is a standard technique that keeps the code in a known, fixed address and prevents the BASIC editor from interpreting the bytes.
  • Self-referential data pointer: LD HL,(0x400C) reads a word from within the REM statement itself, allowing the routine to find its own working data without hardcoding a separate address.
  • LDIR/LDDR for scrolling: using the Z80 block-copy instructions is the fastest pure-Z80 approach to scrolling a rectangular region of screen memory.
  • DJNZ clear loop: after a scroll, a DJNZ loop with LD (HL),0 efficiently blanks the newly exposed row or column.
  • Line 5 LIST 35: GOTO 5 at line 80 causes the program listing to scroll to line 35, effectively hiding the machine code REM from casual view on restart.
  • INKEY$ polling without PAUSE: line 20 samples the keyboard every BASIC iteration with no delay, giving the fastest possible response at the cost of no key-repeat debounce.

Potential Anomalies

  • Line 57 is referenced by GOTO 57 (line 54) but does not exist. After the cascade of diagonal-key checks, control falls through to GOTO 20 at line 60 — the missing line 57 simply causes BASIC to continue to the next higher line, which is line 60. This is intentional and well-understood behaviour.
  • The trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C at the end of the REM (control codes 28–37) are not reachable as code; they appear to be a lookup table or padding used as data by the routines.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10051 – 10121.

Related Products

Related Articles

Related Content

Image Gallery

Screen Scrolling Routine

Source Code

   1 REM \2A\0C\40\23\E5\11\21\00\19\D1\01\B5\02\ED\B0\EB\06\20\36\00\23\10\FB\C9\2A\10\40\11\43\00\ED\52\E5\11\21\00\ED\52\D1\01\B5\02\ED\B8\EB\06\20\2B\36\00\10\FB\C9\2A\0C\40\06\16\C5\06\20\3E\00\23\4F\7E\71\10\FA\23\C1\10\F1\C9\2A\10\40\11\43\00\ED\52\06\16\C5\06\20\3E\00\2B\4F\7E\71\10\FA\2B\C1\10\F1\C9\1D\1E\1F\20\21\22\23\24\25\1C
   5 LIST 35
  20 LET D$=INKEY$
  25 IF D$="J" THEN RAND USR 16588
  30 IF D$="M" THEN RAND USR 16538
  35 IF D$="I" THEN RAND USR 16514
  40 IF D$="K" THEN RAND USR 16567
  41 IF D$="U" THEN GOTO 43
  42 GOTO 45
  43 RAND USR 16514
  44 RAND USR 16588
  45 IF D$="O" THEN GOTO 47
  46 GOTO 49
  47 RAND USR 16514
  48 RAND USR 16567
  49 IF D$="." THEN GOTO 51
  50 GOTO 53
  51 RAND USR 16538
  52 RAND USR 16567
  53 IF D$="N" THEN GOTO 55
  54 GOTO 57
  55 RAND USR 16538
  56 RAND USR 16588
  60 GOTO 20
  70 SAVE "1009%7"
  80 GOTO 5

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

People

No people associated with this content.

Scroll to Top
\ED\B0\EB

Screen Scrolling Routine

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

This program implements a character-movement or screen-scrolling system driven entirely by machine code routines embedded in the REM statement at line 1. The BASIC shell reads a keypress via INKEY$ and dispatches to one of four machine code entry points (USR 16514, 16538, 16567, 16588) depending on the key pressed, covering eight directions: J, M, I, K for cardinal directions and U, O, ., N for diagonals (combining two cardinal calls). The machine code, stored beginning at address 16514 (0x4082, just inside the REM statement data), performs direct memory operations including LDIR and LDDR block moves, consistent with scrolling a screen region or shifting a sprite/character buffer. The SAVE at line 70 uses an inverse-video character in the filename as an auto-run marker.


Program Analysis

Program Structure

The program has three logical layers:

  1. Machine code store — Line 1 is a REM statement whose body contains raw Z80 opcodes. Because the ZX Spectrum/TS2068 stores REM data verbatim in RAM, the bytes are directly executable starting at the address of the first byte after the REM token.
  2. Input loop — Lines 20–60 form a tight polling loop: INKEY$ is sampled at line 20, then a cascade of IF/GOTO chains dispatches to the appropriate machine code entry point(s).
  3. Housekeeping — Lines 70–80 provide a SAVE and a GOTO 5 (which jumps to LIST 35) for re-entry/display purposes.

Machine Code Entry Points

Line 1 begins at address 16384 (0x4000). The REM token occupies one byte and the two-byte length field two more, placing the first opcode at 0x4003 (16387). However, the BASIC calls target four distinct addresses:

USR AddressHexKey(s)Role (inferred)
165140x4082I, U, OScroll/move up
165380x409AM, ., NScroll/move down
165670x40B7K, ., NScroll/move right
165880x40CCJ, U, NScroll/move left

The REM data is 59 bytes long (the trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C are likely padding or lookup data). The entry points are therefore spread across the REM body and each routine ends with a C9 (RET) opcode.

Z80 Routine Analysis

Disassembling the REM bytes reveals four subroutines that use the Z80 block-move instructions LDIR (ED B0) and LDDR (ED B8) to shift screen memory. Common patterns observed:

  • 2A 0C 40LD HL,(0x400C): loads a pointer from within the REM area itself (self-referential data).
  • 11 21 00LD DE,0x0021 (33 decimal): one character row width on a 32-column display plus one, used as an offset for vertical scrolling.
  • ED B0 / ED B8LDIR/LDDR: bulk copy forward/backward for up/down scroll directions.
  • 01 B5 02LD BC,0x02B5 (693): the byte count, matching the number of bytes in roughly 21.6 character rows — consistent with scrolling most of the display.
  • 36 00 inside a DJNZ loop — LD (HL),0: clears the vacated edge row/column after a scroll.
  • 06 20LD B,0x20 (32): loop counter for clearing 32 columns.
  • 06 16LD B,0x16 (22): loop counter for clearing 22 rows.

Key Mapping and Diagonal Movement

The eight keys map naturally to a numeric-keypad layout:

KeyDirectionRoutines called
IUpUSR 16514
KRightUSR 16567
MDownUSR 16538
JLeftUSR 16588
UUp-LeftUSR 16514 + USR 16588
OUp-RightUSR 16514 + USR 16567
.Down-RightUSR 16538 + USR 16567
NDown-LeftUSR 16538 + USR 16588

Diagonal movement is achieved by sequentially calling two cardinal-direction routines in BASIC rather than implementing combined diagonals in machine code, keeping the MC routines simple and orthogonal.

Notable Techniques

  • REM-as-code store: embedding machine code in a REM line is a standard technique that keeps the code in a known, fixed address and prevents the BASIC editor from interpreting the bytes.
  • Self-referential data pointer: LD HL,(0x400C) reads a word from within the REM statement itself, allowing the routine to find its own working data without hardcoding a separate address.
  • LDIR/LDDR for scrolling: using the Z80 block-copy instructions is the fastest pure-Z80 approach to scrolling a rectangular region of screen memory.
  • DJNZ clear loop: after a scroll, a DJNZ loop with LD (HL),0 efficiently blanks the newly exposed row or column.
  • Line 5 LIST 35: GOTO 5 at line 80 causes the program listing to scroll to line 35, effectively hiding the machine code REM from casual view on restart.
  • INKEY$ polling without PAUSE: line 20 samples the keyboard every BASIC iteration with no delay, giving the fastest possible response at the cost of no key-repeat debounce.

Potential Anomalies

  • Line 57 is referenced by GOTO 57 (line 54) but does not exist. After the cascade of diagonal-key checks, control falls through to GOTO 20 at line 60 — the missing line 57 simply causes BASIC to continue to the next higher line, which is line 60. This is intentional and well-understood behaviour.
  • The trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C at the end of the REM (control codes 28–37) are not reachable as code; they appear to be a lookup table or padding used as data by the routines.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10051 – 10121.

Related Products

Related Articles

Related Content

Image Gallery

Screen Scrolling Routine

Source Code

   1 REM \2A\0C\40\23\E5\11\21\00\19\D1\01\B5\02\ED\B0\EB\06\20\36\00\23\10\FB\C9\2A\10\40\11\43\00\ED\52\E5\11\21\00\ED\52\D1\01\B5\02\ED\B8\EB\06\20\2B\36\00\10\FB\C9\2A\0C\40\06\16\C5\06\20\3E\00\23\4F\7E\71\10\FA\23\C1\10\F1\C9\2A\10\40\11\43\00\ED\52\06\16\C5\06\20\3E\00\2B\4F\7E\71\10\FA\2B\C1\10\F1\C9\1D\1E\1F\20\21\22\23\24\25\1C
   5 LIST 35
  20 LET D$=INKEY$
  25 IF D$="J" THEN RAND USR 16588
  30 IF D$="M" THEN RAND USR 16538
  35 IF D$="I" THEN RAND USR 16514
  40 IF D$="K" THEN RAND USR 16567
  41 IF D$="U" THEN GOTO 43
  42 GOTO 45
  43 RAND USR 16514
  44 RAND USR 16588
  45 IF D$="O" THEN GOTO 47
  46 GOTO 49
  47 RAND USR 16514
  48 RAND USR 16567
  49 IF D$="." THEN GOTO 51
  50 GOTO 53
  51 RAND USR 16538
  52 RAND USR 16567
  53 IF D$="N" THEN GOTO 55
  54 GOTO 57
  55 RAND USR 16538
  56 RAND USR 16588
  60 GOTO 20
  70 SAVE "1009%7"
  80 GOTO 5

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

People

No people associated with this content.

Scroll to Top
\FB\C9

Screen Scrolling Routine

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

This program implements a character-movement or screen-scrolling system driven entirely by machine code routines embedded in the REM statement at line 1. The BASIC shell reads a keypress via INKEY$ and dispatches to one of four machine code entry points (USR 16514, 16538, 16567, 16588) depending on the key pressed, covering eight directions: J, M, I, K for cardinal directions and U, O, ., N for diagonals (combining two cardinal calls). The machine code, stored beginning at address 16514 (0x4082, just inside the REM statement data), performs direct memory operations including LDIR and LDDR block moves, consistent with scrolling a screen region or shifting a sprite/character buffer. The SAVE at line 70 uses an inverse-video character in the filename as an auto-run marker.


Program Analysis

Program Structure

The program has three logical layers:

  1. Machine code store — Line 1 is a REM statement whose body contains raw Z80 opcodes. Because the ZX Spectrum/TS2068 stores REM data verbatim in RAM, the bytes are directly executable starting at the address of the first byte after the REM token.
  2. Input loop — Lines 20–60 form a tight polling loop: INKEY$ is sampled at line 20, then a cascade of IF/GOTO chains dispatches to the appropriate machine code entry point(s).
  3. Housekeeping — Lines 70–80 provide a SAVE and a GOTO 5 (which jumps to LIST 35) for re-entry/display purposes.

Machine Code Entry Points

Line 1 begins at address 16384 (0x4000). The REM token occupies one byte and the two-byte length field two more, placing the first opcode at 0x4003 (16387). However, the BASIC calls target four distinct addresses:

USR AddressHexKey(s)Role (inferred)
165140x4082I, U, OScroll/move up
165380x409AM, ., NScroll/move down
165670x40B7K, ., NScroll/move right
165880x40CCJ, U, NScroll/move left

The REM data is 59 bytes long (the trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C are likely padding or lookup data). The entry points are therefore spread across the REM body and each routine ends with a C9 (RET) opcode.

Z80 Routine Analysis

Disassembling the REM bytes reveals four subroutines that use the Z80 block-move instructions LDIR (ED B0) and LDDR (ED B8) to shift screen memory. Common patterns observed:

  • 2A 0C 40LD HL,(0x400C): loads a pointer from within the REM area itself (self-referential data).
  • 11 21 00LD DE,0x0021 (33 decimal): one character row width on a 32-column display plus one, used as an offset for vertical scrolling.
  • ED B0 / ED B8LDIR/LDDR: bulk copy forward/backward for up/down scroll directions.
  • 01 B5 02LD BC,0x02B5 (693): the byte count, matching the number of bytes in roughly 21.6 character rows — consistent with scrolling most of the display.
  • 36 00 inside a DJNZ loop — LD (HL),0: clears the vacated edge row/column after a scroll.
  • 06 20LD B,0x20 (32): loop counter for clearing 32 columns.
  • 06 16LD B,0x16 (22): loop counter for clearing 22 rows.

Key Mapping and Diagonal Movement

The eight keys map naturally to a numeric-keypad layout:

KeyDirectionRoutines called
IUpUSR 16514
KRightUSR 16567
MDownUSR 16538
JLeftUSR 16588
UUp-LeftUSR 16514 + USR 16588
OUp-RightUSR 16514 + USR 16567
.Down-RightUSR 16538 + USR 16567
NDown-LeftUSR 16538 + USR 16588

Diagonal movement is achieved by sequentially calling two cardinal-direction routines in BASIC rather than implementing combined diagonals in machine code, keeping the MC routines simple and orthogonal.

Notable Techniques

  • REM-as-code store: embedding machine code in a REM line is a standard technique that keeps the code in a known, fixed address and prevents the BASIC editor from interpreting the bytes.
  • Self-referential data pointer: LD HL,(0x400C) reads a word from within the REM statement itself, allowing the routine to find its own working data without hardcoding a separate address.
  • LDIR/LDDR for scrolling: using the Z80 block-copy instructions is the fastest pure-Z80 approach to scrolling a rectangular region of screen memory.
  • DJNZ clear loop: after a scroll, a DJNZ loop with LD (HL),0 efficiently blanks the newly exposed row or column.
  • Line 5 LIST 35: GOTO 5 at line 80 causes the program listing to scroll to line 35, effectively hiding the machine code REM from casual view on restart.
  • INKEY$ polling without PAUSE: line 20 samples the keyboard every BASIC iteration with no delay, giving the fastest possible response at the cost of no key-repeat debounce.

Potential Anomalies

  • Line 57 is referenced by GOTO 57 (line 54) but does not exist. After the cascade of diagonal-key checks, control falls through to GOTO 20 at line 60 — the missing line 57 simply causes BASIC to continue to the next higher line, which is line 60. This is intentional and well-understood behaviour.
  • The trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C at the end of the REM (control codes 28–37) are not reachable as code; they appear to be a lookup table or padding used as data by the routines.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10051 – 10121.

Related Products

Related Articles

Related Content

Image Gallery

Screen Scrolling Routine

Source Code

   1 REM \2A\0C\40\23\E5\11\21\00\19\D1\01\B5\02\ED\B0\EB\06\20\36\00\23\10\FB\C9\2A\10\40\11\43\00\ED\52\E5\11\21\00\ED\52\D1\01\B5\02\ED\B8\EB\06\20\2B\36\00\10\FB\C9\2A\0C\40\06\16\C5\06\20\3E\00\23\4F\7E\71\10\FA\23\C1\10\F1\C9\2A\10\40\11\43\00\ED\52\06\16\C5\06\20\3E\00\2B\4F\7E\71\10\FA\2B\C1\10\F1\C9\1D\1E\1F\20\21\22\23\24\25\1C
   5 LIST 35
  20 LET D$=INKEY$
  25 IF D$="J" THEN RAND USR 16588
  30 IF D$="M" THEN RAND USR 16538
  35 IF D$="I" THEN RAND USR 16514
  40 IF D$="K" THEN RAND USR 16567
  41 IF D$="U" THEN GOTO 43
  42 GOTO 45
  43 RAND USR 16514
  44 RAND USR 16588
  45 IF D$="O" THEN GOTO 47
  46 GOTO 49
  47 RAND USR 16514
  48 RAND USR 16567
  49 IF D$="." THEN GOTO 51
  50 GOTO 53
  51 RAND USR 16538
  52 RAND USR 16567
  53 IF D$="N" THEN GOTO 55
  54 GOTO 57
  55 RAND USR 16538
  56 RAND USR 16588
  60 GOTO 20
  70 SAVE "1009%7"
  80 GOTO 5

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

People

No people associated with this content.

Scroll to Top
A

Screen Scrolling Routine

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

This program implements a character-movement or screen-scrolling system driven entirely by machine code routines embedded in the REM statement at line 1. The BASIC shell reads a keypress via INKEY$ and dispatches to one of four machine code entry points (USR 16514, 16538, 16567, 16588) depending on the key pressed, covering eight directions: J, M, I, K for cardinal directions and U, O, ., N for diagonals (combining two cardinal calls). The machine code, stored beginning at address 16514 (0x4082, just inside the REM statement data), performs direct memory operations including LDIR and LDDR block moves, consistent with scrolling a screen region or shifting a sprite/character buffer. The SAVE at line 70 uses an inverse-video character in the filename as an auto-run marker.


Program Analysis

Program Structure

The program has three logical layers:

  1. Machine code store — Line 1 is a REM statement whose body contains raw Z80 opcodes. Because the ZX Spectrum/TS2068 stores REM data verbatim in RAM, the bytes are directly executable starting at the address of the first byte after the REM token.
  2. Input loop — Lines 20–60 form a tight polling loop: INKEY$ is sampled at line 20, then a cascade of IF/GOTO chains dispatches to the appropriate machine code entry point(s).
  3. Housekeeping — Lines 70–80 provide a SAVE and a GOTO 5 (which jumps to LIST 35) for re-entry/display purposes.

Machine Code Entry Points

Line 1 begins at address 16384 (0x4000). The REM token occupies one byte and the two-byte length field two more, placing the first opcode at 0x4003 (16387). However, the BASIC calls target four distinct addresses:

USR AddressHexKey(s)Role (inferred)
165140x4082I, U, OScroll/move up
165380x409AM, ., NScroll/move down
165670x40B7K, ., NScroll/move right
165880x40CCJ, U, NScroll/move left

The REM data is 59 bytes long (the trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C are likely padding or lookup data). The entry points are therefore spread across the REM body and each routine ends with a C9 (RET) opcode.

Z80 Routine Analysis

Disassembling the REM bytes reveals four subroutines that use the Z80 block-move instructions LDIR (ED B0) and LDDR (ED B8) to shift screen memory. Common patterns observed:

  • 2A 0C 40LD HL,(0x400C): loads a pointer from within the REM area itself (self-referential data).
  • 11 21 00LD DE,0x0021 (33 decimal): one character row width on a 32-column display plus one, used as an offset for vertical scrolling.
  • ED B0 / ED B8LDIR/LDDR: bulk copy forward/backward for up/down scroll directions.
  • 01 B5 02LD BC,0x02B5 (693): the byte count, matching the number of bytes in roughly 21.6 character rows — consistent with scrolling most of the display.
  • 36 00 inside a DJNZ loop — LD (HL),0: clears the vacated edge row/column after a scroll.
  • 06 20LD B,0x20 (32): loop counter for clearing 32 columns.
  • 06 16LD B,0x16 (22): loop counter for clearing 22 rows.

Key Mapping and Diagonal Movement

The eight keys map naturally to a numeric-keypad layout:

KeyDirectionRoutines called
IUpUSR 16514
KRightUSR 16567
MDownUSR 16538
JLeftUSR 16588
UUp-LeftUSR 16514 + USR 16588
OUp-RightUSR 16514 + USR 16567
.Down-RightUSR 16538 + USR 16567
NDown-LeftUSR 16538 + USR 16588

Diagonal movement is achieved by sequentially calling two cardinal-direction routines in BASIC rather than implementing combined diagonals in machine code, keeping the MC routines simple and orthogonal.

Notable Techniques

  • REM-as-code store: embedding machine code in a REM line is a standard technique that keeps the code in a known, fixed address and prevents the BASIC editor from interpreting the bytes.
  • Self-referential data pointer: LD HL,(0x400C) reads a word from within the REM statement itself, allowing the routine to find its own working data without hardcoding a separate address.
  • LDIR/LDDR for scrolling: using the Z80 block-copy instructions is the fastest pure-Z80 approach to scrolling a rectangular region of screen memory.
  • DJNZ clear loop: after a scroll, a DJNZ loop with LD (HL),0 efficiently blanks the newly exposed row or column.
  • Line 5 LIST 35: GOTO 5 at line 80 causes the program listing to scroll to line 35, effectively hiding the machine code REM from casual view on restart.
  • INKEY$ polling without PAUSE: line 20 samples the keyboard every BASIC iteration with no delay, giving the fastest possible response at the cost of no key-repeat debounce.

Potential Anomalies

  • Line 57 is referenced by GOTO 57 (line 54) but does not exist. After the cascade of diagonal-key checks, control falls through to GOTO 20 at line 60 — the missing line 57 simply causes BASIC to continue to the next higher line, which is line 60. This is intentional and well-understood behaviour.
  • The trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C at the end of the REM (control codes 28–37) are not reachable as code; they appear to be a lookup table or padding used as data by the routines.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10051 – 10121.

Related Products

Related Articles

Related Content

Image Gallery

Screen Scrolling Routine

Source Code

   1 REM \2A\0C\40\23\E5\11\21\00\19\D1\01\B5\02\ED\B0\EB\06\20\36\00\23\10\FB\C9\2A\10\40\11\43\00\ED\52\E5\11\21\00\ED\52\D1\01\B5\02\ED\B8\EB\06\20\2B\36\00\10\FB\C9\2A\0C\40\06\16\C5\06\20\3E\00\23\4F\7E\71\10\FA\23\C1\10\F1\C9\2A\10\40\11\43\00\ED\52\06\16\C5\06\20\3E\00\2B\4F\7E\71\10\FA\2B\C1\10\F1\C9\1D\1E\1F\20\21\22\23\24\25\1C
   5 LIST 35
  20 LET D$=INKEY$
  25 IF D$="J" THEN RAND USR 16588
  30 IF D$="M" THEN RAND USR 16538
  35 IF D$="I" THEN RAND USR 16514
  40 IF D$="K" THEN RAND USR 16567
  41 IF D$="U" THEN GOTO 43
  42 GOTO 45
  43 RAND USR 16514
  44 RAND USR 16588
  45 IF D$="O" THEN GOTO 47
  46 GOTO 49
  47 RAND USR 16514
  48 RAND USR 16567
  49 IF D$="." THEN GOTO 51
  50 GOTO 53
  51 RAND USR 16538
  52 RAND USR 16567
  53 IF D$="N" THEN GOTO 55
  54 GOTO 57
  55 RAND USR 16538
  56 RAND USR 16588
  60 GOTO 20
  70 SAVE "1009%7"
  80 GOTO 5

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

People

No people associated with this content.

Scroll to Top
\ED\E5

Screen Scrolling Routine

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

This program implements a character-movement or screen-scrolling system driven entirely by machine code routines embedded in the REM statement at line 1. The BASIC shell reads a keypress via INKEY$ and dispatches to one of four machine code entry points (USR 16514, 16538, 16567, 16588) depending on the key pressed, covering eight directions: J, M, I, K for cardinal directions and U, O, ., N for diagonals (combining two cardinal calls). The machine code, stored beginning at address 16514 (0x4082, just inside the REM statement data), performs direct memory operations including LDIR and LDDR block moves, consistent with scrolling a screen region or shifting a sprite/character buffer. The SAVE at line 70 uses an inverse-video character in the filename as an auto-run marker.


Program Analysis

Program Structure

The program has three logical layers:

  1. Machine code store — Line 1 is a REM statement whose body contains raw Z80 opcodes. Because the ZX Spectrum/TS2068 stores REM data verbatim in RAM, the bytes are directly executable starting at the address of the first byte after the REM token.
  2. Input loop — Lines 20–60 form a tight polling loop: INKEY$ is sampled at line 20, then a cascade of IF/GOTO chains dispatches to the appropriate machine code entry point(s).
  3. Housekeeping — Lines 70–80 provide a SAVE and a GOTO 5 (which jumps to LIST 35) for re-entry/display purposes.

Machine Code Entry Points

Line 1 begins at address 16384 (0x4000). The REM token occupies one byte and the two-byte length field two more, placing the first opcode at 0x4003 (16387). However, the BASIC calls target four distinct addresses:

USR AddressHexKey(s)Role (inferred)
165140x4082I, U, OScroll/move up
165380x409AM, ., NScroll/move down
165670x40B7K, ., NScroll/move right
165880x40CCJ, U, NScroll/move left

The REM data is 59 bytes long (the trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C are likely padding or lookup data). The entry points are therefore spread across the REM body and each routine ends with a C9 (RET) opcode.

Z80 Routine Analysis

Disassembling the REM bytes reveals four subroutines that use the Z80 block-move instructions LDIR (ED B0) and LDDR (ED B8) to shift screen memory. Common patterns observed:

  • 2A 0C 40LD HL,(0x400C): loads a pointer from within the REM area itself (self-referential data).
  • 11 21 00LD DE,0x0021 (33 decimal): one character row width on a 32-column display plus one, used as an offset for vertical scrolling.
  • ED B0 / ED B8LDIR/LDDR: bulk copy forward/backward for up/down scroll directions.
  • 01 B5 02LD BC,0x02B5 (693): the byte count, matching the number of bytes in roughly 21.6 character rows — consistent with scrolling most of the display.
  • 36 00 inside a DJNZ loop — LD (HL),0: clears the vacated edge row/column after a scroll.
  • 06 20LD B,0x20 (32): loop counter for clearing 32 columns.
  • 06 16LD B,0x16 (22): loop counter for clearing 22 rows.

Key Mapping and Diagonal Movement

The eight keys map naturally to a numeric-keypad layout:

KeyDirectionRoutines called
IUpUSR 16514
KRightUSR 16567
MDownUSR 16538
JLeftUSR 16588
UUp-LeftUSR 16514 + USR 16588
OUp-RightUSR 16514 + USR 16567
.Down-RightUSR 16538 + USR 16567
NDown-LeftUSR 16538 + USR 16588

Diagonal movement is achieved by sequentially calling two cardinal-direction routines in BASIC rather than implementing combined diagonals in machine code, keeping the MC routines simple and orthogonal.

Notable Techniques

  • REM-as-code store: embedding machine code in a REM line is a standard technique that keeps the code in a known, fixed address and prevents the BASIC editor from interpreting the bytes.
  • Self-referential data pointer: LD HL,(0x400C) reads a word from within the REM statement itself, allowing the routine to find its own working data without hardcoding a separate address.
  • LDIR/LDDR for scrolling: using the Z80 block-copy instructions is the fastest pure-Z80 approach to scrolling a rectangular region of screen memory.
  • DJNZ clear loop: after a scroll, a DJNZ loop with LD (HL),0 efficiently blanks the newly exposed row or column.
  • Line 5 LIST 35: GOTO 5 at line 80 causes the program listing to scroll to line 35, effectively hiding the machine code REM from casual view on restart.
  • INKEY$ polling without PAUSE: line 20 samples the keyboard every BASIC iteration with no delay, giving the fastest possible response at the cost of no key-repeat debounce.

Potential Anomalies

  • Line 57 is referenced by GOTO 57 (line 54) but does not exist. After the cascade of diagonal-key checks, control falls through to GOTO 20 at line 60 — the missing line 57 simply causes BASIC to continue to the next higher line, which is line 60. This is intentional and well-understood behaviour.
  • The trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C at the end of the REM (control codes 28–37) are not reachable as code; they appear to be a lookup table or padding used as data by the routines.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10051 – 10121.

Related Products

Related Articles

Related Content

Image Gallery

Screen Scrolling Routine

Source Code

   1 REM \2A\0C\40\23\E5\11\21\00\19\D1\01\B5\02\ED\B0\EB\06\20\36\00\23\10\FB\C9\2A\10\40\11\43\00\ED\52\E5\11\21\00\ED\52\D1\01\B5\02\ED\B8\EB\06\20\2B\36\00\10\FB\C9\2A\0C\40\06\16\C5\06\20\3E\00\23\4F\7E\71\10\FA\23\C1\10\F1\C9\2A\10\40\11\43\00\ED\52\06\16\C5\06\20\3E\00\2B\4F\7E\71\10\FA\2B\C1\10\F1\C9\1D\1E\1F\20\21\22\23\24\25\1C
   5 LIST 35
  20 LET D$=INKEY$
  25 IF D$="J" THEN RAND USR 16588
  30 IF D$="M" THEN RAND USR 16538
  35 IF D$="I" THEN RAND USR 16514
  40 IF D$="K" THEN RAND USR 16567
  41 IF D$="U" THEN GOTO 43
  42 GOTO 45
  43 RAND USR 16514
  44 RAND USR 16588
  45 IF D$="O" THEN GOTO 47
  46 GOTO 49
  47 RAND USR 16514
  48 RAND USR 16567
  49 IF D$="." THEN GOTO 51
  50 GOTO 53
  51 RAND USR 16538
  52 RAND USR 16567
  53 IF D$="N" THEN GOTO 55
  54 GOTO 57
  55 RAND USR 16538
  56 RAND USR 16588
  60 GOTO 20
  70 SAVE "1009%7"
  80 GOTO 5

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

People

No people associated with this content.

Scroll to Top
\ED\D1 itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57148 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.5 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

Screen Scrolling Routine

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

This program implements a character-movement or screen-scrolling system driven entirely by machine code routines embedded in the REM statement at line 1. The BASIC shell reads a keypress via INKEY$ and dispatches to one of four machine code entry points (USR 16514, 16538, 16567, 16588) depending on the key pressed, covering eight directions: J, M, I, K for cardinal directions and U, O, ., N for diagonals (combining two cardinal calls). The machine code, stored beginning at address 16514 (0x4082, just inside the REM statement data), performs direct memory operations including LDIR and LDDR block moves, consistent with scrolling a screen region or shifting a sprite/character buffer. The SAVE at line 70 uses an inverse-video character in the filename as an auto-run marker.


Program Analysis

Program Structure

The program has three logical layers:

  1. Machine code store — Line 1 is a REM statement whose body contains raw Z80 opcodes. Because the ZX Spectrum/TS2068 stores REM data verbatim in RAM, the bytes are directly executable starting at the address of the first byte after the REM token.
  2. Input loop — Lines 20–60 form a tight polling loop: INKEY$ is sampled at line 20, then a cascade of IF/GOTO chains dispatches to the appropriate machine code entry point(s).
  3. Housekeeping — Lines 70–80 provide a SAVE and a GOTO 5 (which jumps to LIST 35) for re-entry/display purposes.

Machine Code Entry Points

Line 1 begins at address 16384 (0x4000). The REM token occupies one byte and the two-byte length field two more, placing the first opcode at 0x4003 (16387). However, the BASIC calls target four distinct addresses:

USR AddressHexKey(s)Role (inferred)
165140x4082I, U, OScroll/move up
165380x409AM, ., NScroll/move down
165670x40B7K, ., NScroll/move right
165880x40CCJ, U, NScroll/move left

The REM data is 59 bytes long (the trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C are likely padding or lookup data). The entry points are therefore spread across the REM body and each routine ends with a C9 (RET) opcode.

Z80 Routine Analysis

Disassembling the REM bytes reveals four subroutines that use the Z80 block-move instructions LDIR (ED B0) and LDDR (ED B8) to shift screen memory. Common patterns observed:

  • 2A 0C 40LD HL,(0x400C): loads a pointer from within the REM area itself (self-referential data).
  • 11 21 00LD DE,0x0021 (33 decimal): one character row width on a 32-column display plus one, used as an offset for vertical scrolling.
  • ED B0 / ED B8LDIR/LDDR: bulk copy forward/backward for up/down scroll directions.
  • 01 B5 02LD BC,0x02B5 (693): the byte count, matching the number of bytes in roughly 21.6 character rows — consistent with scrolling most of the display.
  • 36 00 inside a DJNZ loop — LD (HL),0: clears the vacated edge row/column after a scroll.
  • 06 20LD B,0x20 (32): loop counter for clearing 32 columns.
  • 06 16LD B,0x16 (22): loop counter for clearing 22 rows.

Key Mapping and Diagonal Movement

The eight keys map naturally to a numeric-keypad layout:

KeyDirectionRoutines called
IUpUSR 16514
KRightUSR 16567
MDownUSR 16538
JLeftUSR 16588
UUp-LeftUSR 16514 + USR 16588
OUp-RightUSR 16514 + USR 16567
.Down-RightUSR 16538 + USR 16567
NDown-LeftUSR 16538 + USR 16588

Diagonal movement is achieved by sequentially calling two cardinal-direction routines in BASIC rather than implementing combined diagonals in machine code, keeping the MC routines simple and orthogonal.

Notable Techniques

  • REM-as-code store: embedding machine code in a REM line is a standard technique that keeps the code in a known, fixed address and prevents the BASIC editor from interpreting the bytes.
  • Self-referential data pointer: LD HL,(0x400C) reads a word from within the REM statement itself, allowing the routine to find its own working data without hardcoding a separate address.
  • LDIR/LDDR for scrolling: using the Z80 block-copy instructions is the fastest pure-Z80 approach to scrolling a rectangular region of screen memory.
  • DJNZ clear loop: after a scroll, a DJNZ loop with LD (HL),0 efficiently blanks the newly exposed row or column.
  • Line 5 LIST 35: GOTO 5 at line 80 causes the program listing to scroll to line 35, effectively hiding the machine code REM from casual view on restart.
  • INKEY$ polling without PAUSE: line 20 samples the keyboard every BASIC iteration with no delay, giving the fastest possible response at the cost of no key-repeat debounce.

Potential Anomalies

  • Line 57 is referenced by GOTO 57 (line 54) but does not exist. After the cascade of diagonal-key checks, control falls through to GOTO 20 at line 60 — the missing line 57 simply causes BASIC to continue to the next higher line, which is line 60. This is intentional and well-understood behaviour.
  • The trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C at the end of the REM (control codes 28–37) are not reachable as code; they appear to be a lookup table or padding used as data by the routines.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10051 – 10121.

Related Products

Related Articles

Related Content

Image Gallery

Screen Scrolling Routine

Source Code

   1 REM \2A\0C\40\23\E5\11\21\00\19\D1\01\B5\02\ED\B0\EB\06\20\36\00\23\10\FB\C9\2A\10\40\11\43\00\ED\52\E5\11\21\00\ED\52\D1\01\B5\02\ED\B8\EB\06\20\2B\36\00\10\FB\C9\2A\0C\40\06\16\C5\06\20\3E\00\23\4F\7E\71\10\FA\23\C1\10\F1\C9\2A\10\40\11\43\00\ED\52\06\16\C5\06\20\3E\00\2B\4F\7E\71\10\FA\2B\C1\10\F1\C9\1D\1E\1F\20\21\22\23\24\25\1C
   5 LIST 35
  20 LET D$=INKEY$
  25 IF D$="J" THEN RAND USR 16588
  30 IF D$="M" THEN RAND USR 16538
  35 IF D$="I" THEN RAND USR 16514
  40 IF D$="K" THEN RAND USR 16567
  41 IF D$="U" THEN GOTO 43
  42 GOTO 45
  43 RAND USR 16514
  44 RAND USR 16588
  45 IF D$="O" THEN GOTO 47
  46 GOTO 49
  47 RAND USR 16514
  48 RAND USR 16567
  49 IF D$="." THEN GOTO 51
  50 GOTO 53
  51 RAND USR 16538
  52 RAND USR 16567
  53 IF D$="N" THEN GOTO 55
  54 GOTO 57
  55 RAND USR 16538
  56 RAND USR 16588
  60 GOTO 20
  70 SAVE "1009%7"
  80 GOTO 5

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

People

No people associated with this content.

Scroll to Top
\ED\B8\EB

Screen Scrolling Routine

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

This program implements a character-movement or screen-scrolling system driven entirely by machine code routines embedded in the REM statement at line 1. The BASIC shell reads a keypress via INKEY$ and dispatches to one of four machine code entry points (USR 16514, 16538, 16567, 16588) depending on the key pressed, covering eight directions: J, M, I, K for cardinal directions and U, O, ., N for diagonals (combining two cardinal calls). The machine code, stored beginning at address 16514 (0x4082, just inside the REM statement data), performs direct memory operations including LDIR and LDDR block moves, consistent with scrolling a screen region or shifting a sprite/character buffer. The SAVE at line 70 uses an inverse-video character in the filename as an auto-run marker.


Program Analysis

Program Structure

The program has three logical layers:

  1. Machine code store — Line 1 is a REM statement whose body contains raw Z80 opcodes. Because the ZX Spectrum/TS2068 stores REM data verbatim in RAM, the bytes are directly executable starting at the address of the first byte after the REM token.
  2. Input loop — Lines 20–60 form a tight polling loop: INKEY$ is sampled at line 20, then a cascade of IF/GOTO chains dispatches to the appropriate machine code entry point(s).
  3. Housekeeping — Lines 70–80 provide a SAVE and a GOTO 5 (which jumps to LIST 35) for re-entry/display purposes.

Machine Code Entry Points

Line 1 begins at address 16384 (0x4000). The REM token occupies one byte and the two-byte length field two more, placing the first opcode at 0x4003 (16387). However, the BASIC calls target four distinct addresses:

USR AddressHexKey(s)Role (inferred)
165140x4082I, U, OScroll/move up
165380x409AM, ., NScroll/move down
165670x40B7K, ., NScroll/move right
165880x40CCJ, U, NScroll/move left

The REM data is 59 bytes long (the trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C are likely padding or lookup data). The entry points are therefore spread across the REM body and each routine ends with a C9 (RET) opcode.

Z80 Routine Analysis

Disassembling the REM bytes reveals four subroutines that use the Z80 block-move instructions LDIR (ED B0) and LDDR (ED B8) to shift screen memory. Common patterns observed:

  • 2A 0C 40LD HL,(0x400C): loads a pointer from within the REM area itself (self-referential data).
  • 11 21 00LD DE,0x0021 (33 decimal): one character row width on a 32-column display plus one, used as an offset for vertical scrolling.
  • ED B0 / ED B8LDIR/LDDR: bulk copy forward/backward for up/down scroll directions.
  • 01 B5 02LD BC,0x02B5 (693): the byte count, matching the number of bytes in roughly 21.6 character rows — consistent with scrolling most of the display.
  • 36 00 inside a DJNZ loop — LD (HL),0: clears the vacated edge row/column after a scroll.
  • 06 20LD B,0x20 (32): loop counter for clearing 32 columns.
  • 06 16LD B,0x16 (22): loop counter for clearing 22 rows.

Key Mapping and Diagonal Movement

The eight keys map naturally to a numeric-keypad layout:

KeyDirectionRoutines called
IUpUSR 16514
KRightUSR 16567
MDownUSR 16538
JLeftUSR 16588
UUp-LeftUSR 16514 + USR 16588
OUp-RightUSR 16514 + USR 16567
.Down-RightUSR 16538 + USR 16567
NDown-LeftUSR 16538 + USR 16588

Diagonal movement is achieved by sequentially calling two cardinal-direction routines in BASIC rather than implementing combined diagonals in machine code, keeping the MC routines simple and orthogonal.

Notable Techniques

  • REM-as-code store: embedding machine code in a REM line is a standard technique that keeps the code in a known, fixed address and prevents the BASIC editor from interpreting the bytes.
  • Self-referential data pointer: LD HL,(0x400C) reads a word from within the REM statement itself, allowing the routine to find its own working data without hardcoding a separate address.
  • LDIR/LDDR for scrolling: using the Z80 block-copy instructions is the fastest pure-Z80 approach to scrolling a rectangular region of screen memory.
  • DJNZ clear loop: after a scroll, a DJNZ loop with LD (HL),0 efficiently blanks the newly exposed row or column.
  • Line 5 LIST 35: GOTO 5 at line 80 causes the program listing to scroll to line 35, effectively hiding the machine code REM from casual view on restart.
  • INKEY$ polling without PAUSE: line 20 samples the keyboard every BASIC iteration with no delay, giving the fastest possible response at the cost of no key-repeat debounce.

Potential Anomalies

  • Line 57 is referenced by GOTO 57 (line 54) but does not exist. After the cascade of diagonal-key checks, control falls through to GOTO 20 at line 60 — the missing line 57 simply causes BASIC to continue to the next higher line, which is line 60. This is intentional and well-understood behaviour.
  • The trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C at the end of the REM (control codes 28–37) are not reachable as code; they appear to be a lookup table or padding used as data by the routines.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10051 – 10121.

Related Products

Related Articles

Related Content

Image Gallery

Screen Scrolling Routine

Source Code

   1 REM \2A\0C\40\23\E5\11\21\00\19\D1\01\B5\02\ED\B0\EB\06\20\36\00\23\10\FB\C9\2A\10\40\11\43\00\ED\52\E5\11\21\00\ED\52\D1\01\B5\02\ED\B8\EB\06\20\2B\36\00\10\FB\C9\2A\0C\40\06\16\C5\06\20\3E\00\23\4F\7E\71\10\FA\23\C1\10\F1\C9\2A\10\40\11\43\00\ED\52\06\16\C5\06\20\3E\00\2B\4F\7E\71\10\FA\2B\C1\10\F1\C9\1D\1E\1F\20\21\22\23\24\25\1C
   5 LIST 35
  20 LET D$=INKEY$
  25 IF D$="J" THEN RAND USR 16588
  30 IF D$="M" THEN RAND USR 16538
  35 IF D$="I" THEN RAND USR 16514
  40 IF D$="K" THEN RAND USR 16567
  41 IF D$="U" THEN GOTO 43
  42 GOTO 45
  43 RAND USR 16514
  44 RAND USR 16588
  45 IF D$="O" THEN GOTO 47
  46 GOTO 49
  47 RAND USR 16514
  48 RAND USR 16567
  49 IF D$="." THEN GOTO 51
  50 GOTO 53
  51 RAND USR 16538
  52 RAND USR 16567
  53 IF D$="N" THEN GOTO 55
  54 GOTO 57
  55 RAND USR 16538
  56 RAND USR 16588
  60 GOTO 20
  70 SAVE "1009%7"
  80 GOTO 5

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

People

No people associated with this content.

Scroll to Top
B

Screen Scrolling Routine

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

This program implements a character-movement or screen-scrolling system driven entirely by machine code routines embedded in the REM statement at line 1. The BASIC shell reads a keypress via INKEY$ and dispatches to one of four machine code entry points (USR 16514, 16538, 16567, 16588) depending on the key pressed, covering eight directions: J, M, I, K for cardinal directions and U, O, ., N for diagonals (combining two cardinal calls). The machine code, stored beginning at address 16514 (0x4082, just inside the REM statement data), performs direct memory operations including LDIR and LDDR block moves, consistent with scrolling a screen region or shifting a sprite/character buffer. The SAVE at line 70 uses an inverse-video character in the filename as an auto-run marker.


Program Analysis

Program Structure

The program has three logical layers:

  1. Machine code store — Line 1 is a REM statement whose body contains raw Z80 opcodes. Because the ZX Spectrum/TS2068 stores REM data verbatim in RAM, the bytes are directly executable starting at the address of the first byte after the REM token.
  2. Input loop — Lines 20–60 form a tight polling loop: INKEY$ is sampled at line 20, then a cascade of IF/GOTO chains dispatches to the appropriate machine code entry point(s).
  3. Housekeeping — Lines 70–80 provide a SAVE and a GOTO 5 (which jumps to LIST 35) for re-entry/display purposes.

Machine Code Entry Points

Line 1 begins at address 16384 (0x4000). The REM token occupies one byte and the two-byte length field two more, placing the first opcode at 0x4003 (16387). However, the BASIC calls target four distinct addresses:

USR AddressHexKey(s)Role (inferred)
165140x4082I, U, OScroll/move up
165380x409AM, ., NScroll/move down
165670x40B7K, ., NScroll/move right
165880x40CCJ, U, NScroll/move left

The REM data is 59 bytes long (the trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C are likely padding or lookup data). The entry points are therefore spread across the REM body and each routine ends with a C9 (RET) opcode.

Z80 Routine Analysis

Disassembling the REM bytes reveals four subroutines that use the Z80 block-move instructions LDIR (ED B0) and LDDR (ED B8) to shift screen memory. Common patterns observed:

  • 2A 0C 40LD HL,(0x400C): loads a pointer from within the REM area itself (self-referential data).
  • 11 21 00LD DE,0x0021 (33 decimal): one character row width on a 32-column display plus one, used as an offset for vertical scrolling.
  • ED B0 / ED B8LDIR/LDDR: bulk copy forward/backward for up/down scroll directions.
  • 01 B5 02LD BC,0x02B5 (693): the byte count, matching the number of bytes in roughly 21.6 character rows — consistent with scrolling most of the display.
  • 36 00 inside a DJNZ loop — LD (HL),0: clears the vacated edge row/column after a scroll.
  • 06 20LD B,0x20 (32): loop counter for clearing 32 columns.
  • 06 16LD B,0x16 (22): loop counter for clearing 22 rows.

Key Mapping and Diagonal Movement

The eight keys map naturally to a numeric-keypad layout:

KeyDirectionRoutines called
IUpUSR 16514
KRightUSR 16567
MDownUSR 16538
JLeftUSR 16588
UUp-LeftUSR 16514 + USR 16588
OUp-RightUSR 16514 + USR 16567
.Down-RightUSR 16538 + USR 16567
NDown-LeftUSR 16538 + USR 16588

Diagonal movement is achieved by sequentially calling two cardinal-direction routines in BASIC rather than implementing combined diagonals in machine code, keeping the MC routines simple and orthogonal.

Notable Techniques

  • REM-as-code store: embedding machine code in a REM line is a standard technique that keeps the code in a known, fixed address and prevents the BASIC editor from interpreting the bytes.
  • Self-referential data pointer: LD HL,(0x400C) reads a word from within the REM statement itself, allowing the routine to find its own working data without hardcoding a separate address.
  • LDIR/LDDR for scrolling: using the Z80 block-copy instructions is the fastest pure-Z80 approach to scrolling a rectangular region of screen memory.
  • DJNZ clear loop: after a scroll, a DJNZ loop with LD (HL),0 efficiently blanks the newly exposed row or column.
  • Line 5 LIST 35: GOTO 5 at line 80 causes the program listing to scroll to line 35, effectively hiding the machine code REM from casual view on restart.
  • INKEY$ polling without PAUSE: line 20 samples the keyboard every BASIC iteration with no delay, giving the fastest possible response at the cost of no key-repeat debounce.

Potential Anomalies

  • Line 57 is referenced by GOTO 57 (line 54) but does not exist. After the cascade of diagonal-key checks, control falls through to GOTO 20 at line 60 — the missing line 57 simply causes BASIC to continue to the next higher line, which is line 60. This is intentional and well-understood behaviour.
  • The trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C at the end of the REM (control codes 28–37) are not reachable as code; they appear to be a lookup table or padding used as data by the routines.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10051 – 10121.

Related Products

Related Articles

Related Content

Image Gallery

Screen Scrolling Routine

Source Code

   1 REM \2A\0C\40\23\E5\11\21\00\19\D1\01\B5\02\ED\B0\EB\06\20\36\00\23\10\FB\C9\2A\10\40\11\43\00\ED\52\E5\11\21\00\ED\52\D1\01\B5\02\ED\B8\EB\06\20\2B\36\00\10\FB\C9\2A\0C\40\06\16\C5\06\20\3E\00\23\4F\7E\71\10\FA\23\C1\10\F1\C9\2A\10\40\11\43\00\ED\52\06\16\C5\06\20\3E\00\2B\4F\7E\71\10\FA\2B\C1\10\F1\C9\1D\1E\1F\20\21\22\23\24\25\1C
   5 LIST 35
  20 LET D$=INKEY$
  25 IF D$="J" THEN RAND USR 16588
  30 IF D$="M" THEN RAND USR 16538
  35 IF D$="I" THEN RAND USR 16514
  40 IF D$="K" THEN RAND USR 16567
  41 IF D$="U" THEN GOTO 43
  42 GOTO 45
  43 RAND USR 16514
  44 RAND USR 16588
  45 IF D$="O" THEN GOTO 47
  46 GOTO 49
  47 RAND USR 16514
  48 RAND USR 16567
  49 IF D$="." THEN GOTO 51
  50 GOTO 53
  51 RAND USR 16538
  52 RAND USR 16567
  53 IF D$="N" THEN GOTO 55
  54 GOTO 57
  55 RAND USR 16538
  56 RAND USR 16588
  60 GOTO 20
  70 SAVE "1009%7"
  80 GOTO 5

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

People

No people associated with this content.

Scroll to Top
\FB\C9

Screen Scrolling Routine

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

This program implements a character-movement or screen-scrolling system driven entirely by machine code routines embedded in the REM statement at line 1. The BASIC shell reads a keypress via INKEY$ and dispatches to one of four machine code entry points (USR 16514, 16538, 16567, 16588) depending on the key pressed, covering eight directions: J, M, I, K for cardinal directions and U, O, ., N for diagonals (combining two cardinal calls). The machine code, stored beginning at address 16514 (0x4082, just inside the REM statement data), performs direct memory operations including LDIR and LDDR block moves, consistent with scrolling a screen region or shifting a sprite/character buffer. The SAVE at line 70 uses an inverse-video character in the filename as an auto-run marker.


Program Analysis

Program Structure

The program has three logical layers:

  1. Machine code store — Line 1 is a REM statement whose body contains raw Z80 opcodes. Because the ZX Spectrum/TS2068 stores REM data verbatim in RAM, the bytes are directly executable starting at the address of the first byte after the REM token.
  2. Input loop — Lines 20–60 form a tight polling loop: INKEY$ is sampled at line 20, then a cascade of IF/GOTO chains dispatches to the appropriate machine code entry point(s).
  3. Housekeeping — Lines 70–80 provide a SAVE and a GOTO 5 (which jumps to LIST 35) for re-entry/display purposes.

Machine Code Entry Points

Line 1 begins at address 16384 (0x4000). The REM token occupies one byte and the two-byte length field two more, placing the first opcode at 0x4003 (16387). However, the BASIC calls target four distinct addresses:

USR AddressHexKey(s)Role (inferred)
165140x4082I, U, OScroll/move up
165380x409AM, ., NScroll/move down
165670x40B7K, ., NScroll/move right
165880x40CCJ, U, NScroll/move left

The REM data is 59 bytes long (the trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C are likely padding or lookup data). The entry points are therefore spread across the REM body and each routine ends with a C9 (RET) opcode.

Z80 Routine Analysis

Disassembling the REM bytes reveals four subroutines that use the Z80 block-move instructions LDIR (ED B0) and LDDR (ED B8) to shift screen memory. Common patterns observed:

  • 2A 0C 40LD HL,(0x400C): loads a pointer from within the REM area itself (self-referential data).
  • 11 21 00LD DE,0x0021 (33 decimal): one character row width on a 32-column display plus one, used as an offset for vertical scrolling.
  • ED B0 / ED B8LDIR/LDDR: bulk copy forward/backward for up/down scroll directions.
  • 01 B5 02LD BC,0x02B5 (693): the byte count, matching the number of bytes in roughly 21.6 character rows — consistent with scrolling most of the display.
  • 36 00 inside a DJNZ loop — LD (HL),0: clears the vacated edge row/column after a scroll.
  • 06 20LD B,0x20 (32): loop counter for clearing 32 columns.
  • 06 16LD B,0x16 (22): loop counter for clearing 22 rows.

Key Mapping and Diagonal Movement

The eight keys map naturally to a numeric-keypad layout:

KeyDirectionRoutines called
IUpUSR 16514
KRightUSR 16567
MDownUSR 16538
JLeftUSR 16588
UUp-LeftUSR 16514 + USR 16588
OUp-RightUSR 16514 + USR 16567
.Down-RightUSR 16538 + USR 16567
NDown-LeftUSR 16538 + USR 16588

Diagonal movement is achieved by sequentially calling two cardinal-direction routines in BASIC rather than implementing combined diagonals in machine code, keeping the MC routines simple and orthogonal.

Notable Techniques

  • REM-as-code store: embedding machine code in a REM line is a standard technique that keeps the code in a known, fixed address and prevents the BASIC editor from interpreting the bytes.
  • Self-referential data pointer: LD HL,(0x400C) reads a word from within the REM statement itself, allowing the routine to find its own working data without hardcoding a separate address.
  • LDIR/LDDR for scrolling: using the Z80 block-copy instructions is the fastest pure-Z80 approach to scrolling a rectangular region of screen memory.
  • DJNZ clear loop: after a scroll, a DJNZ loop with LD (HL),0 efficiently blanks the newly exposed row or column.
  • Line 5 LIST 35: GOTO 5 at line 80 causes the program listing to scroll to line 35, effectively hiding the machine code REM from casual view on restart.
  • INKEY$ polling without PAUSE: line 20 samples the keyboard every BASIC iteration with no delay, giving the fastest possible response at the cost of no key-repeat debounce.

Potential Anomalies

  • Line 57 is referenced by GOTO 57 (line 54) but does not exist. After the cascade of diagonal-key checks, control falls through to GOTO 20 at line 60 — the missing line 57 simply causes BASIC to continue to the next higher line, which is line 60. This is intentional and well-understood behaviour.
  • The trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C at the end of the REM (control codes 28–37) are not reachable as code; they appear to be a lookup table or padding used as data by the routines.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10051 – 10121.

Related Products

Related Articles

Related Content

Image Gallery

Screen Scrolling Routine

Source Code

   1 REM \2A\0C\40\23\E5\11\21\00\19\D1\01\B5\02\ED\B0\EB\06\20\36\00\23\10\FB\C9\2A\10\40\11\43\00\ED\52\E5\11\21\00\ED\52\D1\01\B5\02\ED\B8\EB\06\20\2B\36\00\10\FB\C9\2A\0C\40\06\16\C5\06\20\3E\00\23\4F\7E\71\10\FA\23\C1\10\F1\C9\2A\10\40\11\43\00\ED\52\06\16\C5\06\20\3E\00\2B\4F\7E\71\10\FA\2B\C1\10\F1\C9\1D\1E\1F\20\21\22\23\24\25\1C
   5 LIST 35
  20 LET D$=INKEY$
  25 IF D$="J" THEN RAND USR 16588
  30 IF D$="M" THEN RAND USR 16538
  35 IF D$="I" THEN RAND USR 16514
  40 IF D$="K" THEN RAND USR 16567
  41 IF D$="U" THEN GOTO 43
  42 GOTO 45
  43 RAND USR 16514
  44 RAND USR 16588
  45 IF D$="O" THEN GOTO 47
  46 GOTO 49
  47 RAND USR 16514
  48 RAND USR 16567
  49 IF D$="." THEN GOTO 51
  50 GOTO 53
  51 RAND USR 16538
  52 RAND USR 16567
  53 IF D$="N" THEN GOTO 55
  54 GOTO 57
  55 RAND USR 16538
  56 RAND USR 16588
  60 GOTO 20
  70 SAVE "1009%7"
  80 GOTO 5

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

People

No people associated with this content.

Scroll to Top
A

Screen Scrolling Routine

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

This program implements a character-movement or screen-scrolling system driven entirely by machine code routines embedded in the REM statement at line 1. The BASIC shell reads a keypress via INKEY$ and dispatches to one of four machine code entry points (USR 16514, 16538, 16567, 16588) depending on the key pressed, covering eight directions: J, M, I, K for cardinal directions and U, O, ., N for diagonals (combining two cardinal calls). The machine code, stored beginning at address 16514 (0x4082, just inside the REM statement data), performs direct memory operations including LDIR and LDDR block moves, consistent with scrolling a screen region or shifting a sprite/character buffer. The SAVE at line 70 uses an inverse-video character in the filename as an auto-run marker.


Program Analysis

Program Structure

The program has three logical layers:

  1. Machine code store — Line 1 is a REM statement whose body contains raw Z80 opcodes. Because the ZX Spectrum/TS2068 stores REM data verbatim in RAM, the bytes are directly executable starting at the address of the first byte after the REM token.
  2. Input loop — Lines 20–60 form a tight polling loop: INKEY$ is sampled at line 20, then a cascade of IF/GOTO chains dispatches to the appropriate machine code entry point(s).
  3. Housekeeping — Lines 70–80 provide a SAVE and a GOTO 5 (which jumps to LIST 35) for re-entry/display purposes.

Machine Code Entry Points

Line 1 begins at address 16384 (0x4000). The REM token occupies one byte and the two-byte length field two more, placing the first opcode at 0x4003 (16387). However, the BASIC calls target four distinct addresses:

USR AddressHexKey(s)Role (inferred)
165140x4082I, U, OScroll/move up
165380x409AM, ., NScroll/move down
165670x40B7K, ., NScroll/move right
165880x40CCJ, U, NScroll/move left

The REM data is 59 bytes long (the trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C are likely padding or lookup data). The entry points are therefore spread across the REM body and each routine ends with a C9 (RET) opcode.

Z80 Routine Analysis

Disassembling the REM bytes reveals four subroutines that use the Z80 block-move instructions LDIR (ED B0) and LDDR (ED B8) to shift screen memory. Common patterns observed:

  • 2A 0C 40LD HL,(0x400C): loads a pointer from within the REM area itself (self-referential data).
  • 11 21 00LD DE,0x0021 (33 decimal): one character row width on a 32-column display plus one, used as an offset for vertical scrolling.
  • ED B0 / ED B8LDIR/LDDR: bulk copy forward/backward for up/down scroll directions.
  • 01 B5 02LD BC,0x02B5 (693): the byte count, matching the number of bytes in roughly 21.6 character rows — consistent with scrolling most of the display.
  • 36 00 inside a DJNZ loop — LD (HL),0: clears the vacated edge row/column after a scroll.
  • 06 20LD B,0x20 (32): loop counter for clearing 32 columns.
  • 06 16LD B,0x16 (22): loop counter for clearing 22 rows.

Key Mapping and Diagonal Movement

The eight keys map naturally to a numeric-keypad layout:

KeyDirectionRoutines called
IUpUSR 16514
KRightUSR 16567
MDownUSR 16538
JLeftUSR 16588
UUp-LeftUSR 16514 + USR 16588
OUp-RightUSR 16514 + USR 16567
.Down-RightUSR 16538 + USR 16567
NDown-LeftUSR 16538 + USR 16588

Diagonal movement is achieved by sequentially calling two cardinal-direction routines in BASIC rather than implementing combined diagonals in machine code, keeping the MC routines simple and orthogonal.

Notable Techniques

  • REM-as-code store: embedding machine code in a REM line is a standard technique that keeps the code in a known, fixed address and prevents the BASIC editor from interpreting the bytes.
  • Self-referential data pointer: LD HL,(0x400C) reads a word from within the REM statement itself, allowing the routine to find its own working data without hardcoding a separate address.
  • LDIR/LDDR for scrolling: using the Z80 block-copy instructions is the fastest pure-Z80 approach to scrolling a rectangular region of screen memory.
  • DJNZ clear loop: after a scroll, a DJNZ loop with LD (HL),0 efficiently blanks the newly exposed row or column.
  • Line 5 LIST 35: GOTO 5 at line 80 causes the program listing to scroll to line 35, effectively hiding the machine code REM from casual view on restart.
  • INKEY$ polling without PAUSE: line 20 samples the keyboard every BASIC iteration with no delay, giving the fastest possible response at the cost of no key-repeat debounce.

Potential Anomalies

  • Line 57 is referenced by GOTO 57 (line 54) but does not exist. After the cascade of diagonal-key checks, control falls through to GOTO 20 at line 60 — the missing line 57 simply causes BASIC to continue to the next higher line, which is line 60. This is intentional and well-understood behaviour.
  • The trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C at the end of the REM (control codes 28–37) are not reachable as code; they appear to be a lookup table or padding used as data by the routines.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10051 – 10121.

Related Products

Related Articles

Related Content

Image Gallery

Screen Scrolling Routine

Source Code

   1 REM \2A\0C\40\23\E5\11\21\00\19\D1\01\B5\02\ED\B0\EB\06\20\36\00\23\10\FB\C9\2A\10\40\11\43\00\ED\52\E5\11\21\00\ED\52\D1\01\B5\02\ED\B8\EB\06\20\2B\36\00\10\FB\C9\2A\0C\40\06\16\C5\06\20\3E\00\23\4F\7E\71\10\FA\23\C1\10\F1\C9\2A\10\40\11\43\00\ED\52\06\16\C5\06\20\3E\00\2B\4F\7E\71\10\FA\2B\C1\10\F1\C9\1D\1E\1F\20\21\22\23\24\25\1C
   5 LIST 35
  20 LET D$=INKEY$
  25 IF D$="J" THEN RAND USR 16588
  30 IF D$="M" THEN RAND USR 16538
  35 IF D$="I" THEN RAND USR 16514
  40 IF D$="K" THEN RAND USR 16567
  41 IF D$="U" THEN GOTO 43
  42 GOTO 45
  43 RAND USR 16514
  44 RAND USR 16588
  45 IF D$="O" THEN GOTO 47
  46 GOTO 49
  47 RAND USR 16514
  48 RAND USR 16567
  49 IF D$="." THEN GOTO 51
  50 GOTO 53
  51 RAND USR 16538
  52 RAND USR 16567
  53 IF D$="N" THEN GOTO 55
  54 GOTO 57
  55 RAND USR 16538
  56 RAND USR 16588
  60 GOTO 20
  70 SAVE "1009%7"
  80 GOTO 5

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

People

No people associated with this content.

Scroll to Top
C\C5E

Screen Scrolling Routine

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

This program implements a character-movement or screen-scrolling system driven entirely by machine code routines embedded in the REM statement at line 1. The BASIC shell reads a keypress via INKEY$ and dispatches to one of four machine code entry points (USR 16514, 16538, 16567, 16588) depending on the key pressed, covering eight directions: J, M, I, K for cardinal directions and U, O, ., N for diagonals (combining two cardinal calls). The machine code, stored beginning at address 16514 (0x4082, just inside the REM statement data), performs direct memory operations including LDIR and LDDR block moves, consistent with scrolling a screen region or shifting a sprite/character buffer. The SAVE at line 70 uses an inverse-video character in the filename as an auto-run marker.


Program Analysis

Program Structure

The program has three logical layers:

  1. Machine code store — Line 1 is a REM statement whose body contains raw Z80 opcodes. Because the ZX Spectrum/TS2068 stores REM data verbatim in RAM, the bytes are directly executable starting at the address of the first byte after the REM token.
  2. Input loop — Lines 20–60 form a tight polling loop: INKEY$ is sampled at line 20, then a cascade of IF/GOTO chains dispatches to the appropriate machine code entry point(s).
  3. Housekeeping — Lines 70–80 provide a SAVE and a GOTO 5 (which jumps to LIST 35) for re-entry/display purposes.

Machine Code Entry Points

Line 1 begins at address 16384 (0x4000). The REM token occupies one byte and the two-byte length field two more, placing the first opcode at 0x4003 (16387). However, the BASIC calls target four distinct addresses:

USR AddressHexKey(s)Role (inferred)
165140x4082I, U, OScroll/move up
165380x409AM, ., NScroll/move down
165670x40B7K, ., NScroll/move right
165880x40CCJ, U, NScroll/move left

The REM data is 59 bytes long (the trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C are likely padding or lookup data). The entry points are therefore spread across the REM body and each routine ends with a C9 (RET) opcode.

Z80 Routine Analysis

Disassembling the REM bytes reveals four subroutines that use the Z80 block-move instructions LDIR (ED B0) and LDDR (ED B8) to shift screen memory. Common patterns observed:

  • 2A 0C 40LD HL,(0x400C): loads a pointer from within the REM area itself (self-referential data).
  • 11 21 00LD DE,0x0021 (33 decimal): one character row width on a 32-column display plus one, used as an offset for vertical scrolling.
  • ED B0 / ED B8LDIR/LDDR: bulk copy forward/backward for up/down scroll directions.
  • 01 B5 02LD BC,0x02B5 (693): the byte count, matching the number of bytes in roughly 21.6 character rows — consistent with scrolling most of the display.
  • 36 00 inside a DJNZ loop — LD (HL),0: clears the vacated edge row/column after a scroll.
  • 06 20LD B,0x20 (32): loop counter for clearing 32 columns.
  • 06 16LD B,0x16 (22): loop counter for clearing 22 rows.

Key Mapping and Diagonal Movement

The eight keys map naturally to a numeric-keypad layout:

KeyDirectionRoutines called
IUpUSR 16514
KRightUSR 16567
MDownUSR 16538
JLeftUSR 16588
UUp-LeftUSR 16514 + USR 16588
OUp-RightUSR 16514 + USR 16567
.Down-RightUSR 16538 + USR 16567
NDown-LeftUSR 16538 + USR 16588

Diagonal movement is achieved by sequentially calling two cardinal-direction routines in BASIC rather than implementing combined diagonals in machine code, keeping the MC routines simple and orthogonal.

Notable Techniques

  • REM-as-code store: embedding machine code in a REM line is a standard technique that keeps the code in a known, fixed address and prevents the BASIC editor from interpreting the bytes.
  • Self-referential data pointer: LD HL,(0x400C) reads a word from within the REM statement itself, allowing the routine to find its own working data without hardcoding a separate address.
  • LDIR/LDDR for scrolling: using the Z80 block-copy instructions is the fastest pure-Z80 approach to scrolling a rectangular region of screen memory.
  • DJNZ clear loop: after a scroll, a DJNZ loop with LD (HL),0 efficiently blanks the newly exposed row or column.
  • Line 5 LIST 35: GOTO 5 at line 80 causes the program listing to scroll to line 35, effectively hiding the machine code REM from casual view on restart.
  • INKEY$ polling without PAUSE: line 20 samples the keyboard every BASIC iteration with no delay, giving the fastest possible response at the cost of no key-repeat debounce.

Potential Anomalies

  • Line 57 is referenced by GOTO 57 (line 54) but does not exist. After the cascade of diagonal-key checks, control falls through to GOTO 20 at line 60 — the missing line 57 simply causes BASIC to continue to the next higher line, which is line 60. This is intentional and well-understood behaviour.
  • The trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C at the end of the REM (control codes 28–37) are not reachable as code; they appear to be a lookup table or padding used as data by the routines.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10051 – 10121.

Related Products

Related Articles

Related Content

Image Gallery

Screen Scrolling Routine

Source Code

   1 REM \2A\0C\40\23\E5\11\21\00\19\D1\01\B5\02\ED\B0\EB\06\20\36\00\23\10\FB\C9\2A\10\40\11\43\00\ED\52\E5\11\21\00\ED\52\D1\01\B5\02\ED\B8\EB\06\20\2B\36\00\10\FB\C9\2A\0C\40\06\16\C5\06\20\3E\00\23\4F\7E\71\10\FA\23\C1\10\F1\C9\2A\10\40\11\43\00\ED\52\06\16\C5\06\20\3E\00\2B\4F\7E\71\10\FA\2B\C1\10\F1\C9\1D\1E\1F\20\21\22\23\24\25\1C
   5 LIST 35
  20 LET D$=INKEY$
  25 IF D$="J" THEN RAND USR 16588
  30 IF D$="M" THEN RAND USR 16538
  35 IF D$="I" THEN RAND USR 16514
  40 IF D$="K" THEN RAND USR 16567
  41 IF D$="U" THEN GOTO 43
  42 GOTO 45
  43 RAND USR 16514
  44 RAND USR 16588
  45 IF D$="O" THEN GOTO 47
  46 GOTO 49
  47 RAND USR 16514
  48 RAND USR 16567
  49 IF D$="." THEN GOTO 51
  50 GOTO 53
  51 RAND USR 16538
  52 RAND USR 16567
  53 IF D$="N" THEN GOTO 55
  54 GOTO 57
  55 RAND USR 16538
  56 RAND USR 16588
  60 GOTO 20
  70 SAVE "1009%7"
  80 GOTO 5

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

People

No people associated with this content.

Scroll to Top
FE\FA\C1\F1\C9

Screen Scrolling Routine

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

This program implements a character-movement or screen-scrolling system driven entirely by machine code routines embedded in the REM statement at line 1. The BASIC shell reads a keypress via INKEY$ and dispatches to one of four machine code entry points (USR 16514, 16538, 16567, 16588) depending on the key pressed, covering eight directions: J, M, I, K for cardinal directions and U, O, ., N for diagonals (combining two cardinal calls). The machine code, stored beginning at address 16514 (0x4082, just inside the REM statement data), performs direct memory operations including LDIR and LDDR block moves, consistent with scrolling a screen region or shifting a sprite/character buffer. The SAVE at line 70 uses an inverse-video character in the filename as an auto-run marker.


Program Analysis

Program Structure

The program has three logical layers:

  1. Machine code store — Line 1 is a REM statement whose body contains raw Z80 opcodes. Because the ZX Spectrum/TS2068 stores REM data verbatim in RAM, the bytes are directly executable starting at the address of the first byte after the REM token.
  2. Input loop — Lines 20–60 form a tight polling loop: INKEY$ is sampled at line 20, then a cascade of IF/GOTO chains dispatches to the appropriate machine code entry point(s).
  3. Housekeeping — Lines 70–80 provide a SAVE and a GOTO 5 (which jumps to LIST 35) for re-entry/display purposes.

Machine Code Entry Points

Line 1 begins at address 16384 (0x4000). The REM token occupies one byte and the two-byte length field two more, placing the first opcode at 0x4003 (16387). However, the BASIC calls target four distinct addresses:

USR AddressHexKey(s)Role (inferred)
165140x4082I, U, OScroll/move up
165380x409AM, ., NScroll/move down
165670x40B7K, ., NScroll/move right
165880x40CCJ, U, NScroll/move left

The REM data is 59 bytes long (the trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C are likely padding or lookup data). The entry points are therefore spread across the REM body and each routine ends with a C9 (RET) opcode.

Z80 Routine Analysis

Disassembling the REM bytes reveals four subroutines that use the Z80 block-move instructions LDIR (ED B0) and LDDR (ED B8) to shift screen memory. Common patterns observed:

  • 2A 0C 40LD HL,(0x400C): loads a pointer from within the REM area itself (self-referential data).
  • 11 21 00LD DE,0x0021 (33 decimal): one character row width on a 32-column display plus one, used as an offset for vertical scrolling.
  • ED B0 / ED B8LDIR/LDDR: bulk copy forward/backward for up/down scroll directions.
  • 01 B5 02LD BC,0x02B5 (693): the byte count, matching the number of bytes in roughly 21.6 character rows — consistent with scrolling most of the display.
  • 36 00 inside a DJNZ loop — LD (HL),0: clears the vacated edge row/column after a scroll.
  • 06 20LD B,0x20 (32): loop counter for clearing 32 columns.
  • 06 16LD B,0x16 (22): loop counter for clearing 22 rows.

Key Mapping and Diagonal Movement

The eight keys map naturally to a numeric-keypad layout:

KeyDirectionRoutines called
IUpUSR 16514
KRightUSR 16567
MDownUSR 16538
JLeftUSR 16588
UUp-LeftUSR 16514 + USR 16588
OUp-RightUSR 16514 + USR 16567
.Down-RightUSR 16538 + USR 16567
NDown-LeftUSR 16538 + USR 16588

Diagonal movement is achieved by sequentially calling two cardinal-direction routines in BASIC rather than implementing combined diagonals in machine code, keeping the MC routines simple and orthogonal.

Notable Techniques

  • REM-as-code store: embedding machine code in a REM line is a standard technique that keeps the code in a known, fixed address and prevents the BASIC editor from interpreting the bytes.
  • Self-referential data pointer: LD HL,(0x400C) reads a word from within the REM statement itself, allowing the routine to find its own working data without hardcoding a separate address.
  • LDIR/LDDR for scrolling: using the Z80 block-copy instructions is the fastest pure-Z80 approach to scrolling a rectangular region of screen memory.
  • DJNZ clear loop: after a scroll, a DJNZ loop with LD (HL),0 efficiently blanks the newly exposed row or column.
  • Line 5 LIST 35: GOTO 5 at line 80 causes the program listing to scroll to line 35, effectively hiding the machine code REM from casual view on restart.
  • INKEY$ polling without PAUSE: line 20 samples the keyboard every BASIC iteration with no delay, giving the fastest possible response at the cost of no key-repeat debounce.

Potential Anomalies

  • Line 57 is referenced by GOTO 57 (line 54) but does not exist. After the cascade of diagonal-key checks, control falls through to GOTO 20 at line 60 — the missing line 57 simply causes BASIC to continue to the next higher line, which is line 60. This is intentional and well-understood behaviour.
  • The trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C at the end of the REM (control codes 28–37) are not reachable as code; they appear to be a lookup table or padding used as data by the routines.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10051 – 10121.

Related Products

Related Articles

Related Content

Image Gallery

Screen Scrolling Routine

Source Code

   1 REM \2A\0C\40\23\E5\11\21\00\19\D1\01\B5\02\ED\B0\EB\06\20\36\00\23\10\FB\C9\2A\10\40\11\43\00\ED\52\E5\11\21\00\ED\52\D1\01\B5\02\ED\B8\EB\06\20\2B\36\00\10\FB\C9\2A\0C\40\06\16\C5\06\20\3E\00\23\4F\7E\71\10\FA\23\C1\10\F1\C9\2A\10\40\11\43\00\ED\52\06\16\C5\06\20\3E\00\2B\4F\7E\71\10\FA\2B\C1\10\F1\C9\1D\1E\1F\20\21\22\23\24\25\1C
   5 LIST 35
  20 LET D$=INKEY$
  25 IF D$="J" THEN RAND USR 16588
  30 IF D$="M" THEN RAND USR 16538
  35 IF D$="I" THEN RAND USR 16514
  40 IF D$="K" THEN RAND USR 16567
  41 IF D$="U" THEN GOTO 43
  42 GOTO 45
  43 RAND USR 16514
  44 RAND USR 16588
  45 IF D$="O" THEN GOTO 47
  46 GOTO 49
  47 RAND USR 16514
  48 RAND USR 16567
  49 IF D$="." THEN GOTO 51
  50 GOTO 53
  51 RAND USR 16538
  52 RAND USR 16567
  53 IF D$="N" THEN GOTO 55
  54 GOTO 57
  55 RAND USR 16538
  56 RAND USR 16588
  60 GOTO 20
  70 SAVE "1009%7"
  80 GOTO 5

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

People

No people associated with this content.

Scroll to Top
A

Screen Scrolling Routine

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

This program implements a character-movement or screen-scrolling system driven entirely by machine code routines embedded in the REM statement at line 1. The BASIC shell reads a keypress via INKEY$ and dispatches to one of four machine code entry points (USR 16514, 16538, 16567, 16588) depending on the key pressed, covering eight directions: J, M, I, K for cardinal directions and U, O, ., N for diagonals (combining two cardinal calls). The machine code, stored beginning at address 16514 (0x4082, just inside the REM statement data), performs direct memory operations including LDIR and LDDR block moves, consistent with scrolling a screen region or shifting a sprite/character buffer. The SAVE at line 70 uses an inverse-video character in the filename as an auto-run marker.


Program Analysis

Program Structure

The program has three logical layers:

  1. Machine code store — Line 1 is a REM statement whose body contains raw Z80 opcodes. Because the ZX Spectrum/TS2068 stores REM data verbatim in RAM, the bytes are directly executable starting at the address of the first byte after the REM token.
  2. Input loop — Lines 20–60 form a tight polling loop: INKEY$ is sampled at line 20, then a cascade of IF/GOTO chains dispatches to the appropriate machine code entry point(s).
  3. Housekeeping — Lines 70–80 provide a SAVE and a GOTO 5 (which jumps to LIST 35) for re-entry/display purposes.

Machine Code Entry Points

Line 1 begins at address 16384 (0x4000). The REM token occupies one byte and the two-byte length field two more, placing the first opcode at 0x4003 (16387). However, the BASIC calls target four distinct addresses:

USR AddressHexKey(s)Role (inferred)
165140x4082I, U, OScroll/move up
165380x409AM, ., NScroll/move down
165670x40B7K, ., NScroll/move right
165880x40CCJ, U, NScroll/move left

The REM data is 59 bytes long (the trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C are likely padding or lookup data). The entry points are therefore spread across the REM body and each routine ends with a C9 (RET) opcode.

Z80 Routine Analysis

Disassembling the REM bytes reveals four subroutines that use the Z80 block-move instructions LDIR (ED B0) and LDDR (ED B8) to shift screen memory. Common patterns observed:

  • 2A 0C 40LD HL,(0x400C): loads a pointer from within the REM area itself (self-referential data).
  • 11 21 00LD DE,0x0021 (33 decimal): one character row width on a 32-column display plus one, used as an offset for vertical scrolling.
  • ED B0 / ED B8LDIR/LDDR: bulk copy forward/backward for up/down scroll directions.
  • 01 B5 02LD BC,0x02B5 (693): the byte count, matching the number of bytes in roughly 21.6 character rows — consistent with scrolling most of the display.
  • 36 00 inside a DJNZ loop — LD (HL),0: clears the vacated edge row/column after a scroll.
  • 06 20LD B,0x20 (32): loop counter for clearing 32 columns.
  • 06 16LD B,0x16 (22): loop counter for clearing 22 rows.

Key Mapping and Diagonal Movement

The eight keys map naturally to a numeric-keypad layout:

KeyDirectionRoutines called
IUpUSR 16514
KRightUSR 16567
MDownUSR 16538
JLeftUSR 16588
UUp-LeftUSR 16514 + USR 16588
OUp-RightUSR 16514 + USR 16567
.Down-RightUSR 16538 + USR 16567
NDown-LeftUSR 16538 + USR 16588

Diagonal movement is achieved by sequentially calling two cardinal-direction routines in BASIC rather than implementing combined diagonals in machine code, keeping the MC routines simple and orthogonal.

Notable Techniques

  • REM-as-code store: embedding machine code in a REM line is a standard technique that keeps the code in a known, fixed address and prevents the BASIC editor from interpreting the bytes.
  • Self-referential data pointer: LD HL,(0x400C) reads a word from within the REM statement itself, allowing the routine to find its own working data without hardcoding a separate address.
  • LDIR/LDDR for scrolling: using the Z80 block-copy instructions is the fastest pure-Z80 approach to scrolling a rectangular region of screen memory.
  • DJNZ clear loop: after a scroll, a DJNZ loop with LD (HL),0 efficiently blanks the newly exposed row or column.
  • Line 5 LIST 35: GOTO 5 at line 80 causes the program listing to scroll to line 35, effectively hiding the machine code REM from casual view on restart.
  • INKEY$ polling without PAUSE: line 20 samples the keyboard every BASIC iteration with no delay, giving the fastest possible response at the cost of no key-repeat debounce.

Potential Anomalies

  • Line 57 is referenced by GOTO 57 (line 54) but does not exist. After the cascade of diagonal-key checks, control falls through to GOTO 20 at line 60 — the missing line 57 simply causes BASIC to continue to the next higher line, which is line 60. This is intentional and well-understood behaviour.
  • The trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C at the end of the REM (control codes 28–37) are not reachable as code; they appear to be a lookup table or padding used as data by the routines.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10051 – 10121.

Related Products

Related Articles

Related Content

Image Gallery

Screen Scrolling Routine

Source Code

   1 REM \2A\0C\40\23\E5\11\21\00\19\D1\01\B5\02\ED\B0\EB\06\20\36\00\23\10\FB\C9\2A\10\40\11\43\00\ED\52\E5\11\21\00\ED\52\D1\01\B5\02\ED\B8\EB\06\20\2B\36\00\10\FB\C9\2A\0C\40\06\16\C5\06\20\3E\00\23\4F\7E\71\10\FA\23\C1\10\F1\C9\2A\10\40\11\43\00\ED\52\06\16\C5\06\20\3E\00\2B\4F\7E\71\10\FA\2B\C1\10\F1\C9\1D\1E\1F\20\21\22\23\24\25\1C
   5 LIST 35
  20 LET D$=INKEY$
  25 IF D$="J" THEN RAND USR 16588
  30 IF D$="M" THEN RAND USR 16538
  35 IF D$="I" THEN RAND USR 16514
  40 IF D$="K" THEN RAND USR 16567
  41 IF D$="U" THEN GOTO 43
  42 GOTO 45
  43 RAND USR 16514
  44 RAND USR 16588
  45 IF D$="O" THEN GOTO 47
  46 GOTO 49
  47 RAND USR 16514
  48 RAND USR 16567
  49 IF D$="." THEN GOTO 51
  50 GOTO 53
  51 RAND USR 16538
  52 RAND USR 16567
  53 IF D$="N" THEN GOTO 55
  54 GOTO 57
  55 RAND USR 16538
  56 RAND USR 16588
  60 GOTO 20
  70 SAVE "1009%7"
  80 GOTO 5

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

People

No people associated with this content.

Scroll to Top
\ED\C5E

Screen Scrolling Routine

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

This program implements a character-movement or screen-scrolling system driven entirely by machine code routines embedded in the REM statement at line 1. The BASIC shell reads a keypress via INKEY$ and dispatches to one of four machine code entry points (USR 16514, 16538, 16567, 16588) depending on the key pressed, covering eight directions: J, M, I, K for cardinal directions and U, O, ., N for diagonals (combining two cardinal calls). The machine code, stored beginning at address 16514 (0x4082, just inside the REM statement data), performs direct memory operations including LDIR and LDDR block moves, consistent with scrolling a screen region or shifting a sprite/character buffer. The SAVE at line 70 uses an inverse-video character in the filename as an auto-run marker.


Program Analysis

Program Structure

The program has three logical layers:

  1. Machine code store — Line 1 is a REM statement whose body contains raw Z80 opcodes. Because the ZX Spectrum/TS2068 stores REM data verbatim in RAM, the bytes are directly executable starting at the address of the first byte after the REM token.
  2. Input loop — Lines 20–60 form a tight polling loop: INKEY$ is sampled at line 20, then a cascade of IF/GOTO chains dispatches to the appropriate machine code entry point(s).
  3. Housekeeping — Lines 70–80 provide a SAVE and a GOTO 5 (which jumps to LIST 35) for re-entry/display purposes.

Machine Code Entry Points

Line 1 begins at address 16384 (0x4000). The REM token occupies one byte and the two-byte length field two more, placing the first opcode at 0x4003 (16387). However, the BASIC calls target four distinct addresses:

USR AddressHexKey(s)Role (inferred)
165140x4082I, U, OScroll/move up
165380x409AM, ., NScroll/move down
165670x40B7K, ., NScroll/move right
165880x40CCJ, U, NScroll/move left

The REM data is 59 bytes long (the trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C are likely padding or lookup data). The entry points are therefore spread across the REM body and each routine ends with a C9 (RET) opcode.

Z80 Routine Analysis

Disassembling the REM bytes reveals four subroutines that use the Z80 block-move instructions LDIR (ED B0) and LDDR (ED B8) to shift screen memory. Common patterns observed:

  • 2A 0C 40LD HL,(0x400C): loads a pointer from within the REM area itself (self-referential data).
  • 11 21 00LD DE,0x0021 (33 decimal): one character row width on a 32-column display plus one, used as an offset for vertical scrolling.
  • ED B0 / ED B8LDIR/LDDR: bulk copy forward/backward for up/down scroll directions.
  • 01 B5 02LD BC,0x02B5 (693): the byte count, matching the number of bytes in roughly 21.6 character rows — consistent with scrolling most of the display.
  • 36 00 inside a DJNZ loop — LD (HL),0: clears the vacated edge row/column after a scroll.
  • 06 20LD B,0x20 (32): loop counter for clearing 32 columns.
  • 06 16LD B,0x16 (22): loop counter for clearing 22 rows.

Key Mapping and Diagonal Movement

The eight keys map naturally to a numeric-keypad layout:

KeyDirectionRoutines called
IUpUSR 16514
KRightUSR 16567
MDownUSR 16538
JLeftUSR 16588
UUp-LeftUSR 16514 + USR 16588
OUp-RightUSR 16514 + USR 16567
.Down-RightUSR 16538 + USR 16567
NDown-LeftUSR 16538 + USR 16588

Diagonal movement is achieved by sequentially calling two cardinal-direction routines in BASIC rather than implementing combined diagonals in machine code, keeping the MC routines simple and orthogonal.

Notable Techniques

  • REM-as-code store: embedding machine code in a REM line is a standard technique that keeps the code in a known, fixed address and prevents the BASIC editor from interpreting the bytes.
  • Self-referential data pointer: LD HL,(0x400C) reads a word from within the REM statement itself, allowing the routine to find its own working data without hardcoding a separate address.
  • LDIR/LDDR for scrolling: using the Z80 block-copy instructions is the fastest pure-Z80 approach to scrolling a rectangular region of screen memory.
  • DJNZ clear loop: after a scroll, a DJNZ loop with LD (HL),0 efficiently blanks the newly exposed row or column.
  • Line 5 LIST 35: GOTO 5 at line 80 causes the program listing to scroll to line 35, effectively hiding the machine code REM from casual view on restart.
  • INKEY$ polling without PAUSE: line 20 samples the keyboard every BASIC iteration with no delay, giving the fastest possible response at the cost of no key-repeat debounce.

Potential Anomalies

  • Line 57 is referenced by GOTO 57 (line 54) but does not exist. After the cascade of diagonal-key checks, control falls through to GOTO 20 at line 60 — the missing line 57 simply causes BASIC to continue to the next higher line, which is line 60. This is intentional and well-understood behaviour.
  • The trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C at the end of the REM (control codes 28–37) are not reachable as code; they appear to be a lookup table or padding used as data by the routines.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10051 – 10121.

Related Products

Related Articles

Related Content

Image Gallery

Screen Scrolling Routine

Source Code

   1 REM \2A\0C\40\23\E5\11\21\00\19\D1\01\B5\02\ED\B0\EB\06\20\36\00\23\10\FB\C9\2A\10\40\11\43\00\ED\52\E5\11\21\00\ED\52\D1\01\B5\02\ED\B8\EB\06\20\2B\36\00\10\FB\C9\2A\0C\40\06\16\C5\06\20\3E\00\23\4F\7E\71\10\FA\23\C1\10\F1\C9\2A\10\40\11\43\00\ED\52\06\16\C5\06\20\3E\00\2B\4F\7E\71\10\FA\2B\C1\10\F1\C9\1D\1E\1F\20\21\22\23\24\25\1C
   5 LIST 35
  20 LET D$=INKEY$
  25 IF D$="J" THEN RAND USR 16588
  30 IF D$="M" THEN RAND USR 16538
  35 IF D$="I" THEN RAND USR 16514
  40 IF D$="K" THEN RAND USR 16567
  41 IF D$="U" THEN GOTO 43
  42 GOTO 45
  43 RAND USR 16514
  44 RAND USR 16588
  45 IF D$="O" THEN GOTO 47
  46 GOTO 49
  47 RAND USR 16514
  48 RAND USR 16567
  49 IF D$="." THEN GOTO 51
  50 GOTO 53
  51 RAND USR 16538
  52 RAND USR 16567
  53 IF D$="N" THEN GOTO 55
  54 GOTO 57
  55 RAND USR 16538
  56 RAND USR 16588
  60 GOTO 20
  70 SAVE "1009%7"
  80 GOTO 5

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

People

No people associated with this content.

Scroll to Top

Screen Scrolling Routine

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

This program implements a character-movement or screen-scrolling system driven entirely by machine code routines embedded in the REM statement at line 1. The BASIC shell reads a keypress via INKEY$ and dispatches to one of four machine code entry points (USR 16514, 16538, 16567, 16588) depending on the key pressed, covering eight directions: J, M, I, K for cardinal directions and U, O, ., N for diagonals (combining two cardinal calls). The machine code, stored beginning at address 16514 (0x4082, just inside the REM statement data), performs direct memory operations including LDIR and LDDR block moves, consistent with scrolling a screen region or shifting a sprite/character buffer. The SAVE at line 70 uses an inverse-video character in the filename as an auto-run marker.


Program Analysis

Program Structure

The program has three logical layers:

  1. Machine code store — Line 1 is a REM statement whose body contains raw Z80 opcodes. Because the ZX Spectrum/TS2068 stores REM data verbatim in RAM, the bytes are directly executable starting at the address of the first byte after the REM token.
  2. Input loop — Lines 20–60 form a tight polling loop: INKEY$ is sampled at line 20, then a cascade of IF/GOTO chains dispatches to the appropriate machine code entry point(s).
  3. Housekeeping — Lines 70–80 provide a SAVE and a GOTO 5 (which jumps to LIST 35) for re-entry/display purposes.

Machine Code Entry Points

Line 1 begins at address 16384 (0x4000). The REM token occupies one byte and the two-byte length field two more, placing the first opcode at 0x4003 (16387). However, the BASIC calls target four distinct addresses:

USR AddressHexKey(s)Role (inferred)
165140x4082I, U, OScroll/move up
165380x409AM, ., NScroll/move down
165670x40B7K, ., NScroll/move right
165880x40CCJ, U, NScroll/move left

The REM data is 59 bytes long (the trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C are likely padding or lookup data). The entry points are therefore spread across the REM body and each routine ends with a C9 (RET) opcode.

Z80 Routine Analysis

Disassembling the REM bytes reveals four subroutines that use the Z80 block-move instructions LDIR (ED B0) and LDDR (ED B8) to shift screen memory. Common patterns observed:

  • 2A 0C 40LD HL,(0x400C): loads a pointer from within the REM area itself (self-referential data).
  • 11 21 00LD DE,0x0021 (33 decimal): one character row width on a 32-column display plus one, used as an offset for vertical scrolling.
  • ED B0 / ED B8LDIR/LDDR: bulk copy forward/backward for up/down scroll directions.
  • 01 B5 02LD BC,0x02B5 (693): the byte count, matching the number of bytes in roughly 21.6 character rows — consistent with scrolling most of the display.
  • 36 00 inside a DJNZ loop — LD (HL),0: clears the vacated edge row/column after a scroll.
  • 06 20LD B,0x20 (32): loop counter for clearing 32 columns.
  • 06 16LD B,0x16 (22): loop counter for clearing 22 rows.

Key Mapping and Diagonal Movement

The eight keys map naturally to a numeric-keypad layout:

KeyDirectionRoutines called
IUpUSR 16514
KRightUSR 16567
MDownUSR 16538
JLeftUSR 16588
UUp-LeftUSR 16514 + USR 16588
OUp-RightUSR 16514 + USR 16567
.Down-RightUSR 16538 + USR 16567
NDown-LeftUSR 16538 + USR 16588

Diagonal movement is achieved by sequentially calling two cardinal-direction routines in BASIC rather than implementing combined diagonals in machine code, keeping the MC routines simple and orthogonal.

Notable Techniques

  • REM-as-code store: embedding machine code in a REM line is a standard technique that keeps the code in a known, fixed address and prevents the BASIC editor from interpreting the bytes.
  • Self-referential data pointer: LD HL,(0x400C) reads a word from within the REM statement itself, allowing the routine to find its own working data without hardcoding a separate address.
  • LDIR/LDDR for scrolling: using the Z80 block-copy instructions is the fastest pure-Z80 approach to scrolling a rectangular region of screen memory.
  • DJNZ clear loop: after a scroll, a DJNZ loop with LD (HL),0 efficiently blanks the newly exposed row or column.
  • Line 5 LIST 35: GOTO 5 at line 80 causes the program listing to scroll to line 35, effectively hiding the machine code REM from casual view on restart.
  • INKEY$ polling without PAUSE: line 20 samples the keyboard every BASIC iteration with no delay, giving the fastest possible response at the cost of no key-repeat debounce.

Potential Anomalies

  • Line 57 is referenced by GOTO 57 (line 54) but does not exist. After the cascade of diagonal-key checks, control falls through to GOTO 20 at line 60 — the missing line 57 simply causes BASIC to continue to the next higher line, which is line 60. This is intentional and well-understood behaviour.
  • The trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C at the end of the REM (control codes 28–37) are not reachable as code; they appear to be a lookup table or padding used as data by the routines.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10051 – 10121.

Related Products

Related Articles

Related Content

Image Gallery

Screen Scrolling Routine

Source Code

   1 REM \2A\0C\40\23\E5\11\21\00\19\D1\01\B5\02\ED\B0\EB\06\20\36\00\23\10\FB\C9\2A\10\40\11\43\00\ED\52\E5\11\21\00\ED\52\D1\01\B5\02\ED\B8\EB\06\20\2B\36\00\10\FB\C9\2A\0C\40\06\16\C5\06\20\3E\00\23\4F\7E\71\10\FA\23\C1\10\F1\C9\2A\10\40\11\43\00\ED\52\06\16\C5\06\20\3E\00\2B\4F\7E\71\10\FA\2B\C1\10\F1\C9\1D\1E\1F\20\21\22\23\24\25\1C
   5 LIST 35
  20 LET D$=INKEY$
  25 IF D$="J" THEN RAND USR 16588
  30 IF D$="M" THEN RAND USR 16538
  35 IF D$="I" THEN RAND USR 16514
  40 IF D$="K" THEN RAND USR 16567
  41 IF D$="U" THEN GOTO 43
  42 GOTO 45
  43 RAND USR 16514
  44 RAND USR 16588
  45 IF D$="O" THEN GOTO 47
  46 GOTO 49
  47 RAND USR 16514
  48 RAND USR 16567
  49 IF D$="." THEN GOTO 51
  50 GOTO 53
  51 RAND USR 16538
  52 RAND USR 16567
  53 IF D$="N" THEN GOTO 55
  54 GOTO 57
  55 RAND USR 16538
  56 RAND USR 16588
  60 GOTO 20
  70 SAVE "1009%7"
  80 GOTO 5

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

People

No people associated with this content.

Scroll to Top
BFE\FA

Screen Scrolling Routine

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

This program implements a character-movement or screen-scrolling system driven entirely by machine code routines embedded in the REM statement at line 1. The BASIC shell reads a keypress via INKEY$ and dispatches to one of four machine code entry points (USR 16514, 16538, 16567, 16588) depending on the key pressed, covering eight directions: J, M, I, K for cardinal directions and U, O, ., N for diagonals (combining two cardinal calls). The machine code, stored beginning at address 16514 (0x4082, just inside the REM statement data), performs direct memory operations including LDIR and LDDR block moves, consistent with scrolling a screen region or shifting a sprite/character buffer. The SAVE at line 70 uses an inverse-video character in the filename as an auto-run marker.


Program Analysis

Program Structure

The program has three logical layers:

  1. Machine code store — Line 1 is a REM statement whose body contains raw Z80 opcodes. Because the ZX Spectrum/TS2068 stores REM data verbatim in RAM, the bytes are directly executable starting at the address of the first byte after the REM token.
  2. Input loop — Lines 20–60 form a tight polling loop: INKEY$ is sampled at line 20, then a cascade of IF/GOTO chains dispatches to the appropriate machine code entry point(s).
  3. Housekeeping — Lines 70–80 provide a SAVE and a GOTO 5 (which jumps to LIST 35) for re-entry/display purposes.

Machine Code Entry Points

Line 1 begins at address 16384 (0x4000). The REM token occupies one byte and the two-byte length field two more, placing the first opcode at 0x4003 (16387). However, the BASIC calls target four distinct addresses:

USR AddressHexKey(s)Role (inferred)
165140x4082I, U, OScroll/move up
165380x409AM, ., NScroll/move down
165670x40B7K, ., NScroll/move right
165880x40CCJ, U, NScroll/move left

The REM data is 59 bytes long (the trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C are likely padding or lookup data). The entry points are therefore spread across the REM body and each routine ends with a C9 (RET) opcode.

Z80 Routine Analysis

Disassembling the REM bytes reveals four subroutines that use the Z80 block-move instructions LDIR (ED B0) and LDDR (ED B8) to shift screen memory. Common patterns observed:

  • 2A 0C 40LD HL,(0x400C): loads a pointer from within the REM area itself (self-referential data).
  • 11 21 00LD DE,0x0021 (33 decimal): one character row width on a 32-column display plus one, used as an offset for vertical scrolling.
  • ED B0 / ED B8LDIR/LDDR: bulk copy forward/backward for up/down scroll directions.
  • 01 B5 02LD BC,0x02B5 (693): the byte count, matching the number of bytes in roughly 21.6 character rows — consistent with scrolling most of the display.
  • 36 00 inside a DJNZ loop — LD (HL),0: clears the vacated edge row/column after a scroll.
  • 06 20LD B,0x20 (32): loop counter for clearing 32 columns.
  • 06 16LD B,0x16 (22): loop counter for clearing 22 rows.

Key Mapping and Diagonal Movement

The eight keys map naturally to a numeric-keypad layout:

KeyDirectionRoutines called
IUpUSR 16514
KRightUSR 16567
MDownUSR 16538
JLeftUSR 16588
UUp-LeftUSR 16514 + USR 16588
OUp-RightUSR 16514 + USR 16567
.Down-RightUSR 16538 + USR 16567
NDown-LeftUSR 16538 + USR 16588

Diagonal movement is achieved by sequentially calling two cardinal-direction routines in BASIC rather than implementing combined diagonals in machine code, keeping the MC routines simple and orthogonal.

Notable Techniques

  • REM-as-code store: embedding machine code in a REM line is a standard technique that keeps the code in a known, fixed address and prevents the BASIC editor from interpreting the bytes.
  • Self-referential data pointer: LD HL,(0x400C) reads a word from within the REM statement itself, allowing the routine to find its own working data without hardcoding a separate address.
  • LDIR/LDDR for scrolling: using the Z80 block-copy instructions is the fastest pure-Z80 approach to scrolling a rectangular region of screen memory.
  • DJNZ clear loop: after a scroll, a DJNZ loop with LD (HL),0 efficiently blanks the newly exposed row or column.
  • Line 5 LIST 35: GOTO 5 at line 80 causes the program listing to scroll to line 35, effectively hiding the machine code REM from casual view on restart.
  • INKEY$ polling without PAUSE: line 20 samples the keyboard every BASIC iteration with no delay, giving the fastest possible response at the cost of no key-repeat debounce.

Potential Anomalies

  • Line 57 is referenced by GOTO 57 (line 54) but does not exist. After the cascade of diagonal-key checks, control falls through to GOTO 20 at line 60 — the missing line 57 simply causes BASIC to continue to the next higher line, which is line 60. This is intentional and well-understood behaviour.
  • The trailing bytes \1D\1E\1F\20\21\22\23\24\25\1C at the end of the REM (control codes 28–37) are not reachable as code; they appear to be a lookup table or padding used as data by the routines.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10051 – 10121.

Related Products

Related Articles

Related Content

Image Gallery

Screen Scrolling Routine

Source Code

   1 REM \2A\0C\40\23\E5\11\21\00\19\D1\01\B5\02\ED\B0\EB\06\20\36\00\23\10\FB\C9\2A\10\40\11\43\00\ED\52\E5\11\21\00\ED\52\D1\01\B5\02\ED\B8\EB\06\20\2B\36\00\10\FB\C9\2A\0C\40\06\16\C5\06\20\3E\00\23\4F\7E\71\10\FA\23\C1\10\F1\C9\2A\10\40\11\43\00\ED\52\06\16\C5\06\20\3E\00\2B\4F\7E\71\10\FA\2B\C1\10\F1\C9\1D\1E\1F\20\21\22\23\24\25\1C
   5 LIST 35
  20 LET D$=INKEY$
  25 IF D$="J" THEN RAND USR 16588
  30 IF D$="M" THEN RAND USR 16538
  35 IF D$="I" THEN RAND USR 16514
  40 IF D$="K" THEN RAND USR 16567
  41 IF D$="U" THEN GOTO 43
  42 GOTO 45
  43 RAND USR 16514
  44 RAND USR 16588
  45 IF D$="O" THEN GOTO 47
  46 GOTO 49
  47 RAND USR 16514
  48 RAND USR 16567
  49 IF D$="." THEN GOTO 51
  50 GOTO 53
  51 RAND USR 16538
  52 RAND USR 16567
  53 IF D$="N" THEN GOTO 55
  54 GOTO 57
  55 RAND USR 16538
  56 RAND USR 16588
  60 GOTO 20
  70 SAVE "1009%7"
  80 GOTO 5

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

People

No people associated with this content.

Scroll to Top
B\C1\F1\C9 itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57148 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.5 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"D itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57148 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.5 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"E itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57148 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.5 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"F itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57148 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.5 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"C 5 LIST 35 20 LET D$=INKEY$ 25 IF D$="J" THEN RAND USR 16588 30 IF D$="M" THEN RAND USR 16538 35 IF D$="I" THEN RAND USR 16514 40 IF D$="K" THEN RAND USR 16567 41 IF D$="U" THEN GOTO 43 42 GOTO 45 43 RAND USR 16514 44 RAND USR 16588 45 IF D$="O" THEN GOTO 47 46 GOTO 49 47 RAND USR 16514 48 RAND USR 16567 49 IF D$="." THEN GOTO 51 50 GOTO 53 51 RAND USR 16538 52 RAND USR 16567 53 IF D$="N" THEN GOTO 55 54 GOTO 57 55 RAND USR 16538 56 RAND USR 16588 60 GOTO 20 70 SAVE "1009%7" 80 GOTO 5

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

People

No people associated with this content.

Scroll to Top