;****************************************************************************
;
; DRAWOBJ.MIP
;
;****************************************************************************

	SECTION	ASM
	OPT	at+,w-,c+,m-
	INCLUDE	..\spec_psx\gp.inc
	INCLUDE	..\spec_psx\gte.inc
	INCLUDE	..\spec_psx\draw.inc
	INCLUDE	..\spec_psx\room.inc

;----------------------------------------------------------------------------
; Constants
;----------------------------------------------------------------------------

SUBDIV3D	equ    	1		; 0 = 2d sub-division
SUBDIV_Z	equ	3072
;NEARZ		equ	(32+1)
NEARZ		equ	(0)

DCACHE		equ	$1f800000

; -------- DCACHE vertex capacity (all mod 3)

DCACHE_NVERTS	equ	126		; normal capacity

		if	SUBDIV3D
DCACHE_SNVERTS	equ	105		; 3d sub-division capacity
		else
DCACHE_SNVERTS	equ	114		; 2d sub-division capacity
		endif

DCACHE_NPVERTS	equ	255		; pickup capacity

; -------- GTE usage

POLYCOUNT	equr	C2_DQA		; 16bit
CLUTADDER	equr	C2_DQB

; -------- GTE usage after lighting

CLIPL		equr	C2_RGB		; clip window
CLIPR		equr	C2_RGB0
CLIPT		equr	C2_RGB1
CLIPB		equr	C2_RGB2

VERTS		equr	C2_RFC		; sub-division usage
FACE		equr	C2_GFC
PACKET		equr	C2_BFC
PRIMPTR		equr	C2_RBK
RASAVE		equr	C2_GBK

;----------------------------------------------------------------------------
; Type Definitions
;----------------------------------------------------------------------------

; -------- TEXTINFO structure

		rsreset
tiU0		rb	1
tiV0		rb	1
tiClut		rh	1
tiU1		rb	1
tiV1		rb	1
tiTpage		rh	1
tiU2		rb	1
tiV2		rb	1
tiId0		rb	1
tiId1		rb	1
tiU3		rb	1
tiV3		rb	1
tiPad		rh	1
tiSIZEOF	rb	0

; -------- Object Mesh Header

		rsreset
omX		rh	1
omY		rh	1
omZ		rh	1
omRadius	rh	1
omVertices	rb	1
omFlags		rb	1
omFaceOffset	rh	1
omSIZEOF	rb	0

; -------- stackframe

		rsreset
regs0		rw	1
regs1		rw	1
regs2		rw	1
regs3		rw	1
regs4		rw	1
regs5		rw	1
regs6		rw	1
regs7		rw	1
regfp		rw	1
reggp		rw	1
regra		rw	1
STACKFRAME	rb	0

; -------- ITEM_LIGHT structure

		rsreset
ilSunX		rw	1
ilSunY		rw	1
ilSunZ		rw	1
ilBulbX		rw	1
ilBulbY		rw	1
ilBulbZ		rw	1
ilDynamicX 	rw	1
ilDynamicY 	rw	1
ilDynamicZ 	rw	1
ilInit		rb	1
ilSunR		rb	1
ilSunG		rb	1
ilSunB		rb	1
ilAmbient	rb	1
ilBulbR		rb	1
ilBulbG		rb	1
ilBulbB		rb	1
ilDynamicR 	rb	1
ilDynamicG 	rb	1
ilDynamicB 	rb	1
ilPad		rb	1
SIZEOF_ITEMLIGHT rb	0

; -------- MATRIX3D structure

		rsreset
m00		rh	1
m01		rh	1
m02		rh	1
m10		rh	1
m11		rh	1
m12		rh	1
m20		rh	1
m21		rh	1
m22		rh	1
mPad		rh	1
mx		rw	1
my		rw	1
mz		rw	1
SIZEOF_MATRIX3D	rb	0


; -------- SUBDIV structure

	 	rsreset
vRGB		rw	1		; 24bit RGB
vSX		rh	1		; screen x
vSY		rh	1		; screen y
vSZ		rh	1		; screen z
		if	SUBDIV3D
vPad		rb	2
vX		rh	1		; world x
vY		rh	1		; world y
vZ		rh	1		; world z
		endif
vU		rb	1		; texture u
vV		rb	1		; texture v
SIZEOF_SDVERTEX	rb	0

; -------- DCACHE usage structure

		rsreset
dcV0		rb	SIZEOF_SDVERTEX
dcV1		rb	SIZEOF_SDVERTEX
dcV2		rb	SIZEOF_SDVERTEX
dcV3		rb	SIZEOF_SDVERTEX
dcV4		rb	SIZEOF_SDVERTEX
dcV5		rb	SIZEOF_SDVERTEX
dcV6		rb	SIZEOF_SDVERTEX
dcV7		rb	SIZEOF_SDVERTEX
dcV8		rb	SIZEOF_SDVERTEX
dcVertices	rw	2*DCACHE_SNVERTS

;----------------------------------------------------------------------------
; Externals
;----------------------------------------------------------------------------

	XREF	db			; DB_STRUCT db
	XREF	tsv_buffer		; SVECTOR tsv_buffer[]
	XREF	psxtextinfo		; PSXTEXTINFO *psxtextinfo
	XREF	DownLoadMatrix
	XREF	phd_top
	XREF	phd_left
	XREF	phd_right
	XREF	phd_bottom

	XREF	LightPos

;----------------------------------------------------------------------------
; Data
;----------------------------------------------------------------------------

	XDEF	Div3Tab

Div3Tab	db	dcV0,dcV1		; vertex pairs
	db	dcV1,dcV2
	db	dcV2,dcV0
	db	0,0
	db	dcV0,dcV3,dcV5,0	; poly vertices
	db	dcV3,dcV1,dcV4,0
	db	dcV3,dcV4,dcV5,0
	db	dcV5,dcV4,dcV2,0

Div4Tab	db	dcV0,dcV1		; vertex pairs
	db	dcV1,dcV3
	db	dcV2,dcV3
	db	dcV0,dcV2
	db	dcV0,dcV3
	db	0,0
	db	dcV0,dcV4,dcV7,dcV8	; poly vertices
	db	dcV4,dcV1,dcV8,dcV5
	db	dcV7,dcV8,dcV2,dcV6
	db	dcV8,dcV5,dcV6,dcV3

;----------------------------------------------------------------------------
; Local Routines
;----------------------------------------------------------------------------

;----------------------------------------------------------------------------
;IniPrim
;
;Purpose:	Initialises a sub-divided triangle primitive
;
;Inputs:	s4 = xy0
;		s5 = xy1
;		s6 = xy2
;		t6 = ptr to vertex #0
;		t7 = ptr to vertex #1
;		t8 = ptr to vertex #2
;
;Outputs:	None
;
;Usage:		fp/gp/at/t2-t5
;
;----------------------------------------------------------------------------

IniPrim lw	t1,vRGB(t6)
	lhu	t6,vU(t6)
	lw	t2,vRGB(t7)
	lhu	t7,vU(t7)
	lw	t3,vRGB(t8)
	lhu	t8,vU(t8)
	or	t6,fp			; Clut
	or	t7,gp			; Tpage

	sw	t1,gtRGB0(s0)
	sw	s4,gtX0(s0)
	sw	t6,gtU0(s0)
	sw	t2,gtRGB1(s0)
	sw	s5,gtX1(s0)
	sw	t7,gtU1(s0)
	sw	t3,gtRGB2(s0)
	sw	s6,gtX2(s0)
	mfc2	t1,C2_OTZ
	sw	t8,gtU2(s0)

	slt	t2,t1,NEARZ		; clipped off front ?
	bnez	t2,@exit
	sll	t1,2
	add	t1,a3

	lw	t2,0(t1)		; AddPrim
	sw	s0,0(t1)
	or	t2,at
@exit	jr	ra
	sw	t2,0(s0)

;----------------------------------------------------------------------------
;InitSubDiv
;
;Purpose:	Generic sub-division initialisation routine
;
;Inputs:	s4 = xy0
;		s5 = xy1
;		s6 = xy2
;		s7 = xy3
;		t2 = uv0
;		t3 = uv1
;		t4 = uv2
;		t5 = uv3
;		t6 = rgb0
;		t7 = rgb1
;		t8 = rgb2
;		t9 = rgb3
;		t1 = ot ptr
;
;Outputs:	fp = clut << 16
;		gp = tpage << 16
;
;Usage:		fp/gp/at/t2-t5
;
;----------------------------------------------------------------------------

