Prev: 81B5 Up: Map Next: 820B
81DE: Screen address and bit mask for a point
Used by the routines at PIXEL_SET and PLOT_PIXEL.
Given the point in D and E, returns the screen address in HL and a one-bit mask in A. y is measured upwards, so the first thing it does is turn E into a scanline with $7F - E; the rest is the usual Spectrum interleave, bits 6-7 of the scanline to the address's high byte and bits 3-5 to its low.
This is the most expensive routine in the game -- 52% of the time spent drawing a room -- and it is called per pixel, by PLOT_PIXEL for every pixel drawn and by PIXEL_SET for every pixel the flood fill tests. About 269 T-states a call, of which the mask loop below is a third.
Input
D x, 0-255
E y, 0-127, measured up from scanline 127
Output
HL The screen address
A The bit mask for x within that byte
PIXEL_ADDRESS 81DE LD A,$7F Scanline = $7F - y
81E0 SUB E
81E1 LD L,A
81E2 AND $07
81E4 OR $40
81E6 LD H,A
81E7 LD A,L The scanline's bits 6-7 into the address's high byte
81E8 AND $C0
81EA RRCA
81EB RRCA
81EC RRCA
81ED OR H
81EE LD H,A
81EF LD A,L Its bits 3-5 into the low byte
81F0 AND $38
81F2 RLCA
81F3 RLCA
81F4 LD L,A
81F5 LD A,D x >> 3 gives the byte across
81F6 RRCA
81F7 RRCA
81F8 RRCA
81F9 AND $1F
81FB OR L
81FC LD L,A
81FD LD A,D x & 7 selects the bit...
81FE AND $07
8200 PUSH BC
8201 LD B,A
8202 INC B
8203 LD A,$01
PIXEL_ADDRESS_0 8205 RRC A ...by rotating a single bit that many places, one place at a time
8207 DJNZ PIXEL_ADDRESS_0
8209 POP BC
820A RET
The whole routine is a candidate for two lookup tables and an 8-byte mask table, which would roughly halve it. There is no room above the game for them -- the payload ends at $FC3F and the 960 bytes above that are live workspace -- but the printer buffer at $5B00 is page-aligned and unused: the game's PRINT drives the ZX Printer itself, through LINE_TO_PRINTER, and never goes through the ROM or its buffer.
Prev: 81B5 Up: Map Next: 820B