
;Dude's object insert stuff for Tomb Raider
;Second version
;Transform all vertices once into scratchpad (if possible)
;Then generate polys using nclip only
;Started 15th Sept 96
;Finished 17th Sept 96
;
; updated to work with new asmpsx 25/02/97 by del

JAP		equ		0

		include	..\spec_psx\tomb.inc

mvmva	MACRO	sf,mx,v,cv,lm
	dw	$4a400012|((sf&3)<<19)|((mx&3)<<17)|((v&3)<<15)|((cv&3)<<13)|((lm&3)<<11)
	ENDM

		global	DownLoadMatrix
;		global	phd_PutPolygons
		global	dude_insert_mesh

		xref	tsv_buffer
		xref	phd_mxptr
		xref	db
		xref	shade_effect
		xref	water_effect
		xref	psxtextinfo
		xref	emap_flag
		xref	dude_envmap_tpage
		xref	GdwUWClutSub

		xref	psx_calc_vertice_light_asm
		xref	dude_phd_PutPoly_envmap
		xref	phd_PutPoly_subdivide
		xref	phd_PutPoly_clip
		xref	dude_insert_mesh_clipped

tsvbase equr	v0
num 	equr	v1

objptr	equr	a0
txtbase equr	a1
otbase	equr	a2
polyptr equr	a3

vxy0	equr	t0
vxy1	equr	t1
vxy2	equr	t2
vptr	equr	t3

vz0 	equr	t4
vz1 	equr	t5
vz2 	equr	t6
tsvptr	equr	t7

v0ptr	equr	t0
v1ptr	equr	t1
v2ptr	equr	t2
v3ptr	equr	t3
gt3mask equr	t3

v3tsv	equr	t4
onediv6 equr	t4
txtptr	equr	t5

temp	equr	t8
temp2	equr	t9

n0ptr	equr	t4
n1ptr	equr	t5
n2ptr	equr	t6
n3ptr	equr	t7

em3tp	equr	t3
em31d6	equr	t7

normbase equr	s0
clutsub	equr	s1
envtpage equr	a1
pblimit	equr	s4

ASPECT_512		equ	0

DownLoadMatrix
		if	1
		gpr.lw	t1,phd_mxptr
		li	t0,$ffff0000
		lw	at,M_00(t1)
		lw	v0,M_01(t1)
;		srl	at,2
		lw	v1,M_02(t1)
		andi	at,$ffff
		sll    	v0,16
		and    	v0,t0
		or     	at,v0
		ctc2	at,C2_R11R12
		lw	at,M_10(t1)
;		srl		v1,2
		lw	v0,M_11(t1)
		andi	v1,$ffff
		lw	t2,M_12(t1)
		sll	at,16
		and	at,t0
		or	at,v1
		ctc2	at,C2_R13R21
;		srl	v0,2
		andi	v0,$ffff
		sll	t2,16
		and	t2,t0
		or	v0,t2
		lw	at,M_20(t1)
		ctc2	v0,C2_R22R23
		lw	v0,M_21(t1)
;		srl	at,2
		lw	v1,M_22(t1)
		andi	at,$ffff
		sll	v0,16
		and	v0,t0
		or	at,v0
		ctc2	at,C2_R31R32
		lw	at,M_03(t1)