InitSubDiv:
	ctc2	t0,PACKET		; save texture packet
	lui	at,$ffff
	and	fp,t2,at		; fp = Clut
	and	gp,t3,at		; gp = Tpage
;########
	move	s3,t1			; s3 = ot ptr
;########

	lui	t0,DCACHE>>16
	lui	at,$ff00		; at = id
	and	at,t6

	if	SUBDIV3D
	cfc2	t1,FACE
	cfc2	s7,VERTS
	endif

	sw	t6,dcV0+vRGB(t0)	; initialise vertex #0
	sh	t2,dcV0+vU(t0)
	sw	s4,dcV0+vSX(t0)
	if	SUBDIV3D
	sll	s4,t1,3
	andi	s4,$7f8
	add	s4,s7
	lw	t6,0(s4)
	lh	t2,4(s4)
	sw	t6,dcV0+vX(t0)
	sh	t2,dcV0+vZ(t0)
	endif

	or	t7,at			; initialise vertex #1
	sw	t7,dcV1+vRGB(t0)
	sh	t3,dcV1+vU(t0)
	sw	s5,dcV1+vSX(t0)
	if	SUBDIV3D
	srl	s5,t1,5
	andi	s5,$7f8
	add	s5,s7
	lw	t7,0(s5)
	lh	t3,4(s5)
	sw	t7,dcV1+vX(t0)
	sh	t3,dcV1+vZ(t0)
	endif

	or	t8,at			; initialise vertex #2
	sw	t8,dcV2+vRGB(t0)
	sh	t4,dcV2+vU(t0)
	if	SUBDIV3D
	sw	s6,dcV2+vSX(t0)
	srl	s6,t1,13
	andi	s6,$7f8
	add	s6,s7
	lw	t8,0(s6)
	lh	t4,4(s6)
	sw	t8,dcV2+vX(t0)
	jr	ra
	sh	t4,dcV2+vZ(t0)
	else
	jr	ra
	sw	s6,dcV2+vSX(t0)
	endif

;----------------------------------------------------------------------------
;SubDiv
;
;Purpose:	Interpolates vertex pairs
;
;Inputs:	s4 = ptr to vertex construction table
;		s5 = ptr to destination vertex buffer
;		s6 = ptr to vertex base
;		s7 = # vertices to create -1
;		t9 = rgb mask ($f8f8f8)
;
;Outputs:	None
;
;Usage:		t0-t7/s4/s5/s7
;
;----------------------------------------------------------------------------

SubDiv	lh	t1,0(s4)		; t1 = vertex indices
	addi	s4,2
	andi	t0,t1,$ff		; t0 = vertex #0 ptr
	or	t0,s6
	srl	t1,8			; t1 = vertex #1 ptr
	or	t1,s6

	if	SUBDIV3D		; subdivide co-ordinates
	lh	t2,vX(t0)
	lh	t3,vY(t0)
	lh	t4,vZ(t0)
	lh	t5,vX(t1)
	lh	t6,vY(t1)
	lh	t7,vZ(t1)
	add	t2,t5
	sra	t2,1
	add	t3,t6
	sra	t3,1
	add	t4,t7
	sra	t4,1
	sll	t3,16
	andi	t2,$ffff
	or	t2,t3
	mtc2	t2,C2_VXY0
	mtc2	t4,C2_VZ0
	lbu	t4,vU(t0)
	RTPS
	else
	lh	t2,vSX(t0)
	lh	t3,vSY(t0)
	lh	t4,vSX(t1)
	lh	t5,vSY(t1)
	add	t2,t4
	srl	t2,1
	add	t3,t5
	srl	t3,1
	lbu	t4,vU(t0)
	endif

	lbu	t5,vV(t0)		; subdivide UVs
	lbu	t6,vU(t1)
	lbu	t7,vV(t1)
	add	t4,t6
	srl	t4,1
	add	t5,t7

	lw	t6,vRGB(t0)		; subdivide rgbs
	lw	t7,vRGB(t1)
	srl	t5,1
	add	t6,t7
	srl	t6,1
	and	t6,t9

	if	SUBDIV3D		; store interpolated vertex
	sw	t6,vRGB(s5)
	sb	t4,vU(s5)
	sb	t5,vV(s5)
	swc2	C2_SXY2,vSX(s5)
	swc2	C2_SZ3,vSZ(s5)
	else
	sw	t6,vRGB(s5)
	sh	t2,vSX(s5)
	sh	t3,vSY(s5)
	sb	t4,vU(s5)
	sb	t5,vV(s5)
	endif

	addi	s5,SIZEOF_SDVERTEX
	bnez	s7,SubDiv
	subi	s7,1
	jr	ra
	addi	t0,s4,2			; t0 = ptr to poly construction table

;----------------------------------------------------------------------------
;SubDiv3
;
;Purpose:	Triangle sub-division routine
;
;Inputs:	a3 = ot
;		s0 = prim ptr
;		s1 = prim end
;		s3 = prim length
;
;Outputs:	None
;
;Usage:		s2-s7/t2-t9/at
;
;----------------------------------------------------------------------------

SubDiv3	ctc2	ra,RASAVE
	jal	InitSubDiv		; initialise source vertices
	move	s3,gp			; s3 = prim len

	swc2	C2_SZ1,dcV0+vSZ(t0)
	swc2	C2_SZ2,dcV1+vSZ(t0)
	swc2	C2_SZ3,dcV2+vSZ(t0)

; --------- interpolate vertices

	lui	s4,Div3Tab>>16		; s4 = ptr to poly construction table
	ori	s4,Div3Tab&$ffff
	ori	s5,t0,dcV3		; s5 = vertex destination
	move	s6,t0			; s6 = workspace
	ori	s7,zero,2		; s7 = # vertices to create -1
	lui	t9,$fff8 		; t9 = rgb mask
	jal	SubDiv
	ori	t9,$f8f8

; --------- initialise primitives

	ori	t5,zero,3		; t1 = # polys to create
@iloop:
	slt	at,s0,s1		; enough primitives ?
	beqz	at,@inext		; EQ = no, skip face
	addi	t0,4
	lw	t9,-4(t0)		; t5 = vertex indices

	lui	at,DCACHE>>16
	andi	t6,t9,$ff		; t2 = vertex 0 ptr
	or	t6,at
	srl	t7,t9,8			; t3 = vertex 1 ptr
	andi	t7,$ff
	or	t7,at
	srl	t8,t9,16		; t4 = vertex 2 ptr
	or	t8,at
	lwc2	C2_SZ1,vSZ(t6)
	lwc2	C2_SZ2,vSZ(t7)
	lwc2	C2_SZ3,vSZ(t8)

	lw	s4,vSX(t6)		; clip poly
	lw	s5,vSX(t7)
	lw	s6,vSX(t8)
	AVSZ3				; AverageZ3 (5)
	jal	ClipXY
	move	s7,s6
	bnez	at,@inext		; NE = clipped
	nop

	jal	IniPrim
	lui	at,GT3_LEN<<8		; s2 = prim len
;##	lui	s2,GT3_LEN<<8		; s2 = prim len
	addi	s0,SIZEOF_GT3
@inext:
	bnez	t5,@iloop
	subi	t5,1
	cfc2	ra,RASAVE		; restore ra
	cfc2	t0,PACKET		; restore texture packet
	move	t1,s3			; restore ot ptr
	lui	fp,$00f8		; s2 = RGB mask
	jr	ra
	lui	gp,GT3_LEN<<8		; gp = prim len

;----------------------------------------------------------------------------
;SubDiv4
;
;Purpose:	Quad sub-division routine
;
;Inputs:	a3 = ot
;		s0 = prim ptr
;		s1 = prim end
;		s3 = prim length
;
;Outputs:	None
;
;Usage:		s2-s7/t2-t9/at
;
;----------------------------------------------------------------------------

