How to Plot a Pixel on Screen with the PLOT Routine

ZX Land #05

HOW TO PLOT A POINT ON THE SCREEN?

At the very beginning of the “Bajtek” assembler course, it was stated that it doesn’t matter whether a program is fast, as long as it is short. Most programming lecturers at universities take a similar view. Well, without wishing to dispute the opinions of acknowledged authorities, I’d like to present a PLOT routine that takes up 1 kB (±15 B), but executes in 68 cycles (clock ticks).

 10    LD  L,y
 20    LD  E,x

 30    LD  H,TABY1
 40    LD  D,TABX1
 50    LD  A,(DE)
 60    INC D
 70    ADD A,(HL)
 80    INC H
 90    LD  H,(HL)
100    LD  L,A
110    LD  A,(DE)
120    OR  (HL)
130    LD  (HL),A

Instructions on lines 10 and 20 are not part of the routine. They set the point’s coordinates; x and y are numbers representing the point’s coordinates on the screen.

Lines 30 and 40 set the high bytes of the table addresses, so registers HL and DE now point to positions y and x in tables TABY1 and TABX1, respectively. We load A with the value from TABX1, which gives the point’s horizontal position to the nearest character column. We increment D, so DE now contains the address of the x-th position in TABX2.

We add to A the value from TABY1, which gives the point’s vertical position to the nearest character row within a single memory page (256 bytes). We increment H, so HL contains the address of the y-th position in TABY2. We load H with the value from TABY2, which is the high byte of the screen address—that is, the point’s vertical position to the nearest pixel line. We load L with A, which is the already calculated low byte of the screen address, and load A with the value from TABX2, which gives the pixel’s position within the byte (to the exact point, of course). We now add A to the contents of the screen memory cell and store the result in screen memory (to get the OVER 1 option, use XOR (HL) instead of OR (HL)).

Note that HL is destroyed, but DE is not completely destroyed. If we don’t use DE before the next call to the routine, we can use DEC D instead of LD DE,TABX1.

The routine would be useless without the tables, so here they are. The tables are 256 bytes long, must start at the beginning of a memory page, and occupy consecutive pages, e.g. #8000 TABX1, #8100 TABX2, ...

TABX1 - 0*8, 1*8, 2*8 ...
        30*8, 31*8; that is,
        8 zeros, 8 ones, etc.

TABX2 - 128,64,32,16,8,4,2,1
        --------------------
                 *32
        (that is, repeat the
        sequence 32 times)

TABY1 - 0*8, 32*8, 64*8, 96*8
        128*8, 160*8, 192*8,
        224*8
        -----------------------
        repeat the whole thing
        3 times

        the remaining 64 bytes
        can contain anything—
        you can put a short
        routine here

TABY2 - 64,65,66,67,68,69,70,71
        -----------------------
        repeat the whole
        sequence 8 times

        72,73,74,75,76,77,78,79
        -----------------------
        repeat the whole
        sequence 8 times

        80,81,82,83,84,85,86,87
        -----------------------
        repeat the whole
        sequence 8 times

        the remaining 64 bytes
        can contain anything,
        preferably zeros

With the screen configured this way, point (0,0) is in the bottom-left corner of the screen, and (255,191) is in the top-right corner, so the screen area also includes the system window. If TABY2 is padded with zeros, plotting a point with a y-coordinate greater than 191 is safe. Another advantage of using tables is that the screen can be configured in any way, something I have made use of on several occasions.

DC PAK/EXODUS

Share your thoughts about the article