;		srl	v1,2
		lw	v0,M_13(t1)
		andi	v1,$ffff
		lw	t2,M_23(t1)
		ctc2	v1,C2_R33
		sra	at,W2V_SHIFT
		ctc2	at,C2_TRX
		sra	v0,W2V_SHIFT
		ctc2	v0,C2_TRY
		sra	t2,W2V_SHIFT
		ctc2	t2,C2_TRZ
		ret
		nop

		else
		gpr.lw	t1,phd_mxptr
		li		t0,$ffff0000
		lw		at,M_00(t1)
		lw		v0,M_01(t1)
		srl		at,2
		lw		v1,M_02(t1)
		andi	at,$ffff
		sll		v0,14
		and		v0,t0
		or		at,v0
		ctc2	at,C2_R11R12
		lw		at,M_10(t1)
		srl		v1,2
		if		ASPECT_512
		srl		t7,at,2
		subu	at,t7
		endif
		lw		v0,M_11(t1)
		andi	v1,$ffff
		if		ASPECT_512
		srl		t7,v0,2
		subu	v0,t7
		endif
		lw		t2,M_12(t1)
		sll		at,14
		if		ASPECT_512
		srl		t7,t2,2
		subu	t2,t7
		endif
		and		at,t0
		or		at,v1
		ctc2	at,C2_R13R21
		srl		v0,2
		andi	v0,$ffff
		sll		t2,14
		and		t2,t0
		or		v0,t2
		lw		at,M_20(t1)
		ctc2	v0,C2_R22R23
		lw		v0,M_21(t1)
		srl		at,2
		lw		v1,M_22(t1)
		andi	at,$ffff
		sll		v0,14
		and		v0,t0
		or		at,v0
		ctc2	at,C2_R31R32
		lw		at,M_03(t1)
		srl		v1,2
		lw		v0,M_13(t1)
		andi	v1,$ffff
		if		ASPECT_512
		srl		t7,v0,2
		subu	v0,t7
		endif
		lw		t2,M_23(t1)
		ctc2	v1,C2_R33
		sra		at,W2V_SHIFT
		ctc2	at,C2_TRX
		sra		v0,W2V_SHIFT
		ctc2	v0,C2_TRY
		sra		t2,W2V_SHIFT
		ctc2	t2,C2_TRZ
		ret
		nop
		endif

	if	0	;##

phd_PutPolygons
		addiu	sp,-12
.ok		sw		ra,8(sp)
		jal		DownLoadMatrix
		sw		a0,(sp)
		jal		psx_calc_vertice_light_asm
		sw		a1,4(sp)
		gpr.lw	v0,shade_effect
		gpr.lw	v1,water_effect
		gpr.lw	a1,psxtextinfo
		or		v0,v1
		lw		a0,(sp)
		bz		v0,.notblu
		clr		t0
		gpr.lw	t0,GdwUWClutSub
.notblu:
		gpr.lw	at,emap_flag
		lw		a3,4(sp)
		lw		ra,8(sp)
		bnz		at,dude_phd_PutPoly_envmap
		addiu	sp,12
		lhu		v0,4*2(a0)
		gpr.lw	v1,phd_mxptr
		bz		v0,.notsd
		nop
		lw		v0,M_23(v1)
		nop
		srl		v0,W2V_SHIFT
		cmpi	v0,SUBDIVIDE_Z
		blo		dude_insert_mesh_clipped
		li		v1,1
.notsd	bltz	a3,dude_insert_mesh_clipped
		li		v1,-1
;		li		v1,0

dude_insert_mesh
		lh		num,10(objptr)
		gpr.lw	otbase,(db+db_ot)
		addiu	vptr,objptr,12
		gpr.lw	polyptr,db+db_polyptr
		addiu	sp,-12
		sw		normbase,(sp)
		sw		clutsub,4(sp)
		sw		pblimit,8(sp)
		clr		normbase
		gpr.lw	pblimit,(db+db_polybuf_limit)
		bgez	num,.ispos
		move	clutsub,t0
		negate	num
		sll 	at,num,2
		addu	at,num
		b		.mk_op
		sll 	at,1

.ispos	sll 	at,num,3
		addu	normbase,vptr,at
		sll		at,1

.mk_op	addu	objptr,vptr,at
		cmpi	num,128+1
		blo 	.use_sc
		lui 	tsvbase,$1f80
		mac.la	tsvbase,tsv_buffer