SubDiv4	ctc2	ra,RASAVE
	jal	InitSubDiv		; initialise first 3 vertices
	move	s2,s7

	swc2	C2_SZ0,dcV0+vSZ(t0)
	swc2	C2_SZ1,dcV1+vSZ(t0)
	swc2	C2_SZ2,dcV2+vSZ(t0)
	swc2	C2_SZ3,dcV3+vSZ(t0)

	or	t9,at			; initialise vertex #3
	sw	t9,dcV3+vRGB(t0)
	sh	t5,dcV3+vU(t0)
	sw	s2,dcV3+vSX(t0)
	if	SUBDIV3D
	srl	t1,21
	andi	t1,$7f8
	add	s7,t1
	lw	t9,0(s7)
	lh	t5,4(s7)
	sw	t9,dcV3+vX(t0)
	sh	t5,dcV3+vZ(t0)
	endif

; --------- interpolate vertices

	lui	s4,Div4Tab>>16		; s4 = ptr to poly construction table
	ori	s4,Div4Tab&$ffff
	ori	s5,t0,dcV4		; s5 = vertex destination
	move	s6,t0			; s6 = workspace
	ori	s7,zero,4		; s7 = # vertices to create -1
	lui	t9,$fff8 		; t9 = rgb mask
	jal	SubDiv
	ori	t9,$f8f8

; --------- initialise primitives

	ori	t5,zero,3		; t5 = # polys to create -1
@iloop:
	slt	at,s0,s1		; enough primitives ?
	beqz	at,@inext		; EQ = no, skip face
	addi	t0,4
	lw	t9,-4(t0)		; t9 = vertex indices

	lui	at,DCACHE>>16
	andi	t6,t9,$ff		; t6 = vertex 0 ptr
	or	t6,at
	srl	t7,t9,8			; t7 = vertex 1 ptr
	andi	t7,$ff
	or	t7,at
	srl	t8,t9,16		; t8 = vertex 2 ptr
	andi	t8,$ff
	or	t8,at
	srl	t9,24			; t9 = vertex 3 ptr
	or	t9,at
	lwc2	C2_SZ0,vSZ(t6)		; load screen z's into GTE
	lwc2	C2_SZ1,vSZ(t7)
	lwc2	C2_SZ2,vSZ(t8)
	lwc2	C2_SZ3,vSZ(t9)

	lw	s4,vSX(t6)		; clip poly
	lw	s5,vSX(t7)
	lw	s6,vSX(t8)
	AVSZ4				; AverageZ4 (6)
	jal	ClipXY
	lw	s7,vSX(t9)
	bnez	at,@inext		; NE = clipped
	lw	t4,vRGB(t9)

	jal	IniPrim
	lui	at,GT4_LEN<<8		; at = prim len
;##	lui	s2,GT4_LEN<<8		; s2 = prim len

	lhu	t9,vU(t9)		; initialise vertex #3
	sw	t4,gtRGB3(s0)
	sw	s7,gtX3(s0)
	sw	t9,gtU3(s0)
	addi	s0,SIZEOF_GT4
@inext:
	bnez	t5,@iloop
	subi	t5,1
	cfc2	ra,RASAVE		; restore ra
	cfc2	t0,PACKET		; restore texture packet
	move	t1,s3			; restore ot ptr
	lui	fp,$00f8		; fp = RGB mask
	jr	ra
	lui	gp,GT4_LEN<<8		; gp = prim len

;----------------------------------------------------------------------------
;UnpackRGB
;
;Purpose:	Unpacks 3 15bit RGBs into 24bit colour vectors
;
;Inputs:        t6 = rgb #1
;		t7 = rgb #2
;		t8 = rgb #3
;		fp = $00f80000
;		at = primitive id
;
;Outputs:       t6 = CVECTOR #1
;		t7 = CVECTOR #2
;		t8 = CVECTOR #3
;
;Usage:		t2/t3/at
;
;Timing:	28
;
;----------------------------------------------------------------------------

UnpackRGB:
	srl	t2,t6,7			; convert 5bit RGBs into 24bit RGBs
	and	t2,fp
	srl	t3,t6,10
	andi	t3,$f800
	srl	t6,13
	andi	t6,$f8
	or	t6,t3
	or	t6,t2

	srl	at,24			; primitive ID in top 8 bits
	sll	at,24
	or	t6,at

	srl	t2,t7,7
	and	t2,fp
	srl	t3,t7,10
	andi	t3,$f800
	srl	t7,13
	andi	t7,$f8
	or	t7,t3
	or	t7,t2

	srl	t2,t8,7
	and	t2,fp
	srl	t3,t8,10
	andi	t3,$f800
	srl	t8,13
	andi	t8,$f8
	or	t8,t3
	jr	ra
	or	t8,t2

;----------------------------------------------------------------------------
;ClipXY
;
;Purpose:	Clips four sets of screen co-ordinates against the current
;		clip window.
;
;Inputs:	s4 = xy #1
;		s5 = xy #2
;		s6 = xy #3
;		s7 = xy #4
;
;Outputs:   	at = clip flag
;
;Usage:		at/t1-t4/s2
;
;Timing:
;
;----------------------------------------------------------------------------

ClipXY	mfc2	t3,CLIPT
	mfc2	t4,CLIPB
	slt	at,s4,t3		; top clip
	beqz	at,@bclip
	slt	at,s5,t3
	beqz	at,@bclip
	slt	at,s6,t3
	beqz	at,@bclip
	slt	at,s7,t3
	bnez	at,@clipped
@bclip:
	slt	at,s4,t4		; bottom clip
	bnez	at,@lclip
	slt	at,s5,t4
	bnez	at,@lclip
	slt	at,s6,t4
	bnez	at,@lclip
	slt	at,s7,t4
	beqz	at,@clipped
@lclip:
	sll	t1,s4,16
	sll	t2,s5,16
	sll	t3,s6,16
	mfc2	s2,CLIPL
	sll	t4,s7,16
	slt	at,t1,s2		; left clip
	beqz	at,@rclip
	slt	at,t2,s2
	beqz	at,@rclip
	slt	at,t3,s2
	beqz	at,@rclip
	slt	at,t4,s2
	bnez	at,@clipped
@rclip:
	mfc2	s2,CLIPR
	nop
	slt	at,t1,s2		; right clip
	bnez	at,@ok
	slt	at,t2,s2
	bnez	at,@ok
	slt	at,t3,s2
	bnez	at,@ok
	slt	at,t4,s2
	beqz	at,@clipped
	nop
@ok:
	jr	ra
	move	at,zero
@clipped:
	jr	ra
	ori	at,zero,1

InitGT3	sw	t6,gtRGB0(s0)
	sw	s4,gtX0(s0)
	sw	t2,gtU0(s0)
	sw	t7,gtRGB1(s0)
	sw	s5,gtX1(s0)
	sw	t3,gtU1(s0)
	sw	t8,gtRGB2(s0)
	sw	s6,gtX2(s0)
	jr	ra
	sw	t4,gtU2(s0)

InitGT4	sw	t6,gtRGB0(s0)
	sw	s4,gtX0(s0)
	sw	t2,gtU0(s0)
	sw	t7,gtRGB1(s0)
	sw	s5,gtX1(s0)
	sw	t3,gtU1(s0)
	sw	t8,gtRGB2(s0)
	sw	s6,gtX2(s0)
	sw	t4,gtU2(s0)
	sw	t9,gtRGB3(s0)
	sw	s7,gtX3(s0)
	jr	ra
	sw	t5,gtU3(s0)

;----------------------------------------------------------------------------
;DrawClippedMesh
;
;Purpose:	Draws a single object mesh with clipping
;
;Inputs:	a0 = vertex cache
;		a1 = mesh ptr
;		a2 = TEXTINFO structure ptr
;		a3 = OT ptr
;		s0 = primitive ptr
;		s1 = primitive limiter
;		fp = RGB mask ?
;		gp = primitive length
;		v0 = # triangles
;
;Outputs:	None
;
;Usage:		a0-a3/t0-t9/v0-v1
;
;----------------------------------------------------------------------------

DrawClippedMesh:
	GPR.lh	t0,phd_left		; read current clip window
	GPR.lh	t1,phd_right
	GPR.lh	t2,phd_top
	GPR.lh	t3,phd_bottom
	sll	t0,16
	sll	t1,16
	sll	t2,16
	sll	t3,16
	mtc2	t0,CLIPL
	mtc2	t1,CLIPR
	mtc2	t2,CLIPT
	mtc2	t3,CLIPB

