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
;--------------------------------------------------------------------