Screen Scrolling

See all articles from SYNC v1 n4

Introduction

This article shows how a routine can be written and entered into a ZX80 that enables the user to SCROLL the display. In the 4K monitor there is no facility at all for doing other than printing to the last line of the display, and then, when the display is full, the program will stop unless a CLS (clear screen) command is used.

The 8K monitor does have a SCROLL command, but it is limited in use as it only enables the user to scroll the whole display one-line-up and to print to the bottom line again.

The routine in this article will only work under the 4K ROM.

Objectives

My first objective was to produce a routine that would simply scroll the display one-line-up, when called by a USR command and allow the user to continue printing at the end of the display. However, a second objective soon appeared and that was to extend the routine so that only a predetermined part of the screen would be scrolled, thereby enabling the user to have a “title” area at the top of the display that would remain un-scrolled. The routine would require from the user that the number of lines to be left unscrolled be specified, using a POKE command, before using the USR command.

The Theory

Before writing a routine that manipulates the contents of the display file, we must have a clear understanding of the structure of the display file of the ZX80. Figure 1 shows the parts of the display file as they would be produced by running the simple program:

10 PRINT "FIRST LINE"
20 PRINT "SECOND LINE"

Press RUN and NEWLINE.

Figure 1.
Figure 1.
Figure 2.
Figure 2.

Note that the lines are of varying length and that they all end in a “118” (Hex. 76) which is the end-of-line marker.

The pointer D-FILE always points to the first character in the display file, which is always an end-of-line character.

The pointer DF-EA points to the start of the “lower part of the screen,” and DF-END points to the twenty-fifth end-of-line marker.

It is important to realize that the pointers DF-EA and DF-END are only given their final values when the execution of a program finishes. Before this time the pointers are being changed as each character is added to the display file. Therefore before the “end of program” routine is executed the pointers DF-EA and DF-END both point to the last location in the partially completed display file.

In a scroll routine it is necessary initially to collect the current value of D-FILE and then look through the display file until the point is reached that is to become the “new” contents of D-FILE. However, if certain lines are not to be scrolled, then these lines must be passed over, and the last end-of-line marker considered to be D-FILE.

The length of the line to be erased is then found, and the scrolling is achieved by moving the whole of the remainder of the display file down in memory so that it overwrites the scrolled line. There then remain two house-keeping tasks. The value of DF-EA and the value of the system variable 16421, the line counter, need to be altered. DF-EA has to be reduced by the ‘length’ of the erased line, and the line counter has to be incremented (one added) to take into accunt that there is now one less line in the display file.

Figure 2 shows the action of the scrolling routine that has left 2 lines and then scrolled once, deleting line 3.

Loading the Routine

The following method can be used to enter the routine into the ZX80. The routine is kept in a REM statement held off the screen so do not try to list it.

Enter the following lines:

10 REM 12345678901234567890123456
78901234567890123456789012345678901
2345678901234567890
20 REM *** SCROLL ***
30 REM FIRST POKE 16427 WITH
THE NUMBER OF LINES TO BE LEFT
THEN USE LET K=USR(16430)

Now push line 10 off the screen by using EDIT.

The actual steps are:

HOME
EDIT
RUBOUT,RUBOUT, ENTER 40 and NEWLINE.
EDIT
RUBOUT, RUBOUT, ENTER 70 and NEWLINE.
EDIT
RUBOUT, RUBOUT, ENTER 80 and NEWLINE.
EDIT
NEWLINE
LIST 20
and delete lines 40, 50, 60, 70 and 80.

The actual machine code can now be POKED into line 10 by using a simple loader.

The Assembly Language Listing

402B                                ORG 402B
402B 00 LEAVE DEFB No. of lines unaltered.
402C 00 00 NEW D-FILE DEFW Line end address store.
402E 2A 0C 40 START LD HL,(D-FILE) Pick up D-FILE.
4031 ED 5B 0E 40 LD DE,(DF-EA) Pick up DF-EA.
4035 22 2C 40 LINE END LD (NEW D-FILE),HL Address of scroll line.
4038 23 INC HL Enter next line.
4039 01 00 00 LD BC,+0000 Initialize counter.
403C 3E 75 NEXT LD A,+75 Form end-of-line
403E 3C INC A marker in A register.
403F EB EX DE,HL Change over registers.
4040 A7 AND A Clear carry flag.
4041 ED 52 SBC HL,DE Find if DF-EA has
4043 20 02 JR NC,NO ERROR been reached.
4045 CF 09 ERROR RST 0008, "9" Will give "A" error.
4047 19 NO ERROR ADD HL,DE Reform HL.
4048 EB EX DE,HL Exchange back registers.
4049 BE CP (HL) Look for end of line.
404A 28 04 JR Z,COUNT Yes. End of line found.
404C 23 INC HL No. So go to next
404D 0C INC C character, incrementing
404E 18 EF JR NEXT counter and address.
4050 3A 2B 40 COUNT LD A,(LEAVE) Collect the parameter.
4053 A7 AND A Is it zero?
4054 28 06 JR SCROLLING Yes. So scroll.
4056 3D DEC A No. So pass to next line.
4057 32 2B 40 LD (LEAVE),A Replace the parameter.
405A 18 D9 JR LINE END Back to LINE END.
405C 79 SCROLLING LD A,C Save C in A register.
405D EB EX DE,HL Exchange registers.
405E A7 AND A Clear carry flag.
405F ED 52 SBC HL,DE Find length of rest of
4061 44 LD B,H the display file and
4062 4D LD C,L put it in BC.
4063 2A 2C 40 LD HL,(NEW D-FILE) Collect the line end
4066 EB EX DE,HL address and scroll the
4067 ED B0 LDIR display file.
4069 2A 0E 40 LD HL,(DF-EA) Reduce the value of
406C 4F LD C,A DF-EA by the size of
406D 37 SCF the character count
406E ED 42 SBC HL,BC of the scrolled line
4070 22 0E 40 LD (DF-EA),HL that was saved in A.
4073 3A 25 40 LD A,(LINE COUNT) Increment the value
4076 3C INC A of the system variable
4077 32 25 40 LD (LINE COUNT),A 16421- line count.
407A C9 RET Return to Basic.
100 FOR I=16427 to 16506
110 INPUT A
120 POKE I,A
130 NEXT I