;--------------------------------------
; Draw Triangles
;--------------------------------------

	lui	gp,GT3_LEN<<8		; gp = primitive size
	beqz	v0,@quad		; EQ = no triangles
	addi	a1,4

; -------- packet loop

	lw	t0,0(a1)		; read 4 textures
@tploop	addi	a1,4
	ori	v1,zero,3		; v1 = inner-loop count

; -------- face loop

@tloop	lw	t1,0(a1)		; t1 = face
	slt	at,s0,s1		; enough primitives ?
	beqz	at,@tnext		; EQ = no, skip face
	subi	v0,1

; -------- fetch and clip vertices

	srl	t8,t1,13		; calc vertex pointers
	andi	t8,$7f8
	add	t8,a0
	srl	t7,t1,5
	andi	t7,$7f8
	add	t7,a0
	sll	t6,t1,3
	andi	t6,$7f8
	add	t6,a0
	lw	s4,0(t6)		; load vertices into GTE
	lw	s5,0(t7)
	lw	s6,0(t8)
	mtc2	s4,C2_SXY0
	mtc2	s5,C2_SXY1
	mtc2	s6,C2_SXY2
	andi	t5,t0,$ff		; t5 = texture bits 0-7
	srl	t1,16
	NCLIP				; NormalClip (8)

	andi	t1,$ff00 		; t1 = texture bits 8-15
	or	t5,t1			; t5 = texture #
	jal	ClipXY
	move	s7,s6			; s7 = xy2
	bnez	at,@tnext		; NE = clipped
	srl	t0,8

	lwc2	C2_SZ1,4(t6)
	lwc2	C2_SZ2,4(t7)
	lwc2	C2_SZ3,4(t8)
	mfc2	at,C2_MAC0
	AVSZ3				; AverageZ3 (5)

	bltz	at,@tnext		; <0 = facing into screen
	lw	t6,4(t6)		; fetch vertex z & rgb components
	lw	t7,4(t7)
	lw	t8,4(t8)
	sll	t5,4

	mfc2	t1,C2_OTZ		; t1 = screen zpos
	add	t5,a2
	slt	at,t1,OTSIZE		; within OT ?
	beqz	at,@tnext		; EQ = outside OT
	slt	at,t1,NEARZ		; clipped off front ?
	bnez	at,@tnext		; NE = clipped
	sll	t1,2

; -------- initialise primitive

	lw	t4,tiU2(t5)		; uv2 & primitive ids
	jal	UnpackRGB		; unpack rgbs
	sll	at,t4,8

	cfc2	at,CLUTADDER
	lw	t2,tiU0(t5)		; uv0 & clut
	lw	t3,tiU1(t5)		; uv1 & tpage
	jal	InitGT3
	subu	t2,at

; -------- AddPrim

	add	t1,a3			; t1 = ot ptr
	lw	t2,0(t1)
	sw	s0,0(t1)
	or	t2,gp
	sw	t2,0(s0)
	addi	s0,SIZEOF_GT3
@tnext:
	beqz	v0,@quad
	addi	a1,4
	bnez	v1,@tloop
	subi	v1,1
	j	@tploop
	lw	t0,0(a1)		; read 4 textures

;--------------------------------------
; Draw Quads
;--------------------------------------

@quad	cfc2	v0,POLYCOUNT		; restore # quads
	lui	gp,GT4_LEN<<8		; s3 = primitive length
	beqz	v0,DrawExit		; EQ = no quads

; -------- packet loop

	lw	t0,0(a1)		; read 2 textures
@qploop	addi	a1,4
	ori	v1,zero,1		; v1 = packet loop count

; -------- face loop

@qloop	lw	t1,0(a1)		; t1 = face
	slt	at,s0,s1		; enough primitives ?
	beqz	at,@qnext		; EQ = no, skip face
	subi	v0,1

; -------- fetch and clip vertices

	srl	t9,t1,21		; calc vertex pointers
	andi	t9,$7f8
	srl	t8,t1,13
	andi	t8,$7f8
	add	t8,a0
	srl	t7,t1,5
	andi	t7,$7f8
	add	t7,a0
	sll	t6,t1,3
	andi	t6,$7f8
	add	t6,a0
	lw	s4,0(t6)		; load vertices into GTE
	lw	s5,0(t7)
	lw	s6,0(t8)
	mtc2	s4,C2_SXY0
	mtc2	s5,C2_SXY1
	mtc2	s6,C2_SXY2
	add	t9,a0
	andi	t5,t0,$ffff		; t5 = texture #
	NCLIP				; NormalClip (8)

	jal	ClipXY
	lw	s7,0(t9)		; s7 = xy3
	bnez	at,@qnext		; NE = clipped
	srl	t0,16

	lwc2	C2_SZ0,4(t6)
	lwc2	C2_SZ1,4(t7)
	lwc2	C2_SZ2,4(t8)
	lwc2	C2_SZ3,4(t9)
	mfc2	at,C2_MAC0
	AVSZ4 				; AverageZ4 (6)

	bltz	at,@qnext		; <0 = facing into screen
	lw	t6,4(t6)		; fetch vertex z & rgb components
	lw	t7,4(t7)
	lw	t8,4(t8)
	lw	t9,4(t9)
	sll	t5,4			; calc texture index

	mfc2	t1,C2_OTZ		; t9 = screen zpos
	add	t5,a2			; + PSXTEXTINFO org
	slt	at,t1,OTSIZE		; within OT ?
	beqz	at,@qnext		; EQ = outside OT
	slt	at,t1,NEARZ		; clipped off front ?
	bnez	at,@qnext		; NE = clipped
	sll	t1,2

; -------- initialise primitive

	srl	t2,t9,7			; unpack 4th rgb
	and	t2,fp
	srl	t3,t9,10
	andi	t3,$f800
	srl	t9,13
	andi	t9,$f8
	or	t9,t3
	or	t9,t2

	lw	t4,tiU2(t5)		; uv3 & primitive ids
	jal	UnpackRGB		; unpack rgbs
	move	at,t4

	cfc2	at,CLUTADDER
	lw	t2,tiU0(t5)		; uv0 & clut
	lw	t3,tiU1(t5)		; uv1 & tpage
	lw	t5,tiU3(t5)		; uv2
	jal	InitGT4
	subu	t2,at			; why does this crash ?

; -------- AddPrim

	add	t1,a3
	lw	t2,0(t1)
	sw	s0,0(t1)
	or	t2,gp
	sw	t2,0(s0)
	addi	s0,SIZEOF_GT4
@qnext:
	beqz	v0,DrawExit
	addi	a1,4
	bnez	v1,@qloop
	subi	v1,1
	j	@qploop
	lw	t0,0(a1)		; read 2 textures

;----------------------------------------------------------------------------
;DrawSubDivMesh
;
;Purpose:	Draws a single object mesh with clipping and sub-division
;
;Inputs:	a0 = vertex cache
;		a1 = mesh ptr
;		a2 = TEXTINFO structure ptr
;		a3 = OT ptr
;		s0 = primitive ptr
;		s1 = primitive limiter
;		fp = RGB mask ?
;		gp = primitive length
;		v0 = # triangles
;
;Outputs:	None
;
;Usage:		a0-a3/t0-t9/v0-v1
;
;----------------------------------------------------------------------------

DrawSubDivMesh:
	GPR.lh	t0,phd_left		; read current clip window
	GPR.lh	t1,phd_right
	GPR.lh	t2,phd_top
	GPR.lh	t3,phd_bottom
	sll	t0,16
	sll	t1,16
	sll	t2,16
	sll	t3,16
	mtc2	t0,CLIPL
	mtc2	t1,CLIPR
	mtc2	t2,CLIPT
	mtc2	t3,CLIPB

;--------------------------------------
; Draw Triangles
;--------------------------------------

	lui	gp,GT3_LEN<<8		; gp = primitive size
	beqz	v0,@quad		; EQ = no triangles
	addi	a1,4

; -------- packet loop

	lw	t0,0(a1)		; read 4 textures
@tploop	addi	a1,4
	ori	v1,zero,3		; v1 = inner-loop count

; -------- face loop

