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

LIGHT SCREEN DESIGNER
ZX Computing, December 1984/January 1985
Part 04 of 13

Toni Baker defines some of the keys for use with the program and
suggests some modifications to the existing package


Shome mistakes ...

Just two mistakes in Part Three [There were actually several more than
that. JimG] - these were:
The byte at address DE88 should be 07, not 05 as printed.
The byte at address DE95 should be B6, not D6 as printed.

Right, that over with, let's proceed to the next gripping part, in
which we activate some of the keys. In Part One (with an amendment in
Part Two) we gave a drawing of a keyboard overlay for the Spectrum, in
which each key had a separate function. The keys which this article
will activate are as follows: UNDO (key zero), PLOT (key Q), DRAW_LINE
(key W), CURSOR_TYPE (key 0), MOVE (key A), MARK (key S), CANCEL_MARK
(key D), HIDE (key enter), and ESCAPE (key space).

Before we get down to pushing any buttons though, I suppose I ought to
tell you what each of these keys will actually do in the finished
program. As you press the cursor keys (and remember that SHIFT with a
cursor key produces an automatic REPEAT) you'll notice one cursor
moves about the screen as you direct it, whilst another cursor stands
still. The moving cursor is called the MAIN cursor, (or just "the
cursor"), whereas the stationary one is called the ORIGIN cursor.
Whenever you press the key PLOT then one single screen pixel at the
location of the (main) cursor will be PLOTted.

DRAW_LINE is also much as you'd expect it. It draws a line from the
ORIGIN cursor to the MAIN cursor. The ORIGIN cursor is, in effect, a
record of the last point PLOTted, and both PLOT and DRAW_LINE will
move the origin cursor to its new position. Another way of moving the
origin cursor is with the MOVE key, which simply moves this cursor
without changing the screen.

If you find the appearance of the cursors on the screen unsightly, you
can do one of two things. CURSOR_TYPE will change the appearance of
the cursor from the existing crosswires to a single dot (and back
again). Also, HIDE will render the cursors completely invisible, or
make them visible again.

MARK simply marks a point on the screen for later reference. At
present it will be of no use to us whatsoever but its subroutine is
included anyway. CANCEL_MARK of course nullifies the effect of MARK.

Finally we have UNDO - a cunning little function which will undo any
mistake - should you happen to make one. If, for instance, you draw a
line in the wrong place then UNDO will erase it. Simple, but effective.


Alterations

There are some alterations which require to be made to the program as
it exists so far. Specifically, the table of procedure addresses must
be updated so that each key we define has a subroutine address
associated with it. The full table runs from address DB42 to address
DB8F, but for now we shall only need to update addresses DB6E onwards.
Hunting around this article you should find a table of addresses
between DB6E and DB8F, and the bytes you will need to POKE into them
in order to make LSD Part Four workable.

-----------------------------------------------------------------------------
Null-Table
[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]
DB6E 38DF               DEFW DF38,CANCEL_MK (CANCEL_MARK)
DB70 5200               DEFW 0052,COLOURS   (INK)
DB72 5200               DEFW 0052,COLOURS   (BRIGHT)
DB74 5200               DEFW 0052,USR_CALL  (USR)
DB76 24DF *             DEFW DF24,CURS_TYPE (CURSOR_TYPE)
DB78 5200               DEFW 0052,CLEAR_SCR (CLS)
DB7A 5200               DEFW 0052,FILL
DB7C 04DF               DEFW DF04,DRAW_LINE
DB7E 30DF               DEFW DF30,MARK
DB80 5200               DEFW 0052,COPY_SCRN (COPY)
DB82 A4DE *             DEFW DE9E,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
-----------------------------------------------------------------------------

There is another alteration we can make to the program, and that is an
alteration / improvement in the MAIN_LOOP section given in Part Three.
In the flow diagram (in Part Three) there was a box marked "COPY THE
SCREEN IF NECESSARY". This copies the entire screen, including the
attributes bytes, into an area of RAM between addresses C000 and DAFF
- this is so that the UNDO procedure can work correctly - all the UNDO
routine needs to do is to unload the screen copy back onto the screen.
This UNDOing is therefore a complementary function to the COPY_SCREEN
routine itself, and it would be much more efficient if the two were
handled by a single subroutine. We may also make further tests on the
"IF NECESSARY" part of the clause, for not all of the procedures will
need to be UNDO-able. To this end I have revised the process and come
up with the routine ML_TEST which directly overwrites the original
code which appeared in Part Three.

-----------------------------------------------------------------------------
;ML-test
DE3D 21ADDE             LD   HL,NULL_TABLE 
DE40 011100             LD   BC,#0011      ;BC= length of null table
DE43 00                 NOP
DE44 00                 NOP
DE45 00                 NOP
DE46 00                 NOP
DE47 00                 NOP
DE48 00                 NOP
DE49 EDB1               CPIR               ;Is key pressed in null table?
DE4B 280A               JR   Z,ML_ACTION   ;Jump if so
DE4D 2141DB             LD   HL,JFLAGS hi
DE50 CB66               BIT  4,(HL)
DE52 CCC9DE             CALL Z,COPY_SCRN   ;Copy screen if allowed
DE55 CBAE               RES  5,(HL)
DE57          ML_ACTION $
[The line at DE55 was missing; added in Part 5. JimG]
-----------------------------------------------------------------------------

And onto the new bits.

New parts of the program shall now be given covering addresses DEAD to
DF3D. The first seventeen bytes are a table (called NULLTABLE) which
lists those keys which do not require UNDOing, and directly following
this is the UNDO / COPY_SCREEN routine which was talked about earlier.
At DEE6, however, we break off into a meaningless subroutine which is
not a full procedure in itself. It is called ADJUST_BD since it
prepares the B and D registers for the ROM's PLOT and DRAW routines.
Calling from the label ADJUST_B alters the B register only. From then
on follow the procedures for MOVE, PLOT, DRAW_LINE, CURSOR_TYPE, HIDE,
MARK and CANCEL_MARK.

Although the program is far from complete, it can still do some useful
things at present. You can draw straight lines, and you can rub them
out. In part Five of Light Screen Designer I'll define some more of
the keys for you - and put a little colour into things. See you then.

[There were several printing errors in the listings; corrected here. JimG]
-----------------------------------------------------------------------------
DEAD 0007080C NULLTABLE "BORDER","FLASH","OVER","RECALL"
DEB1 0F101214           "PAPER","INVERSE","CLEAR","STORE"
DEB5 1617181A           "CANCEL_MARK","INK","BRIGHT","CURSOR_TYPE"
DEB9 1E202123           "MARK","ESCAPE","HIDE","UNDO"
DEBD 26                 "MOVE"
-----------------------------------------------------------------------------
;COPY SCREEN subroutine
DEBE DDCB0166 UNDO      BIT  4,(JFLAGS) hi
DEC2 C0                 RET  NZ            ;Return if the memory is being used
                                           ;for some other purpose
DEC3 DDCB016E           BIT  5,(JFLAGS) hi
DEC7 C0                 RET  NZ            ;Return if screen copy has been
                                           ;corrupted
DEC8 A7                 AND  A             ;Reset the zero flag
DEC9 E5       COPY_SCRN PUSH HL
DECA 210040             LD   HL,D_FILE     ;HL points to start of screen
DECD 1100C0             LD   DE,D_FILE_COPY;DE points to start of copy
DED0 01001B             LD   BC,#1B00      ;BC length of screen memory
DED3 2801               JR   Z,CSC_1       ;Jump if making copy of screen
DED5 EB                 EX   DE,HL
DED6 EDB0     CSC_1     LDIR               ;Make required copy
DED8 210CDB             LD   HL,ORIGIN     ;HL points to cursor info
DEDB 1100DB             LD   DE,ORIGIN_COPY;DE points to duplicate cursor info
DEDE 4D                 LD   C,L           ;BC 000C = length of info memory
DEDF 2801               JR   Z,CSC_2       ;Jump if making copy of screen
DEE1 EB                 EX   DE,HL
DEE2 EDB0     CSC_2     LDIR               ;Make required copy
DEE4 E1                 POP  HL
DEE5 C9                 RET
-----------------------------------------------------------------------------
;Routine to prepare B and D registers for the ROM's PLOT routine
DEE6 3EAF     ADJUST_BD LD   A,#AF
DEE8 92                 SUB  D             ;A= adjusted coordinate
DEE9 57                 LD   D,A           ;D now adjusted
DEEA 3EAF     ADJUST_B  LD   A,#AF
DEEC 90                 SUB  B             ;A= adjusted coordinate
DEED 47                 LD   B,A           ;B now adjusted
DEEE C9                 RET
-----------------------------------------------------------------------------
;Move procedure
DEEF ED5B0EDB MOVE_X    LD   DE,(ORIGIN+2) ;DE pixel position of origin-cursor
                                           ;prior to move
DEF3 220CDB   MOVE      LD   (ORIGIN),HL   ;Change origin-cursor (address)
DEF6 ED430EDB           LD   (ORIGIN+2),BC ;Change origin-cursor (pixel pos)
DEFA C9                 RET
-----------------------------------------------------------------------------
;PLOT procedure
DEFB CDF3DE   PLOT      CALL MOVE          ;Move origin-cursor to new position
DEFE CDEADE             CALL ADJUST_B      ;Adjust the B register ready to PLOT
DF01 C3E522   J_PLOT    JP   PLOT_SUB      ;Plot the point
-----------------------------------------------------------------------------
;The DRAW_LINE procedure
;[This was rewritten in Part 11. JimG]
DF04 CDEFDE   DRAW_LINE CALL MOVE_X        ;Move origin-cursor to new position
DF07 CDE6DE             CALL ADJUST_BD     ;Adjust B and D registers
DF0A EB                 EX   DE,HL         ;HL= previous coordinates
DF0B 227D5C             LD   (COORDS),HL   ;Store origin-cursor coordinates
                                           ;as "last point PLOTted"
DF0E 110101             LD   DE,#0101
DF11 78                 LD   A,B           ;A= y coord of main cursor
DF12 94                 SUB  H             ;A= vertical DRAW parameter
DF13 3003               JR   NC,DL_1       ;Jump if positive or zero
DF15 2F                 CPL                ;A= ABS (vertical parameter)
DF16 16FF               LD   D,#FF         ;D indicates vertical parameter 
                                           ;is negative
DF18 47       DL_1      LD   B,A           ;B= ABS (vertical parameter)
DF19 79                 LD   A,C           ;A= x coord of main cursor
DF1A 95                 SUB  L             ;A= horizontal parameter
DF1B 3003               JR   NC,DL_2       ;Jump if positive or zero
DF1D 2F                 CPL                ;A= ABS (horizontal parameter)
DF1E 1EFF               LD   E,#FF         ;E indicates horizontal parameter 
                                           ;is negative
DF20 4F       DL_2      LD   C,A           ;C= ABS (horizontal parameter)
DF21 C3BA24             JP   DRAW_LINE+3   ;Draw line on screen
-----------------------------------------------------------------------------
;Subroutine to alter the image of the cursors on the screen
;[DF24-DF27 were overwritten by the altered DRAW_LINE routine in Part 11,]
;[so the CURS_TYPE entry point was moved to EA12 in Part 12.         JimG]
DF24 3E40     CURS_TYPE LD   A,#40         ;A has bit 6 set
DF26 1802               JR   CT_H
DF28 3E80     HIDE      LD   A,#80         ;A has bit 7 set
DF2A 2141DB   CT_H      LD   HL,JFLAGS hi
DF2D AE                 XOR  (HL)
DF2E 77                 LD   (HL),A        ;Complement the required flag
DF2F C9                 RET
-----------------------------------------------------------------------------
;These two routines place/remove the MARK cursor to/from the main cursor pos
DF30 2210DB   MARK      LD   (MARKER),HL
DF33 ED4312DB           LD   (MARKER+2),BC ;Move marker cursor
DF37 C9                 RET
DF38 2113DB   CANCEL_MK LD   HL,MARKER+3
DF3B 36FF               LD   (HL),#FF      ;Signal "marker cursor not in use"
DF3D C9                 RET
-----------------------------------------------------------------------------