.use_sc lw		vxy0,(vptr)
		lw		vxy1,8(vptr)			;load 3 vertex XYs
		lw		vxy2,16(vptr)
		move	tsvptr,tsvbase

.tsv_lp lw		vz0,4(vptr)
		lw		vz1,12(vptr)			;get 3 Zs
		lw		vz2,20(vptr)
		mtc2	vxy0,C2_VXY0
		mtc2	vxy1,C2_VXY1			;stick XYs into GTE
		mtc2	vxy2,C2_VXY2
		mtc2	vz0,C2_VZ0
		mtc2	vz1,C2_VZ1				;stick Zs into GTE
		mtc2	vz2,C2_VZ2
		addiu	vptr,24 				;move to next set of 3 vertices
		subiu	num,3					;done 3 more vertices
		gte_rtpt						;transform 3 vertices (22 cycles)
		lw		vxy0,(vptr)
		lw		vxy1,8(vptr)			;load next 3 XYs
		lw		vxy2,16(vptr)			;should be okay because poly data follows vertices
		srl 	vz0,8
		andi	vz0,$ff00
		srl 	at,vz0,8
		or		vz0,at
		srl 	vz1,8
		andi	vz1,$ff00				;calculate 3 RGs
		srl 	at,vz1,8
		or		vz1,at
		srl 	vz2,8
		andi	vz2,$ff00
		srl 	at,vz2,8
		or		vz2,at
		bltz	num,.lt3				;if less than 3 vertices then handle differently
		addiu	tsvptr,24				;move to next tsv
		swc2	C2_SXY0,-24(tsvptr)
		swc2	C2_SXY1,8-24(tsvptr)	;store transformed XYs
		swc2	C2_SXY2,16-24(tsvptr)
		mfc2	temp,C2_SZ1
		mfc2	temp2,C2_SZ2
		sll 	temp,16
		or		vz0,temp
		sw		vz0,4-24(tsvptr)
		mfc2	temp,C2_SZ3
		sll 	temp2,16				;store Zs and RGs
		sll 	temp,16
		or		vz1,temp2
		sw		vz1,12-24(tsvptr)
		or		vz2,temp
		bnz 	num,.tsv_lp 			;if >0 left then loop
		sw		vz2,20-24(tsvptr)
		b		.phase2 				;else start phase 2...
.lt3	inc 	num 					;if only one poly to do then num<0
		mfc2	temp,C2_SZ1
		swc2	C2_SXY0,-24(tsvptr) 	;store first tsv
		sll 	temp,16
		or		vz0,temp
		sw		vz0,4-24(tsvptr)
		mfc2	temp,C2_SZ2
		bltz	num,.phase2
		sll 	temp,16
		or		vz1,temp
		sw		vz1,12-24(tsvptr)		;store second tsv if necessary
		swc2	C2_SXY1,8-24(tsvptr)

.phase2	bz		normbase,.doGT4b		;if no normals, no envmaps, no em4/em3 counts.
		lhu		num,(objptr)			;get #em4 or #gt4
		inc.h	objptr
		bnz		num,.doEM4s				;do em4s if necessary
		dec		num
		lhu		num,(objptr)			;get #em3
		inc.h	objptr
		bnz		num,.doEM3s				;do em3s if necessary
		dec		num
.doGT4s	lhu		num,(objptr)			;get #gt4
.doGT4b	inc.h	objptr
		bz		num,.doGT3s
		dec		num