@tloop	lw	t1,0(a1)		; t1 = face
	slt	at,s0,s1		; enough primitives ?
	beqz	at,@tnext		; EQ = no, skip face
	subi	v0,1

; -------- fetch and clip vertices

	if	SUBDIV3D
	ctc2	t1,FACE
	endif

	srl	t8,t1,13		; calc vertex pointers
	andi	t8,$7f8
	add	t8,a0
	srl	t7,t1,5
	andi	t7,$7f8
	add	t7,a0
	sll	t6,t1,3
	andi	t6,$7f8
	add	t6,a0
	lw	s4,0(t6)		; load vertices into GTE
	lw	s5,0(t7)
	lw	s6,0(t8)
	mtc2	s4,C2_SXY0
	mtc2	s5,C2_SXY1
	mtc2	s6,C2_SXY2
	andi	t5,t0,$ff		; t5 = texture bits 0-7
	srl	t1,16
	NCLIP				; NormalClip (8)

	andi	t1,$ff00 		; t1 = texture bits 8-15
	or	t5,t1			; t5 = texture #
	jal	ClipXY
	move	s7,s6			; s7 = xy2
	bnez	at,@tnext		; NE = clipped
	srl	t0,8

	lwc2	C2_SZ1,4(t6)
	lwc2	C2_SZ2,4(t7)
	lwc2	C2_SZ3,4(t8)
	mfc2	at,C2_MAC0
	AVSZ3				; AverageZ3 (5)

	bltz	at,@tnext		; <0 = facing into screen
	lw	t6,4(t6)		; fetch vertex z & rgb components
	lw	t7,4(t7)
	lw	t8,4(t8)
	sll	t5,4

	mfc2	t1,C2_OTZ		; t1 = screen zpos
	add	t5,a2
	slt	at,t1,OTSIZE		; within OT ?
	beqz	at,@tnext		; EQ = outside OT
	slt	at,t1,NEARZ		; Too close ?
	bnez	at,@tnext
	sll	t1,2

; -------- initialise primitive

	lw	t4,tiU2(t5)		; uv2 & primitive ids
	jal	UnpackRGB		; unpack rgbs
	sll	at,t4,8

	cfc2	at,CLUTADDER
	lw	t2,tiU0(t5)		; uv0 & clut
	lw	t3,tiU1(t5)		; uv1 & tpage
;##	jal	InitGT3
	subu	t2,at

;##	ctc2	s0,PRIMPTR
	jal	SubDiv3
	add	t1,a3
	addi	s0,SIZEOF_GT3

;##	j	@tnext
;##	nop

; -------- AddPrim

;##	lw	t2,0(t1)
;##	sw	s0,0(t1)
;##	or	t2,gp
;##	sw	t2,0(s0)
;##	addi	s0,SIZEOF_GT3
@tnext:
	beqz	v0,@quad
	addi	a1,4
	bnez	v1,@tloop
	subi	v1,1
	j	@tploop
	lw	t0,0(a1)		; read 4 textures

;--------------------------------------
; Draw Quads
;--------------------------------------

@quad	cfc2	v0,POLYCOUNT		; restore # quads
	lui	gp,GT4_LEN<<8		; s3 = primitive length
	beqz	v0,@exit		; EQ = no quads

; -------- packet loop

	lw	t0,0(a1)		; read 2 textures
@qploop	addi	a1,4
	ori	v1,zero,1		; v1 = packet loop count

; -------- face loop

@qloop	lw	t1,0(a1)		; t1 = face
	slt	at,s0,s1		; enough primitives ?
	beqz	at,@qnext		; EQ = no, skip face
	subi	v0,1

; -------- fetch and clip vertices

	if	SUBDIV3D
	ctc2	t1,FACE
	endif

	srl	t9,t1,21		; calc vertex pointers
	andi	t9,$7f8
	srl	t8,t1,13
	andi	t8,$7f8
	add	t8,a0
	srl	t7,t1,5
	andi	t7,$7f8
	add	t7,a0
	sll	t6,t1,3
	andi	t6,$7f8
	add	t6,a0
	lw	s4,0(t6)		; load vertices into GTE
	lw	s5,0(t7)
	lw	s6,0(t8)
	mtc2	s4,C2_SXY0
	mtc2	s5,C2_SXY1
	mtc2	s6,C2_SXY2
	add	t9,a0
	andi	t5,t0,$ffff		; t5 = texture #
	NCLIP				; NormalClip (8)

	jal	ClipXY
	lw	s7,0(t9)		; s7 = xy3
	bnez	at,@qnext		; NE = clipped
	srl	t0,16

	lwc2	C2_SZ0,4(t6)
	lwc2	C2_SZ1,4(t7)
	lwc2	C2_SZ2,4(t8)
	lwc2	C2_SZ3,4(t9)
	mfc2	at,C2_MAC0
	AVSZ4 				; AverageZ4 (6)

	bltz	at,@qnext		; <0 = facing into screen
	lw	t6,4(t6)		; fetch vertex z & rgb components
	lw	t7,4(t7)
	lw	t8,4(t8)
	lw	t9,4(t9)
	sll	t5,4			; calc texture index

	mfc2	t1,C2_OTZ		; t9 = screen zpos
	add	t5,a2			; + PSXTEXTINFO org
	slt	at,t1,OTSIZE		; within OT ?
	beqz	at,@qnext		; EQ = outside OT
	slt	at,t1,NEARZ		; Too close ?
	bnez	at,@qnext
	sll	t1,2

; -------- initialise primitive

	srl	t2,t9,7			; unpack 4th rgb
	and	t2,fp
	srl	t3,t9,10
	andi	t3,$f800
	srl	t9,13
	andi	t9,$f8
	or	t9,t3
	or	t9,t2

	lw	t4,tiU2(t5)		; uv3 & primitive ids
	jal	UnpackRGB		; unpack rgbs
	move	at,t4

	cfc2	at,CLUTADDER
	lw	t2,tiU0(t5)		; uv0 & clut
	lw	t3,tiU1(t5)		; uv1 & tpage
	lw	t5,tiU3(t5)		; uv2
;##	jal	InitGT4
	subu	t2,at			; why does this crash ?

;##	ctc2	s0,PRIMPTR
	jal	SubDiv4
	add	t1,a3
	addi	s0,SIZEOF_GT4

;##	j	@qnext
;##	nop

; -------- AddPrim

;##	lw	t2,0(t1)
;##	sw	s0,0(t1)
;##	or	t2,gp
;##	sw	t2,0(s0)
;##	addi	s0,SIZEOF_GT4
@qnext:
	beqz	v0,@exit
	addi	a1,4
	bnez	v1,@qloop
	subi	v1,1
	j	@qploop
	lw	t0,0(a1)		; read 2 textures
@exit:
	cfc2	at,C2_BBK		; restore GTE settings
	ctc2	zero,C2_GFC
	ctc2	zero,C2_BFC
	ctc2	at,C2_RBK
	ctc2	at,C2_GBK
	j	DrawExit
	nop

;----------------------------------------------------------------------------
; Public Routines
;----------------------------------------------------------------------------

	XDEF	phd_PutPolygons
	XDEF	InitObjGTE
;	XDEF	DrawPickup

;----------------------------------------------------------------------------
;DrawObjectMesh
;
;Purpose:	Draws a single object mesh without subdivision
;
;Inputs:	a0 = mesh ptr
;		a1 = clip (<0 = clipped)
;
;Outputs:	None
;
;Usage:		a0-a3/t0-t9/v0-v1
;
;----------------------------------------------------------------------------

	XREF	Matrix

phd_PutPolygons:
	subi	sp,STACKFRAME
	sw	ra,regra(sp)
	sw	s0,regs0(sp)
	sw	s1,regs1(sp)
	sw	s2,regs2(sp)
	sw	s3,regs3(sp)
	sw	s4,regs4(sp)
	sw	s5,regs5(sp)
	sw	s6,regs6(sp)
	sw	s7,regs7(sp)
	sw	fp,regfp(sp)
	sw	gp,reggp(sp)

