ZX81 SCROLLING (16K ZX-81)
By Ian Morrison
from Personal Computing Today, December 1982, pages 60-61

Many 16k ZX81 users will have noticed how slow the SCROLL command operates in
16k programs. It also does some very perculiar things to the display file so
that POKEing onto the screen, in BASIC or Machine Code can often cause a system
to crash. This is also why it takes such a long time for the CLS command to
work after the computer has operated many scrolls.

The following four Machine Code routines are for fast and efficient up, down
and sideways scrolls, the latter three of which cannot be accessed from the
keyboard without the use of Machince Code. They occupy very little memory,
however they do not change the PRINT position or print a line of spaces at the
edge of the screen, but if necessary this can be achieved quite easily.

Each routine makes use of one of the following Machide code commands:-

LDIR - a two byte instruction but really is a routine itself,

       LDIR load (de),(hl)
            increment de
            increment hl
            decrement bc
            if bc=0 then go to LDIR

LDDR - a two byte instruction similar to LDIR except that the de and hl
registers are decreased.

       LDDR load (de),(hl)
            decrement de
            decrement hl
            decrement bc
            if bc=0 then go to LDDR

LDIR stands for Load, Increment (increase) and Repeat while LDDR stands for
Load, Decrement (decrease) and Repeat: both are called Block Operators as they
shift blocks of memory.

Up (normal scroll)
This uses 15 bytes of memory.

00 - 42  12  64   ld hl,(16396)   ; hl now equals the first byte of the display.
03 - 229          push hl         ; put hl onto the stack.
04 - 209          pop de          ; get de off the stack (de=hl).
05 - 01  33  0    ld bc,33        ; bc=33, the width of one full line of the 16K display.
08 - 09           add hl,bc       ; hl is one line lower than de.
09 - 01  181 02   ld bc,693       ; bc=693, the size of the twenty lines of the display to be moved up.
12 - 237 176      ldir            ; moves twenty lines up.
14 - 201          ret             ; return to BASIC.

Down Scroll
This occupies 20 bytes.

00 - 42  12  64   ld hl,(16396)   ; start of the display file.
03 - 17  214 2    ld de,726       ; full size of the screen.
06 - 25           add hl,de       ; hl now points to the end of the display file.
07 - 229          push hl         ; put hl onto the stack.
08 - 209          pop de          ; pop de off the stack (de=hl).
09 - 1   33  0    ld bc,33        ; bc=33, one full line.
12 - 237 66       sbc hl,bc       ; hl=hl-33 and now points to the end of the second last line of the screen.
14 - 1   181 2    ld bc,693       ; the number of characters to be moved down.
17 - 237 184      lddr            ; moves twenty lines down.
19 - 201          ret             ; return to BASIC.

Scroll To The Left
This occupies 20 bytes.

00 - 42  12  64   ld hl,(16396)   ; start of the display file.
03 - 229          push hl         ; put hl onto the stack.
04 - 209          pop de          ; get de off the stack (de=hl).
05 - 62  22       ld a,22         ; a is the number of lines to be scrolled.
07 - 35           LOOP inc hl     ; hl=hl+1
08 - 35           inc hl          ; hl is now pointing to the second character of the line.
09 - 19           inc de          ; de is pointing to first character of the line.
10 - 1   31  0    ld bc,31        ; 31 is the number of columns to move to the left.
13 - 237 176      ldir            ; moves 31 characters to the left.
15 - 19           inc de          ; de and hl are now pointing to a new line.
16 - 61           dec a           ; decrease the number of lines to be scrolled.
17 - 32  244      jr nz,LOOP      ; if not zero then goto LOOP.
19 - 201          ret             ; return to BASIC.

Scroll To The Right
this occupies 24 bytes.

00 - 42  12  64   ld hl,(16396)   ; start of the display file.
03 - 17  214 2    ld de,726       ; size of the screen (22*33).
06 - 25           add hl,de       ; hl now points to the end of the display file.
07 - 229          push hl         ; put hl onto stack.
08 - 209          pop de          ; get de off stack (de=hl).
09 - 62  22       ld a,22         ; a is the number of lines to be scrolled.
11 - 35           LOOP dec hl     ; hl=hl-1
12 - 35           dec hl          ; hl points to the second last character of the line.
13 - 19           dec de          ; de points to the last character of the line.
14 - 1   31  0    ld bc,31        ; the number of columns to be moved.
17 - 237 176      ldir            ; moves 31 characters to the right.
19 - 19           dec de          ; de and hl are now pointing to a new line.
20 - 61           dec a           ; decrease the number of lines to be scrolled.
21 - 32  244      jr nz,LOOP      ; if not zero then goto LOOP.
23 - 201          ret             ; return to BASIC.

The best way, I think of storing these Machine Code routines is to keep them in
a REM statement at teh start of any BASIc program. However they can be placed
any where in RAM as all jumps in Machine Code are relative. In the listing each
scroll routine is kept in a different REM statement which makes it easier to
type in, but can be kept in the one long line which saves memory but is harder
to type in. If all the routines are in the same line then the USR calls will be
different.
