A86: Findpixel explanation - please read over for technical accuracy
[Prev][Next][Index][Thread]
A86: Findpixel explanation - please read over for technical accuracy
I am working on my 4th tutorial, and I was going to incorporate how the
findpixel works line by line. I studied it for a long time, and man is it
awesome! Findpixel was optimized so weirdly, so ingeniously, I am so amazed
how "convenient' everything is for this highly optimized routine to work.
Dan Eble has a very creative mind. Anyway, I just wanted somebody to look
over this and see if I understand it correctly so my tutorial will be
accurate. It uses so many programming techniques I probably learned the most
out of the Z80 just by studying this routine. Hopefully I interpreted it
correctly. If not good someone point out my mistakes?
Thanks all
-Matt Johnson
http://www.dogtech.com/cybop/ti86/
;--------------------------------------------------------------------
; The Eble-Yopp-Yopp-Eble-Eble-Eble-Yopp Fast FindPixel Routine :)
; 36 bytes / 121 t-states not counting ret or possible push/pop of BC
;--------------------------------------------------------------------
; Input: D = y
; E = x
; Output: HL= address of byte in video memory
; A = bitmask (bit corresponding to pixel is set)
; C is modified
;
; +-----------+
; |(0,0) | <- Screen layout
; | |
; | (127,63) |
; +-----------+
;
;--------------------------------------------------------------------
FindPixel:
ld hl,FP_Bits ; HL points to the address of FP_Bits
ld a,e ; Load x into a
and %00000111 ; Get last 3-bits, a = bit offset in range of 0-7
; Prepare for 16-bit simulated addition.
; Adds the correct number (the 3-bit offset) to HL
; to get the correct bitmask.
add a,l ; A = A + L, any overflow stored in Carry flag
ld l,a ; Apply changes to L , overflow is still in carry flag
adc a,h ; Adds the carry flag. The "side effect" is that L was added to A
earlier and L is not needed
sub l ; Subtracts L
ld h,a ; Apply changes to H
; Now a simulated 16-bit addition has been performed.
; Basically A was added to L, and any overflow was added to H
; So HL = HL + A
; Since A is in the range of 0-7, the correct bitmask has already been
selected.
; If a=%00000000 (a=1) then HL now points to value %10000000 (the first
bit)
; If a=%00000101 (a=5) then HL now points to value %00001000 (the fifth
bit)
ld c,(hl) ; c = bitmask for (hl)
ld hl,FP_RLD ; HL points to FP_RLD
ld (hl),d ; FP_RLD = Y
ld a,e ; A = X
; Divide X by 8, which is the correct byte in a row
; (8 bits/byte), Divide by 8, get the correct byte
rrca ; /2
rrca ; /2
rrca ; /2
rld ; Shift (HL) by 4, extra (upper) 4-bits from (HL)
were moved to A because of shifting.
; The lower 4-bits of A, which covers all of X, is
moved to the lower 4-bits of (hl),
; thus added to (hl). Summary: (y*16) + x
or $FC ; HL = HL + $FC – it wont overwrite the bits because the
most Y would ever be is 63 * 16 =
;1008, only affecting a total of 6-bits. The
4-bits in (hl) and the 2-least sig. Bits on A.
;Since OR $FC is %11111100, the last 2-bits are OR
’d, thus not affected. So $FC adds
;successfully. X is in the range of 0-7, Y in the
range of 0-63. Thus: HL = $FC00 + (Y*16) + X
ld l,(hl) ; L = (y*16) + x, 2 most significant
bits were shifted to H
ld h,a ; $FC was added to H, but left room for
the 2-bits shifted from L when Y*16
ld a,c ; now a = bitmask for (hl)
;121 t-states up to this point
ret
FP_RLD: .db $00
FP_Bits: .db $80,$40,$20,$10,$08,$04,$02,$01
.end
;--------------------------------------------------------------------