;--------------------------------------
; Initialise light matrix
;--------------------------------------

	cfc2	t0,C2_R11R12		; fetch current matrix
	cfc2	t1,C2_R13R21
	cfc2	t2,C2_R22R23
	cfc2	t3,C2_R31R32
	cfc2	t4,C2_R33

	lui	t5,$ffff		; transpose matrix
	and	t6,t0,t5		; t6 = m01
	and	t7,t2,t5		; t7 = m12
	and	t0,$ffff		; t0 = m00m10
	and	at,t1,t5
	or	t0,at
	and	t2,$ffff		; t2 = m11m21
	and	at,t3,t5
	or	t2,at
	and	t1,$ffff		; t1 = m02m12
	or	t1,t7
	and	t3,$ffff		; t3 = m20m01
	or	t3,t6

	ctc2	t0,C2_L11L12		; load transposed matrix
	ctc2	t3,C2_L13L21
	ctc2	t2,C2_L22L23
	ctc2	t1,C2_L31L32
	ctc2	t4,C2_L33

; -------- apply matrix to light vectors

	lui	t9,LightPos>>16
	ori	t9,LightPos&$ffff
	lw	t0,0(t9)
	lw	t1,4(t9)
	mtc2	t0,C2_VXY0
	mtc2	t1,C2_VZ0
	nop
	MVMVA	1,1,0,3,0		; [ll] * [v0]

	lw	t0,8(t9)
	srl	t1,16
	sll	at,t0,16
	or	t1,at
	srl	t0,16

	mtc2	t1,C2_VXY1
	mtc2	t0,C2_VZ1
	mfc2	t0,C2_IR1
	mfc2	t2,C2_IR2
	mfc2	t1,C2_IR3
	MVMVA	1,1,1,3,0		; [ll] * [v1]

	lwc2	C2_VXY2,12(t9)
	lwc2	C2_VZ2,16(t9)
	andi	t0,$ffff
	sll	t2,16
	or	t0,t2
	andi	t1,$ffff

	mfc2	t3,C2_IR1
	mfc2	t2,C2_IR2
	mfc2	t4,C2_IR3
	MVMVA	1,1,2,3,0		; [ll] * [v2]

	sll	t3,16
	or	t1,t3
	andi	t2,$ffff
	sll	t4,16
	or	t2,t4

	mfc2	t3,C2_IR1
	mfc2	t5,C2_IR2
	mfc2	t4,C2_IR3
	andi	t3,$ffff
	sll	t5,16
	or	t3,t5

	ctc2	t0,C2_L11L12		; load light matrix
	ctc2	t1,C2_L13L21
	ctc2	t2,C2_L22L23
	ctc2	t3,C2_L31L32
	ctc2	t4,C2_L33

;--------------------------------------
; Initialise constants
;--------------------------------------

	lw	v0,omVertices(a0)	; v0 = Flags, nVertices, FaceOffset
	addi	a0,omSIZEOF		; a0 = vertex ptr
	move	s5,a1			; s5 = clip ?
	andi	s6,v0,$0100		; s6 = subdiv ?
	srl	a1,v0,16		; a1 = face offset
	andi	v1,v0,$8000		; v1 = light-source flag
	andi	v0,$ff			; v0 = # vertices

; -------- determine vertex buffer

	slt	at,v0,DCACHE_SNVERTS
	bnez	at,@fast
	add	a1,a0			; a1 = face data ptr
	lui	a2,tsv_buffer>>16
	j	@ok
	ori	a2,tsv_buffer&$ffff
@fast:
	lui	a2,DCACHE>>16
	ori	a2,dcVertices
@ok:	move	s7,a2			; s7 = saved vertex buffer ptr

;--------------------------------------
; Light vertices
;--------------------------------------

	cfc2	t0,C2_TRZ		; determine depth cue value
	move	t1,zero
	move	s4,t0			; temp = mesh z
	subi	t0,DPQ_START
	blez	t0,@nodpq
	sll	at,v0,3			; at = # vertices * SIZEOF_VERTEX
	srl	t1,t0,1
@nodpq	mtc2	t1,C2_IR0		; initialise depth cue
	beqz	v1,@anim		; EQ = animating mesh
	move	v1,v0			; v1 = # vertices

; -------- light a static mesh

	move	a3,a0			; a3 = vertex ptr
@sloop:
	lh	t0,6(a3)		; t0 = vertex intensity
	addi	a3,8
	mtc2	t0,C2_IRGB		; unpack RGB into GTE
	subi	v1,1
	addi	a2,8
	nop
	DCPL				; (1-dp)[rgb*sv] + dp[fc] (8)
	mfc2	t0,C2_ORGB
	bnez	v1,@sloop
	sh	t0,6-8(a2)
	j	@trans
	move	a2,s7			; a2 = vertex buffer

; -------- light an animating mesh

@anim	add	a3,a0,at		; a3 = normal ptr
	lui	t0,$80			; set initial vertex colour
	ori	t0,$8080
	mtc2	t0,C2_RGB
@aloop:
	lwc2	C2_VXY0,0(a3)		; load vertex normal into GTE
	lwc2	C2_VZ0,4(a3)
	addi	a3,8
	NCDS				; NormalColorDPQ (19)
	subi	v1,1
	addi	a2,8
	mfc2	t0,C2_ORGB
	bnez	v1,@aloop
	sh	t0,6-8(a2)
	move	a2,s7			; a2 = vertex buffer

;--------------------------------------
; Transform vertices
;--------------------------------------

@trans	lw	t0, 0(a0)		; fetch initial 3 vertices
	lw	t1, 4(a0)
	lw	t2, 8(a0)
	lw	t3,12(a0)
	lw	t4,16(a0)
	lw	t5,20(a0)
	if	SUBDIV3D
	ctc2	a0,VERTS		; save vertex ptr for sub-division
	endif
@vloop:
	mtc2	t0,C2_VXY0
	mtc2	t1,C2_VZ0
	mtc2	t2,C2_VXY1
	mtc2	t3,C2_VZ1
	mtc2	t4,C2_VXY2
	mtc2	t5,C2_VZ2
	addi	a0,24
	RTPT				; RotTransPers3 (22)

	lw	t0, 0(a0)		; fetch next 3 vertices
	lw	t1, 4(a0)
	lw	t2, 8(a0)
	lw	t3,12(a0)
	lw	t4,16(a0)
	lw	t5,20(a0)

	mfc2	t6,C2_SZ1		; store transformed vertices
	mfc2	t7,C2_SZ2
	mfc2	t8,C2_SZ3
	swc2	C2_SXY0,0(a2)
	sh	t6,4(a2)
	swc2	C2_SXY1,8(a2)
	sh	t7,12(a2)
	swc2	C2_SXY2,16(a2)
	sh	t8,20(a2)

	subi	v0,3
	bgtz	v0,@vloop
	addi	a2,24

;--------------------------------------
; Draw Triangles
;--------------------------------------

	move	a0,s7			; a0 = vertex cache
	GPR.lw	a2,psxtextinfo		; a2 = texture info ptr
	GPla	t0,db
	lw	a3,dbOT(t0)		; a3 = OT
	lw	s0,dbPrimPtr(t0)	; s0 = POLY_GT4 ptr
	lw	s1,dbPrimEnd(t0)	; s1 = POLY_GT4 max
	lw	v0,0(a1)		; v0 = # polys
	lui	fp,$00f8		; fp = RGB mask
	srl	at,v0,16		; save # quads
	ctc2	at,POLYCOUNT

; -------- determine whether clipping or subdivision is required

	beqz	s6,@nosd		; EQ = no mesh subdivision
	subi	s4,SUBDIV_Z
	bltz	s4,DrawSubDivMesh	; <0 = subdivision required
	andi	v0,$ffff		; v0 = # triangles
@nosd	bltz	s5,DrawClippedMesh	; <0 = clipping required
	andi	v0,$ffff		; v0 = # triangles

	lui	gp,GT3_LEN<<8		; gp = primitive size
	beqz	v0,@quad		; EQ = no triangles
	addi	a1,4

; -------- packet loop

	lw	t0,0(a1)		; read 4 textures
@tploop	addi	a1,4
	ori	v1,zero,3		; v1 = inner-loop count

; -------- face loop

@tloop	lw	t1,0(a1)		; t1 = face
	slt	at,s0,s1		; enough primitives ?
	beqz	at,@tnext		; EQ = no, skip face
	subi	v0,1

