Scrolls

Date: 198x
Type: Program
Platform(s): TS 2068

Scrolls demonstrates two machine code routines that perform hardware-level screen scrolling — one scrolling the display right and one scrolling it left. The routines are loaded into RAM at addresses 26715 and 26753 respectively via POKE loops reading DATA statements, then invoked with RANDOMIZE USR. Line 2000 offers a separate demonstration that cycles through all 255 values of the system variable at address 23606, which controls the horizontal pixel scroll offset, printing a string at a fixed screen position to show the effect. Line 500 contains an extended comment mapping out screen third boundaries (64–88 in display RAM terms) that likely guided the machine code design.


Program Analysis

Program Structure

The program is divided into three functional areas:

  1. Initialization (lines 10–20): Two FOR loops use READ and POKE to install machine code into RAM at addresses 26715–26733 and 26753–26779.
  2. Scroll-right demo (lines 995–1160): Prints a test string, then calls the left-scroll routine 100 times via RANDOMIZE USR 26753, reprints the string, and calls the right-scroll routine 100 times via RANDOMIZE USR 26715.
  3. Hardware pixel-scroll demo (line 2000–2010): Cycles system variable address 23606 through values 1–255 while displaying a fixed string, then resets to 0.

Execution begins at line 10 and falls through to line 20, then hits GO TO 1090 at line 995 (line 500’s REM and line 996’s STOP are bypassed). The DATA statements at lines 1000–1080 are read sequentially by the two initialization loops.

Machine Code Routines

The two routines are disassembled below. Display RAM on the ZX Spectrum begins at 0x4000 (16384 decimal); pixel rows are interleaved in a non-linear pattern, but the routines treat the screen as a flat 32-byte-wide, 192-row block for simplicity, using the range 0x4000–0x5800 (64–88 in high-byte terms).

Scroll Right Routine (address 26715)

BytesMnemonicNotes
33,0,64LD HL,&4000Point HL to start of display RAM
14,32LD C,3232 bytes per row
175XOR AClear A (carry flag source / shift-in bit)
126LD A,(HL)Load byte
31RRARotate right through carry
119LD (HL),AStore shifted byte
35INC HLAdvance pointer
13DEC CDecrement column counter
32,249JR NZ,-7Loop for 32 bytes
62,88LD A,88High byte of end address (0x5800)
188CP HCompare with current high byte
32,241JR NZ,-15If not at end, do next row
201RETReturn

This routine scrolls all pixel bytes one bit to the right using RRA (rotate right through carry). The carry propagates across each byte in a row but resets between rows (carry is cleared by the XOR A only at the start), meaning the rightmost bit of each byte wraps into the leftmost bit of the next — effectively a bitwise right-shift across the full 32 bytes of each row. The outer loop advances row by row until the high byte of HL reaches 88 (0x58).

Scroll Left Routine (address 26753)

BytesMnemonicNotes
33,31,64LD HL,&401FPoint HL to byte 31 of first row (last byte)
22,0LD D,0Row counter high = 0
30,65LD E,65Used in DE for row stepping
14,32LD C,3232 bytes per row
175XOR AClear A / carry
126LD A,(HL)Load byte
23RLARotate left through carry
119LD (HL),AStore shifted byte
43DEC HLMove left
13DEC CDecrement column counter
32,249JR NZ,-7Loop for 32 bytes
25ADD HL,DEAdvance HL to next row’s last byte
62,88LD A,88End high-byte sentinel
188CP HCompare
40,3JR Z,+3If at end, jump to RET
43DEC HLAdjust to last byte of next row
24,235JR -21Next row loop
201RETReturn

This routine works from right to left within each row, using RLA (rotate left through carry) to shift pixels leftward. DE (value 65 = 0x41) is added to HL after each row to step forward 65 bytes, then HL is decremented by 1 to land on the last byte of the next row — a compact way to handle the 32-byte row stride from an end-of-row position.

Hardware Pixel-Scroll Demo (line 2000)

System variable address 23606 (the CHARS system variable, normally a pointer to the character set) is repurposed here as a pixel scroll offset. Cycling it through 0–255 causes the display hardware to shift the pixel output horizontally, producing a smooth scrolling effect without moving any screen data. The POKE 23606,0 at line 2010 restores normal character rendering after the demo.

Notable Techniques

  • RANDOMIZE USR is used to call machine code, discarding the return value — the standard method for invoking Z80 routines from BASIC.
  • The XOR A before the inner byte loop clears both A and the carry flag in a single byte, ensuring no spurious carry from the previous row bleeds into the shift.
  • The high-byte sentinel check (LD A,88 / CP H) efficiently detects the end of display RAM without a full 16-bit comparison.
  • Line 500’s lengthy REM serves as a developer scratch pad, documenting address ranges for screen thirds — typical of iterative machine code development within BASIC.
  • The ''' (three newlines via multiple apostrophes in PRINT) creates vertical spacing in the demo output at line 1090.

Anomalies and Notes

  • The loop variable at line 1140 is A (uppercase) while the loop at line 1100 uses a (lowercase). In Spectrum BASIC these are the same variable, so the NEXT a at line 1160 correctly terminates the loop begun at line 1140.
  • Lines 1 and 2 contain REM statements with cryptic shorthand (e.g. RANDOMIZE, SGN, LET) that appear to be development notes about variable usage rather than executable code.
  • Line 996’s STOP is unreachable in normal execution since line 995 performs a GO TO 1090, but it acts as a safety barrier between the jump and the DATA statements should the flow ever fall through.

Content

Appears On

Related Products

Related Articles

Related Content

Image Gallery

Source Code

    1 REM !@# RANDOMIZE >XSGN  LET <>zzzzzzzzzzzzz
    2 REM !@A+ RANDOMIZE >XSGN (+ FOR <>zzzzz
   10 FOR g=26715 TO 26733: READ a: POKE g,a: NEXT g
   20 FOR g=26753 TO 26779: READ a: POKE g,a: NEXT g
  500 REM 1000  1002  2000  2002          itm3  itm1  itm3  itm6  all       64    88    64    88  top third 64    72    64    72  mid third 72    80    72    80  low third 80    88    80    88  top 2/3   64    80    64    80  low 2/3   72    88    72    88                               
  995 GO TO 1090
  996 STOP 
  997 REM 
  998 REM SCROLL RIGHT (26715)    
 1000 DATA 33,0,64,14,32,175,126
 1010 DATA 31,119,35,13,32,249,62
 1020 DATA 88,188,32,241,201
 1030 REM 
 1040 REM SCROLL LEFT (26753)     
 1050 DATA 33,31,64,22,0,30,65,14
 1060 DATA 32,175,126,23,119,43
 1070 DATA 13,32,249,25,62,88,188
 1080 DATA 40,3,43,24,235,201
 1090 PRINT "this is a test of the system"''''"      Also Try RUN 2000"
 1100 FOR a=1 TO 100
 1110 RANDOMIZE USR 26753
 1120 NEXT a
 1130 PRINT "this is a test of the system"''''"      Also Try RUN 2000"
 1140 FOR A=1 TO 100
 1150 RANDOMIZE USR 26715
 1160 NEXT a
 2000 FOR A=1 TO 255: POKE 23606,A: PRINT AT 12,10;"ABCDEFGHIJK": NEXT A
 2010 POKE 23606,0

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

People

No people associated with this content.

Scroll to Top