DrawTriangle:
;IN: x1,y1,u1,v1,x2,y2,u2,v2,x3,y3,u3,v3
;scherm = 96*64
;the following code was used to add 100 to the x coordinates, to see if the sign was the problem
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ld de, 100
; ld hl, (x1)
; add hl, de
; ld (x1), hl
; ld hl, (x2)
; add hl, de
; ld (x2), hl
; ld hl, (x3)
; add hl, de
; ld (x3), hl
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;---------------------------------------------------------------
; This part sorts the points so that Y1 <= Y2 <= Y3 so
; we can just draw each scanline below the last one.
;---------------------------------------------------------------
ld hl, (x1)
call Signed16To8
ld h, $FF
ld l, a
ld (x1), hl
ld hl, (x2)
call Signed16To8
ld h, $FF
ld l, a
ld (x2), hl
ld hl, (x3)
call Signed16To8
ld h, $FF
ld l, a
ld (x3), hl
ld hl, (y1)
ld de, (y2)
cpHLDE
jr c, Y1SmallerThanY2
ld hl, x1
ld de, dx1 ;temp location
ld bc, 6 ;size
ldir
ld hl, x2
ld de, x1
ld bc, 6
ldir
ld hl, dx1
ld de, x2
ld bc, 6
ldir
Y1SmallerThanY2:
ld hl, (y1)
ld de, (y3)
cpHLDE
jr c, Y1SmallerThanY3
ld hl, x1
ld de, dx1 ;temp location
ld bc, 6 ;size
ldir
ld hl, x3
ld de, x1
ld bc, 6
ldir
ld hl, dx1
ld de, x3
ld bc, 6
ldir
Y1SmallerThanY3:
ld hl, (y2)
ld de, (y3)
cpHLDE
jr c, Y2SmallerThanY3
ld hl, x2
ld de, dx1 ;temp location
ld bc, 6 ;size
ldir
ld hl, x3
ld de, x2
ld bc, 6
ldir
ld hl, dx1
ld de, x3
ld bc, 6
ldir
Y2SmallerThanY3:
; +++++ End of sorting code +++++
;----------------------------------------------------------
; Here, some variables are initialized. The delta
; variables (the variables which start with a 'd')
; contain the values that need to be added to
; the variables which start with a 't'. Variables
; with a 't' and a '1' are used for the start of
; the scanline. Those with a 't' and a '2' are used
; for the end of the scanline.
;----------------------------------------------------------
res 0, (IY) ;if this bit is 0, the routine is drawing the top half of the triangle. if it's 1, it's drawing the bottom half.
res 1, (IY) ;This bit is used to store if the deltas for the texture coordinates inside scanlines are already calculated. They are constants, so they only need to be calculated once per half.
ld hl, (y2)
ld de, (y1)
subFP ;This routine is for substracting fixed-point values, but here it's used to substract integer values.
ld h, l
ld l, 0
push hl
ld hl, (x2)
ld de, (x1)
subFP
ld h, l
ld l, 0
pop de
call DivFP
ld (dx1), hl
ld hl, (y3)
ld de, (y2)
subFP
ld h, l
ld l, 0
push hl
ld hl, (x3)
ld de, (x2)
subFP
ld h, l
ld l, 0
pop de
call DivFP
ld (dx2), hl
ld hl, (y3)
ld de, (y1)
subFP
ld h, l
ld l, 0
push hl
ld hl, (x3)
ld de, (x1)
subFP
ld h, l
ld l, 0
pop de
call DivFP
ld (dx3), hl
ld hl, (y2)
ld de, (y1)
subFP
ld h, l
ld l, 0
push hl
ld a, (u2)
ld h, a
ld l, 0
ld a, (u1)
ld d, a
ld e, 0
subFP
;ld h, l
;ld l, 0
pop de
call DivFP
ld (du1), hl
ld hl, (y3)
ld de, (y2)
subFP
ld h, l
ld l, 0
push hl
ld a, (u3)
ld h, a
ld l, 0
ld a, (u2)
ld d, a
ld e, 0
subFP
;ld h, l
;ld l, 0
pop de
call DivFP
ld (du2), hl
ld hl, (y3)
ld de, (y1)
subFP
ld h, l
ld l, 0
push hl
ld a, (u3)
ld h, a
ld l, 0
ld a, (u1)
ld d, a
ld e, 0
subFP
;ld h, l
;ld l, 0
pop de
call DivFP
ld (du3), hl
ld hl, (y2)
ld de, (y1)
subFP
ld h, l
ld l, 0
push hl
ld a, (v2)
ld h, a
ld l, 0
ld a, (v1)
ld d, a
ld l, 0
subFP
;ld h, l
;ld l, 0
pop de
call DivFP
ld (dv1), hl
ld hl, (y3)
ld de, (y2)
subFP
ld h, l
ld l, 0
push hl
ld a, (v3)
ld h, a
ld l, 0
ld a, (v2)
ld d, a
ld e, 0
subFP
;ld h, l
;ld l, 0
pop de
call DivFP
ld (dv2), hl
ld hl, (y3)
ld de, (y1)
subFP
ld h, l
ld l, 0
push hl
ld a, (v3)
ld h, a
ld l, 0
ld a, (v1)
ld d, a
ld e, 0
subFP
;ld h, l
;ld l, 0
pop de
call DivFP
ld (dv3), hl
ld hl, (x1)
bit 7, h
jr z, TPos1
ld (tx1+1),hl \ ld a, $FF \ ld (tx1),a
ld (tx2+1),hl \ ld a, $FF \ ld (tx2),a
jr TEnd1
TPos1:
ld (tx1+1),hl \ xor a \ ld (tx1),a ;store the 16bit integer at hl into 16.8 fixed point number tx1
ld (tx2+1),hl \ xor a \ ld (tx2),a
TEnd1:
ld hl, (y1)
ld (_ty), hl
ld a, (u1)
ld h, a
ld l, 0
ld (tu1), hl
ld (tu2), hl
ld a, (v1)
ld h, a
ld l, 0
ld (tv1), hl
ld (tv2), hl
;if Y1 == Y2, then we don't need to draw the first half.
ld hl, (Y1)
ld de, (y2)
cpHLDE
jp z, __TEndLoop
; +++++ End of initializing code +++++
;------------------------------------------------------------
; This is the loop in which the triangle is drawn.
; In each interval of the loop, a single scanline is
; drawn. When this loop finished, one half of the
; triangle is drawn.
;------------------------------------------------------------
TDrawLoop:
ld a, (_ty)
ld d, a
;if the Y of the scanline is negative, then go to the next one.
bit 7, a
jp nz, Clip
ld a, (_ty)
;If it reaches the bottom of the screen, then stop drawing the triangle.
cp 64
ret nc
;Initialize variables for the scanline
ld hl, (tu1)
ld (tmpu), hl
ld hl, (tv1)
ld (tmpv), hl
ld hl, (tu2)
ld (temp2), hl
ld hl, (tv2)
ld (temp3), hl
ld a, (tx2+1)
ld (temp+1), a
add a, 128
ld b, a
ld a, (tx1+1)
ld (temp), a
add a, 128
cp b
jr c, TOrdered
;jp po, TOrdered
ld hl, (tu2)
ld (tmpu), hl
ld hl, (tv2)
ld (tmpv), hl
ld hl, (tu1)
ld (temp2), hl
ld hl, (tv1)
ld (temp3), hl
ld a, (tx2+1)
ld (temp), a
ld a, (tx1+1)
ld (temp+1), a
TOrdered:
ld l, d
ld a, (temp)
;folowing line was for the test to see if the sign was the problem
;sub 100 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
bit 7, a
jr z, TGetPixel
xor a
TGetPixel:
call GetPixel
ld (mask), a
ld (pointer), hl
;If the deltas for the texture coordinates inside a scanline are already
;calculated, then calculating them again is a wast of cycles.
bit 1, (IY)
jr nz, TPlotLoop
ld hl, (tx1)
ld de, (tx2)
cpHLDE
jr z, TPlotLoop
ld a, (temp)
ld h, a
ld l, 0
ld a, (temp+1)
ld d, a
ld e, 0
subFP
push hl
ld hl, (tmpu)
ld de, (temp2)
subFP
pop de
call DivFP
ld (tmpdu), hl
ld a, (temp)
ld h, a
ld l, 0
ld a, (temp+1)
ld d, a
ld e, 0
subFP
push hl
ld hl, (tmpv)
ld de, (temp3)
subFP
pop de
call DivFP
ld (tmpdv), hl
set 1, (IY)
;---------------------------------------------------------------------
; In this loop, the scanline is drawn. One interval here
; draws one pixel. When the loop ends, one scanline is drawn.
;---------------------------------------------------------------------
TPlotLoop:
;If the x coordinate of the pixel is negative, then go to the next pixel.
ld a, (temp)
bit 7, a
jr nz, TNoCarry
;if the pixel goes of the right side of the screen, then go to the next scanline
cp 96
jp nc, Clip
;Everything with 4 ;'s behind it are for 16x16 textures. Remove those and the
;textures will be 8x8.
ld a, (tmpv+1)
add a, a ;;;;
ld hl, texture
add a, l
ld l, a
ld a, (tmpu+1)
bit 3, a ;;;;
jr z, TFirstByte ;;;;
res 3, a ;;;;
inc hl ;;;;
TFirstByte: ;;;;
ld b, a
inc b
ld a, (hl)
TshiftLoop:
rla
djnz TshiftLoop
ld a, (mask)
ld hl, (pointer)
jr c, TSetPixel
TResPixel:
;ld a, b
cpl
and (hl)
ld (hl), a
jr TEndPlot
TSetPixel:
;ld a, b
or (hl)
ld (hl), a
TEndPlot:
ld hl, mask
rrc (hl)
jr nc, TNoCarry
ld hl, (pointer)
inc hl
ld (pointer), hl
TNoCarry:
ld hl, (tmpu)
ld de, (tmpdu)
add hl, de
ld (tmpu), hl
ld hl, (tmpv)
ld de, (tmpdv)
add hl, de
ld (tmpv), hl
ld a, (temp+1)
ld b, a
ld a, (temp)
ld hl, temp
inc (hl)
cp b
jp nz, TPlotLoop
; +++++ End of pixel plotting code +++++
;If it's drawing the secound half, then make it recalculate the thexture deltas
;for inside the scanlines. This was to solve a bug in the texture mapping.
bit 0, (IY)
jr nz, aaaa ;I suddenly ran out of inspiration for label names
; res 1, (IY)
aaaa:
Clip:
ld hl,(tx1)
ld de, (dx1)
ld a, d
rla
sbc a, a
ld b, a
add hl, de
ld (tx1), hl
ld a, (tx1+2)
adc a, b
ld (tx1+2), a
ld hl,(tx2)
ld de, (dx3)
ld a, d
rla
sbc a, a
ld b, a
add hl, de
ld (tx2), hl
ld a, (tx2+2)
adc a, b
ld (tx2+2), a
ld hl, (tu1)
ld de, (du1)
add hl, de
ld (tu1), hl
ld hl, (tu2)
ld de, (du3)
add hl, de
ld (tu2), hl
ld hl, (tv1)
ld de, (dv1)
add hl, de
ld (tv1), hl
ld hl, (tv2)
ld de, (dv3)
add hl, de
ld (tv2), hl
ld hl, (_ty)
inc hl
ld (_ty), hl
ld de, (y2)
cpHLDE
jp c, TDrawLoop
;This is the end of the drawing loop
;If the secound half was drawn, then stop this routine.
bit 0, (IY)
jr nz, _TEnd
__TEndLoop:
;Here, some variables are initialized for drawing the secound half.
ld hl, (y2)
ld (_ty), hl
ld hl, (y3)
ld (y2), hl
ld hl, (dx2)
ld (dx1), hl
ld hl, (du2)
ld (du1), hl
ld hl, (dv2)
ld (dv1), hl
ld hl, (x2)
bit 7, h
jr nz, TPos4
ld (tx1+1),hl \ ld a, $FF \ ld (tx1),a
jr TEnd4
TPos4:
ld (tx1+1),hl \ xor a \ ld (tx1),a
Tend4:
ld a, (u2)
ld h, a
ld l, 0
ld (tu1), hl
ld a, (v2)
ld h, a
ld l, 0
ld (tv1), hl
set 0, (IY)
jp TDrawLoop
_TEnd:
ret
getPixel:
bit 7, a
ret nz
bit 7, l
ret nz
ld h, 0
ld d, h
ld e, l
add hl, hl
add hl, de
add hl, hl
add hl, hl
ld e, a
srl e
srl e
srl e
add hl, de
ld de, PlotSScreen
add hl, de
and 7
ld b, a
ld a, $80
ret z
rrca
djnz $-1
ret