; -------- fetch and clip vertices

	srl	t8,t1,13		; calc vertex pointers
	andi	t8,$7f8
	add	t8,a0
	srl	t7,t1,5
	andi	t7,$7f8
	add	t7,a0
	sll	t6,t1,3
	andi	t6,$7f8
	add	t6,a0
	lw	s4,0(t6)		; load vertices into GTE
	lw	s5,0(t7)
	lw	s6,0(t8)
	mtc2	s4,C2_SXY0
	mtc2	s5,C2_SXY1
	mtc2	s6,C2_SXY2
	andi	t5,t0,$ff		; t5 = texture bits 0-7
	srl	t0,8
	NCLIP				; NormalClip (8)

	lw	t6,4(t6)		; fetch vertex z & rgb components
	lw	t7,4(t7)
	lw	t8,4(t8)
	mtc2	t6,C2_SZ1
	mtc2	t7,C2_SZ2
	mtc2	t8,C2_SZ3
	srl	t1,16
	andi	t1,$ff00 		; t1 = texture bits 8-15

	mfc2	at,C2_MAC0
	AVSZ3				; AverageZ3 (5)
	bltz	at,@tnext		; <0 = facing into screen
	or	t5,t1			; t5 = texture #
	sll	t5,4
	add	t5,a2
; 1 cycle here

	mfc2	t1,C2_OTZ		; t1 = screen zpos
	nop
	slt	at,t1,OTSIZE		; within OT ?
	beqz	at,@tnext		; EQ = outside OT
	slt	at,t1,NEARZ		; Too close ?
	bnez	at,@tnext
	sll	t1,2

; -------- initialise primitive

	lw	t4,tiU2(t5)		; uv2 & primitive ids
	jal	UnpackRGB		; unpack rgbs
	sll	at,t4,8

	cfc2	at,CLUTADDER
	lw	t2,tiU0(t5)		; uv0 & clut
	lw	t3,tiU1(t5)		; uv1 & tpage
	jal	InitGT3
	subu	t2,at

; -------- AddPrim

	add	t1,a3			; t1 = ot ptr
	lw	t2,0(t1)
	sw	s0,0(t1)
	or	t2,gp
	sw	t2,0(s0)
	addi	s0,SIZEOF_GT3
@tnext:
	beqz	v0,@quad
	addi	a1,4
	bnez	v1,@tloop
	subi	v1,1
	j	@tploop
	lw	t0,0(a1)		; read 4 textures

;--------------------------------------
; Draw Quads
;--------------------------------------

@quad	cfc2	v0,POLYCOUNT		; restore # quads
	lui	gp,GT4_LEN<<8		; gp = primitive length
	beqz	v0,DrawExit		; EQ = no quads

; -------- packet loop

	lw	t0,0(a1)		; read 2 textures
@qploop	addi	a1,4
	ori	v1,zero,1		; v1 = packet loop count

; -------- face loop

@qloop	lw	t1,0(a1)		; t1 = face
	slt	at,s0,s1		; enough primitives ?
	beqz	at,@qnext		; EQ = no, skip face
	subi	v0,1

; -------- fetch and clip vertices

	srl	t9,t1,21		; calc vertex pointers
	srl	t8,t1,13
	andi	t8,$7f8
	add	t8,a0
	srl	t7,t1,5
	andi	t7,$7f8
	add	t7,a0
	sll	t6,t1,3
	andi	t6,$7f8
	add	t6,a0
	lw	s4,0(t6)		; load vertices into GTE
	lw	s5,0(t7)
	lw	s6,0(t8)
	mtc2	s4,C2_SXY0
	mtc2	s5,C2_SXY1
	mtc2	s6,C2_SXY2
	andi	t9,$7f8
	add	t9,a0
	NCLIP				; NormalClip (8)

	lw	t6,4(t6)		; fetch vertex z & rgb components
	lw	t7,4(t7)
	lw	t8,4(t8)
	lw	s7,0(t9)		; s7 = xy3
	lw	t9,4(t9)
	mtc2	t6,C2_SZ0
	mtc2	t7,C2_SZ1
	mtc2	t8,C2_SZ2
	mtc2	t9,C2_SZ3
	mfc2	at,C2_MAC0
	AVSZ4 				; AverageZ4 (6)

	andi	t5,t0,$ffff		; t5 = texture #
	srl	t0,16			; t0 = next texture #
	bltz	at,@qnext		; <0 = facing into screen
	sll	t5,4			; calc texture index
	add	t5,a2			; + PSXTEXTINFO org
	srl	t2,t9,7			; unpack 4th rgb

	mfc2	t1,C2_OTZ		; t9 = screen zpos
	and	t2,fp
	slt	at,t1,OTSIZE		; within OT ?
	beqz	at,@qnext		; EQ = outside OT
	slt	at,t1,NEARZ		; Too close ?
	bnez	at,@qnext
	sll	t1,2

; -------- initialise primitive

	srl	t3,t9,10
	andi	t3,$f800
	srl	t9,13
	andi	t9,$f8
	or	t9,t3
	or	t9,t2

	lw	t4,tiU2(t5)		; uv3 & primitive ids
	jal	UnpackRGB		; unpack rgbs
	move	at,t4

	cfc2	at,CLUTADDER
	lw	t2,tiU0(t5)		; uv0 & clut
	lw	t3,tiU1(t5)		; uv1 & tpage
	lw	t5,tiU3(t5)		; uv2
	jal	InitGT4
	subu	t2,at			; why does this crash ?

; -------- AddPrim

	add	t1,a3
	lw	t2,0(t1)
	sw	s0,0(t1)
	or	t2,gp
	sw	t2,0(s0)
	addi	s0,SIZEOF_GT4
@qnext:
	beqz	v0,DrawExit
	addi	a1,4
	bnez	v1,@qloop
	subi	v1,1
	j	@qploop
	lw	t0,0(a1)		; read 2 textures
DrawExit:
	ctc2	zero,C2_RFC		; load depth cue target
	lw	gp,reggp(sp)
	lw	ra,regra(sp)
	GPla	a1,db
	sw	s0,dbPrimPtr(a1)

	lw	s0,regs0(sp)
	lw	s1,regs1(sp)
	lw	s2,regs2(sp)
	lw	s3,regs3(sp)
	lw	s4,regs4(sp)
	lw	s5,regs5(sp)
	lw	s6,regs6(sp)
	lw	s7,regs7(sp)
	lw	fp,regfp(sp)
	jr	ra
	addi	sp,STACKFRAME

;----------------------------------------------------------------------------
;InitObjGTE
;
;Purpose:	Initialises the GTE for object drawing
;
;Inputs:	None
;
;Outputs:	None
;
;Usage:		v0
;
;----------------------------------------------------------------------------

InitObjGTE:
	ori	v0,zero,$aa		; initialise z dividers
	ctc2	v0,C2_ZSF3
	ori	v0,zero,$80
	ctc2	v0,C2_ZSF4
	ctc2	zero,C2_RFC		; load depth cue target
	ctc2	zero,C2_GFC
	ctc2	zero,C2_BFC
	jr	ra
	nop

	XDEF	LightFish

LightFish:
	mtc2	a2,C2_IRGB		; unpack RGB into GTE
	move	t0,zero			; determine depth cue value
	subi	a1,DPQ_START
	blez	a1,@nodpq
	nop
	srl	t0,a1,1
@nodpq	mtc2	t0,C2_IR0		; initialise depth cue
	nop
	DCPL				; (1-dp)[rgb*sv] + dp[fc] (8)
	swc2	C2_RGB2,ftRGB0(a0)
	jr	ra
	nop

;----------------------------------------------------------------------------

	XDEF	MakeMono

MakeMono:
	ori	at,zero,$2ab		; initialise z divider
	ctc2	at,C2_ZSF3
	lw	t0,(a0)
	ori	v0,zero,((256*128)/2)-1