.GT4lp	lhu 	v0ptr,(objptr)
	cmpu	polyptr,pblimit
	bhs	.exit
	lhu 	v1ptr,2(objptr)
	addu	v0ptr,tsvbase

	lhu 	v2ptr,6(objptr) 	;get vertex numbers
	addu	v1ptr,tsvbase		;make vertex pointers

	lhu 	v3ptr,4(objptr)
	addu	v2ptr,tsvbase

	lwc2	C2_SXY0,(v0ptr)
	lwc2	C2_SXY1,(v1ptr) 	;load transformed XY for nclip
	lwc2	C2_SXY2,(v2ptr)
	lw	v1ptr,4(v1ptr)		;get RG/Z1
	addiu	objptr,10
	gte_nclip			;do nclip (8 cycles)

	lw	v2ptr,4(v2ptr)		;get RG/Z2
	addu	v3ptr,tsvbase

	lw	v3tsv,(v3ptr)		;get transformed XY 3
	andi	temp,v1ptr,$ffff

	lw	v3ptr,4(v3ptr)		;get RG/Z3
	sll 	at,temp,8
	or	temp,at
	mfc2	at,C2_MAC0		;read the nclip
	srl 	v1ptr,16		;get z1
	bmi 	.next4			;skip poly if it's back facing

	andi	at,v2ptr,$ffff
	sw	temp,rgb1(polyptr)	;make and store rgb1
	sll 	temp,at,8
	or	at,temp
	sw	at,rgb2(polyptr)	;make and store rgb2
	lhu 	txtptr,8-10(objptr) 	;get texture number
	lw	v0ptr,4(v0ptr)		;get RG/Z0
	srl 	v2ptr,16
	addu	v1ptr,v2ptr 		;z1+z2
	andi	at,v3ptr,$ffff
	sll 	temp,at,8
	or	at,temp
	sw	at,rgb3(polyptr)	;make and store rgb3
	srl 	v3ptr,16
	addu	v1ptr,v3ptr 		;z1+z2+z3
	andi	at,v0ptr,$ffff
	srl 	v0ptr,16
	addu	v0ptr,v1ptr 		;z0+z1+z2+z3
	sll 	txtptr,4
	addu	txtptr,txtbase		;make texture pointer
	lw	temp,8(txtptr)		;get uv2 and poly codes
	lw	v1ptr,0(txtptr) 	;get uv0 & clut
	lw	v2ptr,4(txtptr) 	;get uv1 & tpage
	lw	v3ptr,12(txtptr)	;get uv3
	swc2	C2_SXY0,xy0(polyptr)
	swc2	C2_SXY1,xy1(polyptr)	;store xy0..2 from gte
	swc2	C2_SXY2,xy2(polyptr)
	sw	v3tsv,xy3(polyptr)	;store xy3 from reg
	sll 	v3tsv,at,8
	or	at,v3tsv		;make rgb0
	srl 	temp2,temp,16
	sll 	temp2,24 		;make poly code
	or	at,temp2
	subu	v1ptr,clutsub		;modify clut if underwater
	sw	at,rgb0c(polyptr)	;make and store rgb0
	sw	temp,uv2(polyptr)	;store uv2
	sw	v1ptr,uv0clut(polyptr)	;store uv0 & clut
	srl 	v0ptr,OTRIGHT+2 	;get it in Paul's range <<2
	cmpiu	v0ptr,DPQ_END>>1	;make sure otz is in range
	bhs	.next4
	andi	v0ptr,$3ffc 		;dword align it
	addu	v0ptr,otbase		;make ot ptr
	lw	temp,(v0ptr)		;get previous ot prim ptr
	lui 	at,$0c00		;make len
	or	temp,at
	sw	temp,(polyptr)		;store tag & len
	sw	v2ptr,uv1tpg(polyptr)	;store uv1 & tpage
	sw	v3ptr,uv3(polyptr)	;store uv3
	sw	polyptr,(v0ptr)
	addiu	polyptr,gt4_sz		;move to next poly

.next4	bnz 	num,.GT4lp
	dec 	num

.doGT3s lhu 	num,(objptr)
		inc.h	objptr
		bz		num,.exit
		dec 	num
		lui 	gt3mask,$ff00
		mac.li	onediv6,$2aaaaaaa