The data for this routine is:

0,0,0,42,12,64,237,91,14,64,34,44,64,35,
1,0,0,62,117,60,235,167,237,82,32,2,
207,9,25,235,190,40,4,35,12,24,239,58,
43,64,167,40,6,61,50,43,64,24,217,121,
235,167,237,82,68,77,42,44,64,235,237,
176,42,14,64,79,55,237,66,34,14,64,58,
37,64,60,50,37,64,201

So enter lines 100 to 130 and RUN 100. Enter the machine code carefully. The checksum for the data is 6578, and this can be checked by adding the lines:

 90 LET T=0
110 delete
120 LET T=T+PEEK(I) and using RUN 90
140 PRINT T

Now delete all the lines from 90 onwards and SAVE.

Using the Scroll Routine

The following demonstration program shows in a simple way how the routine can be used.

With the routine stored in line 10, held off the screen, enter:

40 for I=1 TO 23
50 PRINT "LINE ";I
60 NEXT I
70 POKE 16427,2
80 LET K=USR(16430)
RUN

In line 70 always specify how many lines. Line 80 calls the scroll routine.

The result of the above program should be to produce a display in which “LINE 3” is missing, and the remainder of the display has been scrolled up a line (hence the gap between “LINE 23” and the error report).

ERROR A Report

The routine does declare an error when an attempt is made to hold more lines unscrolled than actually exist in the display file at that particular moment. This can be seen in the demonstration program by changing line 70 to read:

70 POKE 16427,24

This asks the routine to scroll all the lines after the 24th. Clearly a confusing situation so ERROR A is reported.

An Example Use of Scrolling

The following game shows just one of the many uses to which the scroll routine can be put. In this game you will test your skill at driving along a road. The scroll routine is used to scroll the “road” and also to remove an “end message”; in this case the message is “PRESS 5,6 or 8.” Note carefully how the parameter of how many lines are to be left unscrolled is specified on each occasion that the scroll routine is called.

This game program is really only a first try at using the scroll routine, so I would therefore be very interested in seeing programs from readers who use this routine in writing their own programs.

Road Game

 10 as previously prepared and held off the screen.
20 REM STOP , Just a reminder.
30 RANDOMISE , Different every run.
40 PRINT ,"*** ROAD GAME ***" , Title.
50 PRINT , Space.
60 LET C=0 , Set odometer to zero.
70 GO TO 190 , Go past subroutine.
80 LET S=S+RND(5)-3 , Move road a little left or right,
90 IF S<4 THEN LET S=4 , but not off the left,
100 IF S>30 THEN LET S=30 , or off the right.
110 FOR A=1 TO S-3 , Print "one mile" of road.
120 PRINT "▒"; ▒ (shift A) , Hard verge.
130 NEXT A ,
140 PRINT " "; (4 sp.) , Print four spaces for the road.
150 FOR A=S+2 TO 32 , The other hard verge.
160 PRINT "▒"; ▒ (shift A) ,
170 NEXT A ,
180 RETURN , One mile of road printed.
190 FOR R=1 TO 4 , Print four miles of road
200 LET S=15 , but fixed, rather than curved.
210 GO SUB 110 , Each mile.
220 NEXT R ,
230 FOR R=1 TO 3 , Now print three miles of road
240 GO SUB 80 , that does use the random function
250 NEXT R , to move the road left or right.
260 LET T=110+PEEK(16396)+PEEK( , Initial car position.
16397)*256 ,
270 LET R=T , Copy it.
280 POKE R,20 , Print the car.
290 PRINT , Add an end of line marker.
300 PRINT , Space.
310 PRINT ,"PRESS 5,6 OR 8" , Left, right, or straight ahead.
320 INPUT A , Collect direction.
330 POKE 16427,9 , Hold the title and road unscrolled.
340 LET T=USR(16430) , Scroll away the blank line.
350 POKE 16427,9 , Hold the title and road unscrolled.
360 LET T=USR(16430) , Scroll away 'PRESS 5,6 OR 8'
370 IF A=8 THEN LET R=R-(RND(5) , Turn to right, but not always.
>2)
380 IF A=5 THEN LET R=R+(RND(5) , Turn to left, but not always.
>2)
390 POKE 16427,2 , Hold the title unscrolled.
400 LET T=USR(16430) , Scroll the road
410 GO SUB 80 , Add another mile of road.
420 IF NOT PEEK(R)=0 THEN GO TO , Test to see if runs off road.
450
430 LET C=C+1 , Increment odometer.
440 GO TO 280 , "Survived" so drive on.
450 POKE R,148 , "CRASHED"
460 PRINT , Add end of line marker.
470 PRINT , Space.
480 PRINT "* YOU CRASHED AFTER , The sign of failure.

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