@loop:
	srl	t3,t0,26
	srl	t2,t0,21
	srl	t1,t0,16
	andi	t3,31
	andi	t2,31
	andi	t1,31
	mtc2	t3,C2_SZ1
	mtc2	t2,C2_SZ2
	mtc2	t1,C2_SZ3
	addi	a0,4
	AVSZ3

	srl	t2,t0,10
	srl	t1,t0,5
	andi	t2,31
	andi	t1,31
	andi	t0,31
	mtc2	t2,C2_SZ1
	mtc2	t1,C2_SZ2
	mtc2	t0,C2_SZ3
	mfc2	t1,C2_OTZ
	AVSZ3

	lw	t0,(a0)
	mfc2	at,C2_OTZ
	sll	t1,4
	or	t1,at
	sb	t1,0(a1)
	addi	a1,1

	bnez	v0,@loop
	subi	v0,1
	ori	v0,zero,$aa		; restore z divider
	ctc2	v0,C2_ZSF3
	jr	ra
	nop

	if	0
;----------------------------------------------------------------------------
;DrawPickup
;
;Purpose:	Draws a pickup mesh
;
;Inputs:	a0 = mesh ptr
;
;Outputs:	None
;
;Usage:		a0-a3/t0-t9/v0-v1
;
;----------------------------------------------------------------------------

DrawPickup:
	subi	sp,STACKFRAME
	sw	ra,regra(sp)
	sw	s0,regs0(sp)
	sw	s1,regs1(sp)
	sw	s2,regs2(sp)
	sw	s3,regs3(sp)
	sw	s4,regs4(sp)
	sw	s5,regs5(sp)
	sw	s6,regs6(sp)
	sw	s7,regs7(sp)
	sw	fp,regfp(sp)
	sw	gp,reggp(sp)

;--------------------------------------
; Initialise constants
;--------------------------------------

	lw	v0,omVertices(a0)	; v0 = Flags, nVertices, FaceOffset
	addi	a0,omSIZEOF		; a0 = vertex ptr
	srl	a1,v0,16		; a1 = face offset
	andi	v0,$ff			; v0 = # vertices

	add	a1,a0			; a1 = face data ptr
	lui	a2,DCACHE>>16

;--------------------------------------
; Transform vertices
;--------------------------------------

	ori	t0,zero,440	;448
	lui	t1,200		;216
;	ori	t0,zero,256	;448
;	lui	t1,120		;216
	lui	t2,$ffff
@vloop:
	lw	t3,0(a0)
	addi	a0,8

	sll	t4,t3,16
	sra	t4,16
	sra	at,t4,1
	add	t4,at

	sub	t4,zero,t4
	add	t4,t0
	and	t4,$ffff
	add	t3,t1
	and	t3,t2
	or	t3,t4

	sw	t3,0(a2)
	subi	v0,1
	bgtz	v0,@vloop
	addi	a2,4

;--------------------------------------
; Draw Triangles
;--------------------------------------

	lw	v0,0(a1)		; v0 = # polys
	lui	a0,DCACHE>>16		; a0 = vertex cache
	GPR.lw	a2,psxtextinfo		; a2 = texture info ptr
	GPla	t0,db
	lw	a3,dbOT(t0)		; a3 = OT
	lw	s0,dbPrimPtr(t0)	; s0 = POLY_GT4 ptr
	lw	s1,dbPrimEnd(t0)	; s1 = POLY_GT4 max
	srl	s4,v0,16		; s3 = # quads

	andi	v0,$ffff		; v0 = # triangles
	beqz	v0,@quad		; EQ = no triangles
	addi	a1,4

	lui	s2,FT3_LEN<<8		; s2 = primitive length
	lui	s3,$2460		; s3 = primitive ID + RGB
	ori	s3,$6060

; -------- packet loop

	lw	t0,0(a1)		; read 4 textures
@tploop	addi	a1,4
	ori	v1,zero,3		; v1 = inner-loop count

; -------- face loop

@tloop	lw	t1,0(a1)		; t1 = face
	slt	at,s0,s1		; enough primitives ?
	beqz	at,@exit		; EQ = no, exit
	subi	v0,1

	srl	t8,t1,14		; calc vertex pointers
	andi	t8,$3fc
	add	t8,a0
	srl	t7,t1,6
	andi	t7,$3fc
	add	t7,a0
	sll	t6,t1,2
	andi	t6,$3fc
	add	t6,a0
	lw	t6,0(t6)		; fetch vertices
	lw	t7,0(t7)
	lw	t8,0(t8)

	if	0
	mtc2	t6,C2_SXY0
	mtc2	t7,C2_SXY1
	mtc2	t8,C2_SXY2
	nop
	nop
	NCLIP				; NormalClip (8)
	mfc2	at,C2_MAC0
	nop
	bltz	at,@tnext		; <0 = facing into screen
	endif

	andi	t5,t0,$ff		; t5 = texture bits 0-7
	srl	t0,8
	srl	t1,16
	andi	t1,$ff00 		; t1 = texture bits 8-15
	or	t5,t1			; t5 = texture #

; -------- initialise primitive

	sll	t5,4
	add	t5,a2
	lw	t2,tiU0(t5)
	lw	t3,tiU1(t5)
	lw	t4,tiU2(t5)

	sw	s3,ftRGB0(s0)
	sw	t6,ftX0(s0)
	sw	t2,ftU0(s0)
	sw	t7,ftX1(s0)
	sw	t3,ftU1(s0)
	sw	t8,ftX2(s0)
	sw	t4,ftU2(s0)

	lw	t2,0(a3)
	sw	s0,0(a3)
	or	t2,s2
	sw	t2,0(s0)
	addi	s0,SIZEOF_FT3
@tnext:
	beqz	v0,@quad
	addi	a1,4
	bnez	v1,@tloop
	subi	v1,1
	j	@tploop
	lw	t0,0(a1)		; read 4 textures

;--------------------------------------
; Draw Quads
;--------------------------------------

@quad	move	v0,s4			; vo = # quads
	beqz	v0,@exit		; EQ = no quads
	lui	s2,FT4_LEN<<8		; s2 = primitive length
	lui	s3,$2c80		; s3 = primitive ID + RGB
	ori	s3,$8080

; -------- packet loop

	lw	t0,0(a1)		; read 2 textures
@qploop	addi	a1,4
	ori	v1,zero,1		; v1 = packet loop count

; -------- face loop

@qloop	lw	t1,0(a1)		; t1 = face
	slt	at,s0,s1		; enough primitives ?
	beqz	at,@exit		; EQ = no, exit
	subi	v0,1

	srl	t9,t1,22		; calc vertex pointers
	andi	t9,$3fc
	add	t9,a0
	srl	t8,t1,14
	andi	t8,$3fc
	add	t8,a0
	srl	t7,t1,6
	andi	t7,$3fc
	add	t7,a0
	sll	t6,t1,2
	andi	t6,$3fc
	add	t6,a0
	lw	t6,0(t6)		; fetch vertices
	lw	t7,0(t7)
	lw	t8,0(t8)
	lw	t9,0(t9)

	andi	t5,t0,$ffff		; t5 = texture #
	srl	t0,16			; t0 = next texture #

; -------- initialise primitive

	sll	t5,4
	add	t5,a2

	lw	t2,tiU0(t5)
	lw	t3,tiU1(t5)
	lw	t4,tiU2(t5)
	lw	t5,tiU3(t5)

	sw	s3,ftRGB0(s0)
	sw	t6,ftX0(s0)
	sw	t2,ftU0(s0)
	sw	t7,ftX1(s0)
	sw	t3,ftU1(s0)
	sw	t8,ftX2(s0)
	sw	t4,ftU2(s0)
	sw	t9,ftX3(s0)
	sw	t5,ftU3(s0)

	lw	t2,0(a3)
	sw	s0,0(a3)
	or	t2,s2
	sw	t2,0(s0)
	addi	s0,SIZEOF_FT4
@qnext:
	beqz	v0,@exit
	addi	a1,4
	bnez	v1,@qloop
	subi	v1,1
	j	@qploop
	lw	t0,0(a1)		; read 2 textures
@exit:
	lw	gp,reggp(sp)
	lw	ra,regra(sp)
	GPla	a1,db
	sw	s0,dbPrimPtr(a1)
	lw	s0,regs0(sp)
	lw	s1,regs1(sp)
	lw	s2,regs2(sp)
	lw	s3,regs3(sp)
	lw	s4,regs4(sp)
	lw	s5,regs5(sp)
	lw	s6,regs6(sp)
	lw	s7,regs7(sp)
	lw	fp,regfp(sp)
	jr	ra
	addi	sp,STACKFRAME


	endif