.GT3lp	lhu 	v0ptr,(objptr)
		cmpu	polyptr,pblimit
		bhs		.exit
		lhu 	v1ptr,2(objptr)
		addu	v0ptr,tsvbase
		lhu 	v2ptr,4(objptr) 		;get vertex numbers
		addu	v1ptr,tsvbase			;make vertex pointers
		lwc2	C2_SXY0,(v0ptr)
		addu	v2ptr,tsvbase
		lwc2	C2_SXY1,(v1ptr) 		;load transformed XY for nclip
		lwc2	C2_SXY2,(v2ptr)
		lw		v1ptr,4(v1ptr)			;get RG/Z1
		addiu	objptr,8
		gte_nclip						;do nclip (8 cycles)
		lw		v2ptr,4(v2ptr)			;get RG/Z2
		andi	temp,v1ptr,$ffff
		sll 	at,temp,8
		or		temp,at
		sw		temp,rgb1(polyptr)		;make and store rgb1
		srl 	v1ptr,16				;get z1
		lw		v0ptr,4(v0ptr)			;get RG/Z0
		mfc2	at,C2_MAC0				;read the nclip
		andi	temp2,v2ptr,$ffff
		bmi 	.next3					;skip poly if it's back facing
		sll 	temp,temp2,8
		lhu 	txtptr,6-8(objptr)		;get texture number
		or		temp2,temp
		sw		temp2,rgb2(polyptr) 	;make and store rgb2
		srl 	v2ptr,16
		addu	v1ptr,v2ptr 			;z1+z2
		andi	at,v0ptr,$ffff
		srl 	v0ptr,16
		addu	v0ptr,v1ptr 			;z0+z1+z2
		multu	v0ptr,onediv6
		sll 	txtptr,4
		addu	txtptr,txtbase			;make texture pointer
		lw		temp,8(txtptr)			;get uv2 and poly codes
		lw		v1ptr,0(txtptr) 		;get uv0 & clut
		lw		v2ptr,4(txtptr) 		;get uv1 & tpage
		swc2	C2_SXY0,xy0(polyptr)
		swc2	C2_SXY1,xy1(polyptr)	;store xy0..2 from gte
		swc2	C2_SXY2,xy2(polyptr)
		sll 	temp2,at,8
		or		at,temp2				;make rgb0
		and 	temp2,temp,gt3mask		;make poly code
		or		at,temp2
		sw		at,rgb0c(polyptr)		;make and store rgb0c
		sw		temp,uv2(polyptr)		;store uv2
		mfhi	v0ptr					;get average of 3 Zs
		sltiu	temp2,v0ptr,DPQ_END>>1	;make sure otz is in range
		bf		temp2,.next3
		andi	v0ptr,$3ffc 			;dword align it
		addu	v0ptr,otbase			;make ot ptr
		subu	v1ptr,clutsub			;modify clut for underwater
		lw		temp,(v0ptr)			;get previous ot prim ptr
		lui 	at,$0900				;make len
		or		temp,at
		sw		temp,(polyptr)			;store tag & len
		sw		v1ptr,uv0clut(polyptr)	;store uv0 & clut
		sw		v2ptr,uv1tpg(polyptr)	;store uv1 & tpage
		sw 		polyptr,(v0ptr)
		addiu	polyptr,gt3_sz			;move to next poly

.next3	bnz 	num,.GT3lp
		dec 	num

.exit
		gpr.sw	polyptr,(db+db_polyptr)
		lw		pblimit,8(sp)
		lw		clutsub,4(sp)
		lw		normbase,(sp)
		ret
		addiu	sp,12

.doEM4s	mtlo	txtbase						;save a1
		gpr.lw	envtpage,dude_envmap_tpage	;a1=envmap tpage

