.........1.........2.........3.........4.........5.........6.........7.........8

LIGHT SCREEN DESIGNER
ZX Computing, February/March 1985
Part 05 of 13

Toni Baker continues our machine code mega-program


Before I start Part Five, I'd like to give a brief summary of all the
errors which have cropped up in the listing so far. In Part One, the
drawing labelled Figure One was incorrect, however this was corrected
in Part Two. The other errors are all either errors in the hex listing
in the first column, or errors in the assembler mnemonics in the
remaining columns.

All errors in Part One were corrected in Part Two, except that in the
section GET_CHR_2, the instruction INC A should be in the third
column, not the second. Part Two however contained errors which were
not corrected in Part Three. The hex instruction at DD38 should be
FEB0, not FEC0. The hex instruction at DD89 should be 1E36, not 1E26.
In the section DR_CURSOR, "LD E,DOWN_PIX low" should read "LD E,UP_PIX
low", and "LD E,UP_PIX low" should read "LD E,DOWN_PIX low". In Part
Three the chunk of code between DE3D and DE56 is all obsolete, and is
replaced by a new block of code given in Part Four - which contains an
error (which I'll deal with in a minute). Also the hex code at DE87
should be 3807, not 3805, and the hex code at DE94 should be CDB6DD,
not CDB6DD. In the section DR_CURSORS the label DSC_CONT should be one
line down, and further on, "RET" should be in the third column, not
the second. In the section START, the label "LSD_LOOP" is in the wrong
place. It is currently in the third column - it should in fact be in
the second column, and one line up. The instruction LD E,(HL) should
be in the third column (where "LSD_LOOP" is now) and not in the fourth
column. In the section MAIN_LOOP, "LD DE,(CURSOR+2)" should read "LD
BC,(CURSOR+2)". The labels "CSR_DOWN" and "CSR_UP" should be
transposed, [and] on the same lines "CALL UP_PIX" and "CALL DOWN_PIX"
should also be transposed, and also the accompanying notes.


Yet More ...

Now onto Part Four, where we find an error in the amendments to Part
Three. In the section ML_TEST there is a missing line, which should be
positioned directly above the label ML_CTlON. The missing line should
read "CBAE - RES 5,(HL)". Also in Part Four; at address DEC2 the word
"UNDO" appears in the first column amongst the hex code - this is in
fact a label, and hence should appear in the second column. At address
DED8: "2106DB" should read "210CDB", and at address DEFE: "CREADE"
should read "CDEADE". In the section MOVE, "LD (ORIGIN+2),BC" should
be in the third column, not the second, and the notes "Change origin
..." etc on the same line should be in the fourth column, not the third.

Phew ...

Anyway, this issue's article covers thirteen more keys, and thus
enables you to do a whole lot more. From the top row of the keyboard
we have the functions STORE and RECALL, and also CLS. (Note that CLS
is on key "9", not on key "V" as in BASIC). From the second row the
function CLEAR - this is not the same as the BASIC CLEAR, but I'll
explain what it does in this program in a moment. From the third row
we have the function USR, and on the fourth row - every single key
will now be operative.


Store And Recall

STORE is activated by key "3", and RECALL by key "4". The program uses
ten "memories" - numbered from zero to nine. Each memory can store the
position of the cursor. In other words, if you type STORE 5, then the
cursor position will be stored in memory 5. If you, at some later
stage type RECALL 5, the cursor will move to the "remembered"
position. In addition to merely storing cursor positions, you can
STORE and RECALL the whole screen. Typing STORE 'enter' will store the
entire screen picture (and the positions of all three cursors). Typing
RECALL 'enter' will restore the screen to the stored picture, and
restore the cursors too. All of the memories are initially designated
"unused". Attempting to RECALL an unused memory produces no effect.
Once a memory has been used, however, it is not possible to declare it
"unused" any more. The SCREEN memory, however, CAN at any stage be
declared unused, simply by pressing the button "CLEAR" (key "I"). Note
that all the time there is an image stored in the screen memory the
function UNDO will not work, so it is advisable to CLEAR the screen
memory as soon as you have finished using it.

CLS (key "9") will clear the screen in the current colours. You can
change these current colours at will (see below) and hence you can
clear the screen in any colours.

The function USR is more or less self explanatory. Its purpose is to
call a machine code subroutine at any address. You must type "USR"
followed by four hex digits (forming a machine code address), followed
by enter. A subroutine at that address will then be called. If you
type in an address wrongly you can of course press the ESCAPE button
(SPACE) in order to cancel your decision. As examples, USR 0D6B will
clear the screen, and USR 1CEE will generate a STOP statement report.
The purpose of the function is of course to make Light Screen Designer
infinitely flexible. You can write your own machine code programs to
perform various graphic functions, and call them from within LSD.
(Note that in keeping with convention, such a program should always
use the SPACE key as an ESCAPE function - that is, it must cancel the
current operation and return to Light Screen Designer). It is of
course possible to use your own BASIC as well - simply press ESCAPE to
return to BASIC, carry out whatever tasks you require, and then use
USR 56789 to reinstate Light Screen Designer.

COPY makes a copy of the screen image onto the ZX printer. It is the
same as the COPY command in BASIC.

PAPER and INK change the current paper and ink colours as you would
expect. Note that PAPER 8 (transparent) and PAPER 9 (contrast) are
both allowed. FLASH and BRIGHT may be switched on (1) and off (0) at
will. Note that FLASH 8 (transparent) is also allowed. BORDER changes
the colour of (a) the border, and (b) the lower two lines of the
screen. OVER and INVERSE may be switched on and off at will - eg. to
"un-PLOT" a point just type INVERSE 1, PLOT and INVERSE 0. All of
these colour controlling functions are on the same keys as in BASIC,
except for BRIGHT, which is on the "CAPS SHIFT" key.

And there we have it. With the exception of CLEAR, all of this issue's
functions require the user to INPUT something after selecting the
function - either to select a memory number, a colour, a machine code
address, or just to say "Y" or "N" (yes or no). All of this is made
possible by the MESSAGE subroutine given in Part One. Go back to it if
you like, to see how it works. Another point of interest about this
Part is that all of the colour functions (except BORDER) are all
handled by the same routine - ie. there is but one subroutine which
copes with PAPER, INK, FLASH, BRIGHT, OVER and INVERSE. This lies at
address DF5D.

In order to associate the various subroutines to the various keys, it
is necessary, once again, to update the address table. The address
table update routine is given as Figure 1.

-----------------------------------------------------------------------------
[I restricted all labels to a maximum of 9 characters in the listings here.]
[The first label on each DEFW line is the actual one used in the listing; a]
[second label in () is the one used in the text, which was not always      ]
[consistent with the assembler label.                                      ]
[Entries marked "*" indicate that the routine was relocated later.     JimG]
DB42 04E0     CMD_ADDRS DEFW E004,BORDERCOL (BORDER)
DB44 5200               DEFW 0052,CALC_CENT (CIRCLE_CENTRE)
DB46 5200               DEFW 0052,Q_ELLIPSE (QUARTER_ELLIPSE)
DB48 0000               DEFW 0000,not used
DB4A 0000               DEFW 0000,not used
DB4C 5200               DEFW 0052,ARC_RAD   (DRAW_ANR)
DB4E 5200               DEFW 0052,CIRC_THRU (CIRCLE_THRU)
DB50 5DDF               DEFW DF5D,COLOURS   (FLASH)
DB52 5DDF               DEFW DF5D,COLOURS   (OVER)
DB54 5200               DEFW 0052,RECTANGLE
DB56 5200               DEFW 0052,PARALLGRM (PARALLELOGRAM)
DB58 0000               DEFW 0000,not used
DB5A 9BDF               DEFW DF9B,RECALL
DB5C 5200               DEFW 0052,ARC_USING (DRAW_AU)
DB5E 5200               DEFW E690,ELLIPSE
DB60 5DDF               DEFW DF5D,COLOURS   (PAPER)
DB62 5DDF               DEFW DF5D,COLOURS   (INVERSE)
DB64 5200               DEFW 0052,TRIANGLE
DB66 80DF               DEFW DF80,CLEAR
DB68 0000               DEFW 0000,not used
DB6A 85DF               DEFW DF85,STORE
DB6C 5200               DEFW 0052,ARC_THRU  (DRAW_AT)
DB6E 38DF               DEFW DF38,CANCEL_MK (CANCEL_MARK)
DB70 5DDF               DEFW DF5D,COLOURS   (INK)
DB72 5DDF               DEFW DF5D,COLOURS   (BRIGHT)
DB74 C2DF               DEFW DFC2,USR_CALL  (USR)
DB76 24DF *             DEFW DF24,CURS_TYPE (CURSOR_TYPE)
DB78 B8DF               DEFW DFB8,CLEAR_SCR (CLS)
DB7A 5200               DEFW 0052,FILL
DB7C 04DF               DEFW DF04,DRAW_LINE
DB7E 30DF               DEFW DF30,MARK
DB80 0FE0               DEFW E00F,COPY_SCRN (COPY)
DB82 A4DE *             DEFW DEA4,ESCAPE
DB84 28DF               DEFW DF28,HIDE
DB86 5200               DEFW 0052,TEXT_MODE (TEXT)
DB88 BEDE               DEFW DEBE,UNDO
DB8A 5200               DEFW 0052,PAINT
DB8C FBDE               DEFW DEFB,PLOT
DB8E F3DE               DEFW DEF3,MOVE
-----------------------------------------------------------------------------

The new bits of program cover addresses DF3E to E01B (see Figure 2).
We start off with a subroutine called LOCATE, which is used in STORE
and RECALL, and then move onto a table, called COL_TABLE, which is
used by the colour functions. In Part Six of this series I'll get down
to some geometry - all this drawing rectangles and stuff.

See you then - bye bye.

-----------------------------------------------------------------------------
DF3E 010400   LOCATE    LD   BC,#0004      ;BC= number of bytes per memory
DF41 1114DB             LD   DE,CURSOR     ;DE points to cursor address
DF44 87                 ADD  A,A
DF45 87                 ADD  A,A
DF46 C658               ADD  A,#58
DF48 6F                 LD   L,A
DF49 62                 LD   H,D           ;HL point to required memory
DF4A C9                 RET

DF4B 500D12   COL_TABLE DEFB #50,#0D,#12   ;Information concerning FLASH
DF4E 520F15             DEFB #52,#0F,#15   ;Information concerning OVER
DF51 600C11             DEFB #60,#0C,#11   ;Information concerning PAPER
DF54 621014             DEFB #62,#10,#14   ;Information concerning INVERSE
DF57 700B10             DEFB #70,#0B,#10   ;Information concerning INK
DF5A 721113             DEFB #72,#11,#13   ;Information concerning BRIGHT

DF5D 214BDF   COLOURS   LD   HL,COL_TABLE  ;HL points to colour info table
DF60 45                 LD   B,L           ;BC= large number
DF61 EDB1               CPIR               ;Locate required entry to table
                                           ;(note that A contains low part of
                                           ;pointer into address table)
DF63 116FDF             LD   DE,COL_MES
DF66 EDA0               LDI                ;Alter program to print reqd message
DF68 1E77               LD   E,COL_CTR lo
DF6A EDA0               LDI                ;Alter program to select appropriate
                                           ;function
DF6C CDCCDC             CALL MESSAGE
DF6F 00       COL_MES   DEFS 01            ;Print required message
DF70 F5                 PUSH AF            ;Stack user's response
DF71 3E02               LD   A,#02
DF73 CD0116             CALL CHAN_OPEN     ;Select stream 2 (the screen)
DF76 3E00               LD   A,??          ;A= required control character
              COL_CTR   $-1
DF78 D7                 RST  #10           ;Print control code
DF79 F1                 POP  AF            ;A= user's response
DF7A D630               SUB  #30           ;A= required colour
DF7C D7                 RST  #10           ;Select required colour
DF7D C3AD1C             JP   PERMS+23      ;Make colour permanent
-----------------------------------------------------------------------------
DF80 DDCB01A6 CLEAR     RES  4,(JFLAGS) hi ;Free memory for use by UNDO
DF84 C9                 RET
DF85 CDCCDC   STORE     CALL MESSAGE
DF88 04                 DEFB #04           ;Print message "Store memory"
DF89 FE0D               CP   "enter"
DF8B 2807               JR   Z,ST_SCR      ;Jump if "enter" pressed
DF8D CD3EDF             CALL LOCATE        ;Locate required memory
DF90 EB                 EX   DE,HL
DF91 EDB0               LDIR               ;Store cursor position
DF93 C9                 RET
DF94 DDCB01E6 ST_SCR    SET  4,(JFLAGS) hi ;Signal "memory is being used"
DF98 C3C9DE   S/R_SCR   JP   COPY_SCRN     ;Store screen (note Z flag is set)
DF9B CDCCDC   RECALL    CALL MESSAGE
DF9E 05                 DEFB #05           ;Print message "Recall memory"
DF9F FE0D               CP   "enter"
DFA1 280E               JR   Z,REC_SCR     ;Jump if "enter" pressed
DFA3 CD3EDF             CALL LOCATE        ;Locate required memory
DFA6 E5                 PUSH HL            ;Stack memory address
DFA7 09                 ADD  HL,BC         ;Point to next memory
DFA8 2B                 DEC  HL            ;Point to last byte of current memory
DFA9 7E                 LD   A,(HL)        ;A= last byte of memory
DFAA E1                 POP  HL            ;HL points to required memory
DFAB FEB0               CP   #B0
DFAD D0                 RET  NC            ;Return if memory not in use
DFAE EDB0               LDIR               ;Recall memory
DFB0 C9                 RET
DFB1 DDCB0166 REC_SCR   BIT  4,(JFLAGS) hi
DFB5 20E1               JR   NZ,S/R_SCR    ;Recall screen if memory in use
DFB7 C9                 RET
-----------------------------------------------------------------------------
DFB8 CDCCDC   CLEAR_SCR CALL MESSAGE
DFBB 06                 DEFB #06           ;Print message "Clear screen?"
DFBC FE59               CP   "Y"
DFBE CA6B0D             JP   Z,CLS         ;Clear screen if required
DFC1 C9                 RET

DFC2 CDCCDC   USR_CALL  CALL MESSAGE
DFC5 09                 DEFB #09           ;Print messg "Machine code address?"
DFC6 210100             LD   HL,#0001
DFC9 E5       USR_LOOP  PUSH HL
DFCA FDCB30DE USR_KEY   SET  3,(FLAGS2)    ;Engage CAPS LOCK
DFCE CDDE15             CALL WAIT_KEY1     ;Wait for key to be pressed
DFD1 FE20               CP   #20
DFD3 282C               JR   Z,USR_ESC     ;Jump if ESCAPE pressed
DFD5 CD882C             CALL ALPHANUM
DFD8 30F0               JR   NC,USR_KEY    ;Jump unless letter or digit pressed
DFDA FE47               CP   "G"
DFDC 30EC               JR   NC,USR_KEY    ;Jump if "G" to "Z" pressed
DFDE F5                 PUSH AF
DFDF D7                 RST  #10           ;Print hex digit
DFE0 F1                 POP  AF
DFE1 D630               SUB  #30           ;Codes "0" to "9" now correct
DFE3 FE0A               CP   #0A
DFE5 3802               JR   C,USR_C       ;Jump if digit "0" to "9"
DFE7 D607               SUB  #07           ;Codes "A" to "F" now correct

DFE9 E1       USR_C     POP  HL            ;HL= "address so far"
DFEA 29                 ADD  HL,HL
DFEB 29                 ADD  HL,HL
DFEC 29                 ADD  HL,HL
DFED 29                 ADD  HL,HL         ;Shift HL one digit left
DFEE F5                 PUSH AF            ;Stack the carry flag
DFEF B5                 OR   L
DFF0 6F                 LD   L,A           ;Incorporate new digit
DFF1 F1                 POP  AF            ;Restore carry flag
DFF2 30D5               JR   NC,USR_LOOP   ;Loop back until digits collected
DFF4 E5                 PUSH HL            ;Stack m/code subroutine address
DFF5 CDDE15   USR_ENTER CALL WAIT_KEY1     ;Wait for key to be pressed
DFF8 FE20               CP   #20
DFFA 2805               JR   Z,USR_ESC     ;Jump if ESCAPE pressed
DFFC FE0D               CP   "enter"
DFFE 20F5               JR   NZ,USE_ENTER  ;Jump back unless "enter" pressed
E000 E5                 PUSH HL            ;Place dummy entry on stack
E001 E1       USR_ESC   POP  HL            ;Delete item from stack (either
                                           ;dummy entry or m/code address)
E002 1815               JR   UBC_LOWER     ;Jump to erase message from lower
                                           ;part of screen
-----------------------------------------------------------------------------
E004 CDCCDC   BORDERCOL CALL MESSAGE
E007 0E                 DEFB #0E           ;Print message "Border colour?"
E008 D630               SUB  #30           ;A= required border colour
E00A CD9722             CALL BORDER+3      ;Change border colour
E00D 180A               JR   UBC_LOWER     ;Jump to change colour of bottom
                                           ;two lines of screen
E00F CDCCDC   COPY_SCRN CALL MESSAGE
E012 0A                 DEFB #0A           ;Print message "Copy?"
E013 FE59               CP   "Y"
E015 C0                 RET  NZ            ;Return if reply was "N"
E016 CDAC0E             CALL COPY          ;Copy screen onto printer
E019 C36E0D   UBC_LOWER JP   CLS_LOWER     ;Reset lower part of screen
-----------------------------------------------------------------------------