.EM4lp	lhu 	v0ptr,(objptr)
		cmpu	polyptr,pblimit
		lhu 	v1ptr,2(objptr)
		bhs		.exit
		lhu 	v2ptr,6(objptr) 		;get vertex numbers
		lhu 	v3ptr,4(objptr)
		addu	n0ptr,v0ptr,normbase
		addu	n1ptr,v1ptr,normbase	;make normal pointers
		addu	n2ptr,v2ptr,normbase
		addu	v0ptr,tsvbase
		addu	v1ptr,tsvbase			;make vertex pointers
		addu	v2ptr,tsvbase
		lwc2	C2_SXY0,(v0ptr)
		lwc2	C2_SXY1,(v1ptr) 		;load transformed XY for nclip
		lwc2	C2_SXY2,(v2ptr)
		lhu		temp,8(objptr)			;get CR
		lhu		temp2,10(objptr)		;get GB
		gte_nclip						;do nclip (8 cycles)
		addu	n3ptr,normbase,v3ptr	;v3 normal ptr
		addu	v3ptr,tsvbase			;v3 vector ptr
		lwc2	C2_VXY0,(n0ptr)			;load v0 normal
		lwc2	C2_VZ0,4(n0ptr)
		lwc2	C2_VXY1,(n1ptr)			;load v1 normal
		lwc2	C2_VZ1,4(n1ptr)
		lw		v3tsv,(v3ptr)			;get transformed XY 3 (v3tsv==n0ptr...)
		sll		temp2,16
		mfc2	at,C2_MAC0				;read the nclip
		or		temp,temp2				;make CRGB
		bmi 	.nexte4					;skip poly if it's back facing
		addiu	objptr,12
		mvmva	1,0,0,3,0				;v0*r, 1.3.12, no translate, no limiter
		lw		v1ptr,4(v1ptr)
		lwc2	C2_VXY2,(n2ptr)			;load v2 normal
		lwc2	C2_VZ2,4(n2ptr)
		sw		temp,rgb0c(polyptr)		;store rgb0
		sw		temp,rgb1(polyptr)		;store rgb1
		sw		temp,rgb2(polyptr)		;store rgb2
		sw		temp,rgb3(polyptr)		;store rgb3
		srl 	v1ptr,16				;get z1
		mfc2	temp,C2_MAC1			;get rotated normal x/y
		mfc2	temp2,C2_MAC2
		lwc2	C2_VXY0,(n3ptr)			;load v3 normal into v0
		lwc2	C2_VZ0,4(n3ptr)
		sra		temp,7					;shift rotated normal x/y to desired range (-128..127)
		sll		temp2,1					;y is shifted up by 8 too
		mvmva	1,0,1,3,0				;v1*r
		if		0;JAP
		sra		at,temp2,4
		subu	temp2,at
		addiu	temp2,$7800
		endif
		lw		v2ptr,4(v2ptr)
		andi	temp,$00ff
		andi	temp2,$ff00				;mask off sign bits
		or		temp,temp2				;make uv
		if		0;JAP
		xori	temp,$0080
		else
		xori	temp,$8080
		endif
		sw		temp,uv0clut(polyptr)	;stash uv0 (clut doesn't matter cos its 16 bit)
		srl 	v2ptr,16
		addu	v1ptr,v2ptr 			;z1+z2
		mfc2	temp,C2_MAC1
		mfc2	temp2,C2_MAC2
		sra		temp,7
		sll		temp2,1
		mvmva	1,0,2,3,0				;v2*r
		if		0;JAP
		sra		at,temp2,4
		subu	temp2,at
		addiu	temp2,$7800
		endif
		lw		v3ptr,4(v3ptr)
		andi	temp,$00ff
		andi	temp2,$ff00
		or		temp,temp2
		if		0;JAP
		xori	temp,$0080
		else
		xori	temp,$8080
		endif
		or		temp,envtpage			;or in tpage (middle of current displayed screen)
		sw		temp,uv1tpg(polyptr)	;stash uv1 & tpage
		srl 	v3ptr,16
		addu	v1ptr,v3ptr 			;z1+z2+z3
		mfc2	temp,C2_MAC1
		mfc2	temp2,C2_MAC2
		sra		temp,7
		sll		temp2,1
		mvmva	1,0,0,3,0				;v0*r (v3)
		if		0;JAP
		sra		at,temp2,4
		subu	temp2,at
		addiu	temp2,$7800
		endif
		lw		v0ptr,4(v0ptr)
		andi	temp,$00ff
		andi	temp2,$ff00
		or		temp,temp2
		if		0;JAP
		xori	temp,$0080
		else
		xori	temp,$8080
		endif
		sw		temp,uv2(polyptr)		;stash uv2
		srl 	v0ptr,16
		addu	v0ptr,v1ptr 			;z0+z1+z2+z3
		mfc2	temp,C2_MAC1
		mfc2	temp2,C2_MAC2
		sra		temp,7
		sll		temp2,1
		if		0;JAP
		sra		at,temp2,4
		subu	temp2,at
		addiu	temp2,$7800
		endif
		andi	temp,$00ff
		andi	temp2,$ff00
		or		temp,temp2
		if		0;JAP
		xori	temp,$0080
		else
		xori	temp,$8080
		endif
		sw		temp,uv3(polyptr)		;stash uv3
		swc2	C2_SXY0,xy0(polyptr)
		swc2	C2_SXY1,xy1(polyptr)	;store xy0..2 from gte
		swc2	C2_SXY2,xy2(polyptr)
		sw		v3tsv,xy3(polyptr)		;store xy3 from reg
		srl 	v0ptr,OTRIGHT+2 		;get it in Paul's range <<2
		cmpiu	v0ptr,DPQ_END>>1		;make sure otz is in range
		bhs		.nexte4
		andi	v0ptr,$3ffc 			;dword align it
		addu	v0ptr,otbase			;make ot ptr
		lw		temp,(v0ptr)			;get previous ot prim ptr
		lui 	at,$0c00				;make len
		or		temp,at
		sw		temp,(polyptr)			;store tag & len
		sw	 	polyptr,(v0ptr) 		;store bytes 0..2 into ot
		addiu	polyptr,gt4_sz			;move to next poly

.nexte4	bnz 	num,.EM4lp
		dec 	num

		mflo	txtbase					;restore a1
		lhu		num,(objptr)			;if here, there must be normals -> #em3 count. get it...
		inc.h	objptr
		bz		num,.doGT4s				;no em3s -> go back to gt4s
		dec		num

.doEM3s
		gpr.lw	em3tp,dude_envmap_tpage	;a1=envmap tpage
		mac.li	em31d6,$2aaaaaaa

.EM3lp	lhu 	v0ptr,(objptr)
		cmpu	polyptr,pblimit
		lhu 	v1ptr,2(objptr)
		bhs		.exit
		lhu 	v2ptr,4(objptr) 		;get vertex numbers
		addu	n0ptr,v0ptr,normbase
		addu	n1ptr,v1ptr,normbase	;make normal pointers
		addu	n2ptr,v2ptr,normbase
		addu	v0ptr,tsvbase
		addu	v1ptr,tsvbase			;make vertex pointers
		addu	v2ptr,tsvbase
		lwc2	C2_SXY0,(v0ptr)
		lwc2	C2_SXY1,(v1ptr) 		;load transformed XY for nclip
		lwc2	C2_SXY2,(v2ptr)
		lhu		temp,6(objptr)			;get CR
		lhu		temp2,8(objptr)			;get GB
		gte_nclip						;do nclip (8 cycles)
		lwc2	C2_VXY0,(n0ptr)			;load v0 normal
		lwc2	C2_VZ0,4(n0ptr)
		lw		v0ptr,4(v0ptr)
		lw		v1ptr,4(v1ptr)
		sll		temp2,16
		or		temp,temp2				;make CRGB
		addiu	objptr,10
		mfc2	at,C2_MAC0				;read the nclip
		srl 	v0ptr,16				;get z0
		bmi 	.nexte3					;skip poly if it's back facing
		srl 	v1ptr,16				;get z1
		mvmva	1,0,0,3,0				;v0*r, 1.3.12, no translate, no limiter
		lw		v2ptr,4(v2ptr)
		lwc2	C2_VXY1,(n1ptr)			;load v1 normal
		lwc2	C2_VZ1,4(n1ptr)
		addu	v0ptr,v1ptr				;z0+z1
		sw		temp,rgb0c(polyptr)		;store rgb0
		sw		temp,rgb1(polyptr)		;store rgb1
		sw		temp,rgb2(polyptr)		;store rgb2
		srl		v2ptr,16				;get z2
		mfc2	temp,C2_MAC1			;get rotated normal x/y
		mfc2	temp2,C2_MAC2
		sra		temp,7					;shift rotated normal x/y to desired range (-128..127)
		sll		temp2,1					;y is shifted up by 8 too
		mvmva	1,0,1,3,0				;v1*r
		if		0;JAP
		sra		at,temp2,4
		subu	temp2,at
		addiu	temp2,$7800
		endif
		lwc2	C2_VXY2,(n2ptr)			;load v2 normal
		lwc2	C2_VZ2,4(n2ptr)
		addu	v0ptr,v2ptr				;z0+z1+z2
		multu	v0ptr,em31d6			;(z0+z1+z2)/6 -> hi
		andi	temp,$00ff
		andi	temp2,$ff00				;mask off sign bits
		or		temp,temp2				;make uv
		if		0;JAP
		xori	temp,$0080
		else
		xori	temp,$8080
		endif
		sw		temp,uv0clut(polyptr)	;stash uv0 (clut doesn't matter cos its 16 bit)
		mfc2	temp,C2_MAC1
		mfc2	temp2,C2_MAC2
		sra		temp,7
		sll		temp2,1
		mvmva	1,0,2,3,0				;v2*r
		if		0;JAP
		sra		at,temp2,4
		subu	temp2,at
		addiu	temp2,$7800
		endif
		andi	temp,$00ff
		andi	temp2,$ff00
		mfhi	v0ptr					;otz
		cmpiu	v0ptr,DPQ_END>>1		;make sure otz is in range
		bhs		.nexte3
		or		temp,temp2
		if		0;JAP
		xori	temp,$0080
		else
		xori	temp,$8080
		endif
		or		temp,em3tp				;or in tpage (middle of current displayed screen)
		sw		temp,uv1tpg(polyptr)	;stash uv1 & tpage
		mfc2	temp,C2_MAC1
		mfc2	temp2,C2_MAC2
		sra		temp,7
		sll		temp2,1
		if		0;JAP
		sra		at,temp2,4
		subu	temp2,at
		addiu	temp2,$7800
		endif
		andi	temp,$00ff
		andi	temp2,$ff00
		or		temp,temp2
		if		0;JAP
		xori	temp,$0080
		else
		xori	temp,$8080
		endif
		sw		temp,uv2(polyptr)		;stash uv2
		swc2	C2_SXY0,xy0(polyptr)
		swc2	C2_SXY1,xy1(polyptr)	;store xy0..2 from gte
		swc2	C2_SXY2,xy2(polyptr)
		andi	v0ptr,$3ffc 			;dword align it
		addu	v0ptr,otbase			;make ot ptr
		lw		temp,(v0ptr)			;get previous ot prim ptr
		lui 	at,$0900				;make len
		or		temp,at
		sw		temp,(polyptr)			;store tag & len
		sw	 	polyptr,(v0ptr) 		;store bytes 0..2 into ot
		addiu	polyptr,gt3_sz			;move to next poly

.nexte3	bnz 	num,.EM3lp
		dec 	num

		b		.doGT4b
		lhu		num,(objptr)

		endif
