;****************************************************************************
;
;
;
;
;****************************************************************************


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

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

FARTHEST_Z	equ	$5000
MAX_VERTICES	equ	93

DCACHE	equ	$1f800000
LIGHTS	equ	DCACHE+768

; -------- global GTE workspace

CLIPL	equr	C2_L11L12
CLIPR	equr	C2_L13L21
CLIPT	equr	C2_L22L23
CLIPB	equr	C2_L31L32
ROOMX	equr	C2_RBK
ROOMY	equr	C2_GBK
ROOMZ	equr	C2_BBK
WATER	equr	C2_RFC

FACE	equr	C2_DQB
VERTS	equr	C2_LR1LR2
TEMP1	equr	C2_LR3LG1
TEMP2	equr	C2_LG2LG3
BFACE	equr	C2_LB1LB2
TEMP4	equr	C2_DQA

WIBBLE	equr	C2_LB3
WIBTAB	equr	C2_RGB0		; mtc2

;
; Subdiv stores.
;

DS_FLAG	equr	C2_L33
TPAGE	equr	C2_RGB1
CLUT	equr	C2_RGB2

XMASK		equ	%111110000000000
YMASK		equ	%1111100000
ZMASK		equ	%11111

OTSIZE		equ	2560

NEAR_CLIP	equ	4
SUBDIV1		equ	768
SUBDIV2		equ	384
MIPMAP1		equ	1024*4
MIPMAP2		equ	2048*4

GT3_LEN		equ	9
GT4_LEN		equ	12
FT3_LEN		equ	7
FT4_LEN		equ	9

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

SCREEN_WIDTH	equ	320	;512
SCREEN_HEIGHT	equ	240

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

; -------- MMTEXTINFO structure

		rsreset
mmTextInfo	rb	tiSIZEOF*3
mmSIZEOF	rb	0

; -------- MESH_HEADER structure

		rsreset
mhBoundMinIndex	rh	1
mhBoundMaxIndex	rh	1
mhTransIndex	rb	1
mhFlags		rb	1
mhVertices	rb	1	; # vertices
mhTriangles	rb	1	; # triangles
mhSIZEOF	rb	0

; -------- WATERTAB structure

		rsreset
wtShimmer	rb	1
wtChoppy	rb	1
wtRandom	rb	1
wtAbs		rb	1
wtSIZEOF	rb	0

; -------- POLY_GT3/4 structure

		rsreset
gtTag		rw	1
gtRGB0		rw	1
gtX0		rh	1
gtY0		rh	1
gtU0		rb	1
gtV0		rb	1
gtClut		rh	1
gtRGB1		rw	1
gtX1		rh	1
gtY1		rh	1
gtU1		rb	1
gtV1		rb	1
gtTpage		rh	1
gtRGB2		rw	1
gtX2		rh	1
gtY2		rh	1
gtU2		rb	1
gtV2		rb	1
gtPad2		rh	1
SIZEOF_GT3	rb	0
gtRGB3		rw	1
gtX3		rh	1
gtY3		rh	1
gtU3		rb	1
gtV3		rb	1
gtPad3		rh	1
SIZEOF_GT4	rb	0

		rsreset
ftTag		rw	1
ftRGB0		rw	1
ftX0		rh	1
ftY0		rh	1
ftU0		rb	1
ftV0		rb	1
ftClut		rh	1
ftX1		rh	1
ftY1		rh	1
ftU1		rb	1
ftV1		rb	1
ftTpage		rh	1
ftX2		rh	1
ftY2		rh	1
ftU2		rb	1
ftV2		rb	1
ftPad1		rh	1
SIZEOF_FT3	rb	0
ftX3		rh	1
ftY3		rh	1
ftU3		rb	1
ftV3		rb	1
ftPad2		rh	1
SIZEOF_FT4	rb	0

		rsreset
liXPos		rw	1
liYPos		rw	1
liZPos		rw	1
liFalloff	rb	1
liR		rb	1
liG		rb	1
liB		rb	1
LIGHT_INFO	rb	0

		rsreset
li2XYZPos	rw	1
li2Falloff	rb	1
li2R		rb	1
li2G		rb	1
li2B		rb	1
LIGHT_INFO2	rb	0

		rsreset
regra		rw	1
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
rega1		rw	1
STACKFRAME	rb	0

		rsreset
vSX		rh	1	; screen x
vSY		rh	1	; screen y
vSZ		rh	1	; screen z
vPad		rb	2
vX		rh	1	; world x
vY		rh	1	; world y
vZ		rh	1	; world z
vU		rb	1
vV		rb	1
vRGB		rw	1	; 24bit colour
SIZEOF_SVERTEX	rb	0

		rsreset
spVertices	rw	2*MAX_VERTICES
spV0		rb	SIZEOF_SVERTEX
spV1		rb	SIZEOF_SVERTEX
spV2		rb	SIZEOF_SVERTEX
spV3		rb	SIZEOF_SVERTEX

spV4		rb	SIZEOF_SVERTEX
spV5		rb	SIZEOF_SVERTEX
spV6		rb	SIZEOF_SVERTEX
spV7		rb	SIZEOF_SVERTEX
spV8		rb	SIZEOF_SVERTEX

spV9		rb	SIZEOF_SVERTEX
spV10		rb	SIZEOF_SVERTEX
spV11		rb	SIZEOF_SVERTEX
spV12		rb	SIZEOF_SVERTEX
spV13		rb	SIZEOF_SVERTEX

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

	XREF	room
	XREF	RoomTextInfo
	XREF	RoomBBoxes
	XREF	OurSqrt

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

	cnop	0,4

;
; Quad sub-division tables.
;

QuadVertTable
	dh	spV0,spV1	; a
	dh	spV1,spV3       ; b
	dh	spV3,spV2       ; c
	dh	spV2,spV0       ; d
	dh	spV1,spV2       ; e

	dh	spV0,spV4,spV7,spV8
	dh	spV4,spV1,spV8,spV5
	dh	spV7,spV8,spV2,spV6
	dh	spV8,spV5,spV6,spV3

QVertTableA
	dh	spV0,spV4	; a
	dh	spV4,spV8       ; b
	dh	spV8,spV7       ; c
	dh	spV7,spV0       ; d
	dh	spV4,spV7       ; e

	dh	spV0,spV9,spV12,spV13
	dh	spV9,spV4,spV13,spV10
	dh	spV12,spV13,spV7,spV11
	dh	spV13,spV10,spV11,spV8

QVertTableB
	dh	spV4,spV1	; a
	dh	spV1,spV5       ; b
	dh	spV5,spV8       ; c
	dh	spV8,spV4       ; d
	dh	spV1,spV8       ; e

	dh	spV4,spV9,spV12,spV13
	dh	spV9,spV1,spV13,spV10
	dh	spV12,spV13,spV8,spV11
	dh	spV13,spV10,spV11,spV5

QVertTableC
	dh	spV7,spV8	; a
	dh	spV8,spV6       ; b
	dh	spV6,spV2       ; c
	dh	spV2,spV7       ; d
	dh	spV8,spV2       ; e

	dh	spV7,spV9,spV12,spV13
	dh	spV9,spV8,spV13,spV10
	dh	spV12,spV13,spV2,spV11
	dh	spV13,spV10,spV11,spV6

QVertTableD
	dh	spV8,spV5	; a
	dh	spV5,spV3       ; b
	dh	spV3,spV6       ; c
	dh	spV6,spV8       ; d
	dh	spV5,spV6       ; e

	dh	spV8,spV9,spV12,spV13
	dh	spV9,spV5,spV13,spV10
	dh	spV12,spV13,spV6,spV11
	dh	spV13,spV10,spV11,spV3

QuadVertTables
	dw	QVertTableD
	dw	QVertTableC
	dw	QVertTableB
	dw	QVertTableA

;
; Tri sub-division tables.
;

TriVertTable
	dh	spV0,spV1	; a
	dh	spV1,spV2       ; b
	dh	spV2,spV0       ; c

	dh	spV0,spV3,spV5,0
	dh	spV3,spV1,spV4,0
	dh	spV3,spV4,spV5,0
	dh	spV5,spV4,spV2,0

TVertTableA
	dh	spV0,spV3	; a
	dh	spV3,spV5       ; b
	dh	spV5,spV0       ; c

	dh	spV0,spV6,spV8,0
	dh	spV6,spV3,spV7,0
	dh	spV6,spV7,spV8,0
	dh	spV8,spV7,spV5,0

TVertTableB
	dh	spV3,spV1	; a
	dh	spV1,spV4       ; b
	dh	spV4,spV3       ; c

	dh	spV3,spV6,spV8,0
	dh	spV6,spV1,spV7,0
	dh	spV6,spV7,spV8,0
	dh	spV8,spV7,spV4,0

TVertTableC
	dh	spV3,spV4	; a
	dh	spV4,spV5       ; b
	dh	spV5,spV3	; c

	dh	spV3,spV6,spV8,0
	dh	spV6,spV4,spV7,0
	dh	spV6,spV7,spV8,0
	dh	spV8,spV7,spV5,0

TVertTableD
	dh	spV5,spV4	; a
	dh	spV4,spV2       ; b
	dh	spV2,spV5       ; c

	dh	spV5,spV6,spV8,0
	dh	spV6,spV4,spV7,0
	dh	spV6,spV7,spV8,0
	dh	spV8,spV7,spV2,0

TriVertTables
	dw	TVertTableD
	dw	TVertTableC
	dw	TVertTableB
	dw	TVertTableA

YOffsets	dcb	93*4,0

LightOffsetTab	incbin ..\spec_psx\offset.tab
LightTab	incbin ..\spec_psx\coltab.tab

	cnop	0,4

;----------------------------------------------------------------------------
;GetBounds
;
;Purpose:	Updates the current bounds
;
;Inputs:        s0 = left boundary
;		s1 = right boundary
;		s2 = top boundary
;		s3 = bottom boundary
;		t0 = screen xy 0
;		t1 = screen z 0
;		t6 = screen xy 1
;		t7 = screen z 1
;		t8 = screen xy 2
;		t9 = screen z 2
;		v0 = z count
;
;Outputs:	s0-s3 = update bounds
;		v0 = updated z count
;
;Usage:		t0/t6/t8/v1/at
;
;Timing:	40/52
;
;----------------------------------------------------------------------------

GetBounds:
	sll	v1,t0,16
	sra	v1,16
	slt	at,v1,s0		; x0 < bound left
	beqz	at,@r1
	slt	at,v1,s1		; x0 > bound right
	move	s0,v1
@r1	bnez	at,@t1
	sra	t0,16
	move	s1,v1
@t1	slt	at,t0,s2		; y0 < bound top
	beqz	at,@b1
	slt	at,t0,s3		; y0 > bound bottom
	move	s2,t0
@b1	bnez	at,@2
	sll	v1,t6,16
	move	s3,t0
@2:
	sra	v1,16
	slt	at,v1,s0		; x1 < bound left
	beqz	at,@r2
	slt	at,v1,s1		; x1 > bound right
	move	s0,v1
@r2	bnez	at,@t2
	sra	t6,16
	move	s1,v1
@t2	slt	at,t6,s2		; y1 < bound top
	beqz	at,@b2
	slt	at,t6,s3		; y1 > bound bottom
	move	s2,t6
@b2	bnez	at,@3
	sll	v1,t8,16
	move	s3,t6
@3
	sra	v1,16
	slt	at,v1,s0		; x2 < bound left
	beqz	at,@r3
	slt	at,v1,s1		; x2 > bound right
	move	s0,v1
@r3	bnez	at,@t3
	sra	t8,16
	move	s1,v1
@t3	slt	at,t8,s2		; y2 < bound top
	beqz	at,@b3
	slt	at,t8,s3		; y2 > bound bottom
	move	s2,t8
@b3	bnez	at,@end
	sltiu	at,t1,FARTHEST_Z
	move	s3,t8
@end
	bnez	at,@z1
	sltiu	at,t7,FARTHEST_Z
	addi	v0,1
@z1	bnez	at,@z2
	sltiu	at,t9,FARTHEST_Z
	addi	v0,1
@z2	bnez	at,@z3
	nop
	addi	v0,1
@z3	jr	ra
	nop

;----------------------------------------------------------------------------
;UnpackRGB
;
;Purpose:	Unpacks 3 15bit RGBs into 24bit colour vectors
;
;Inputs:        t1 = rgb #1
;		t2 = rgb #2
;		t3 = rgb #3
;		s2 = $00f80000
;
;Outputs:       t1 = CVECTOR #1
;		t2 = CVECTOR #2
;		t3 = CVECTOR #3
;
;Usage:		t1-t3/t5-t8
;
;Timing:	28
;
;----------------------------------------------------------------------------

UnpackRGB:
	srl	t5,s4,7	  		; convert 5bit RGBs into 24bit RGBs
	and	t5,s2
	srl	t6,s4,10
	andi	t6,$f800
	srl	fp,s4,13
	andi	fp,$f8
	or	fp,t5
	or	fp,t6
	srl	t5,t8,24 		; primitive id in top 8 bits
	sll	t5,24
	or	fp,t5

	srl	t5,s5,7
	and	t5,s2
	srl	t6,s5,10
	andi	t6,$f800
	srl	gp,s5,13
	andi	gp,$f8
	or	gp,t5
	or	gp,t6

	srl	t5,s6,7
	and	t5,s2
	srl	t6,s6,10
	andi	t6,$f800
	srl	s3,s6,13
	andi	s3,$f8
	or	s3,t5
	jr	ra
	or	s3,t6

;----------------------------------------------------------------------------
;ClipXY
;
;Purpose:	Clips four sets of screen co-ordinates against the current
;		clip window.
;
;Inputs:	t1 = xy #1
;		t2 = xy #2
;		t3 = xy #3
;		t4 = xy #4
;
;Outputs:   	t5 = clip flag
;
;Usage:		t5-t9/fp
;
;Timing:
;
;----------------------------------------------------------------------------

ClipXY	cfc2	t9,CLIPT
	sll	t5,t1,16
	slt	at,t1,t9		; top clip
	beqz	at,@bclip
	slt	at,t2,t9
	beqz	at,@bclip
	slt	at,t3,t9
	beqz	at,@bclip
	slt	at,t4,t9
	bnez	at,@clipped
@bclip:
	sll	t6,t2,16		; bottom clip
	cfc2	t9,CLIPB
	sll	t7,t3,16
	slt	at,t1,t9
	bnez	at,@lclip
	slt	at,t2,t9
	bnez	at,@lclip
	slt	at,t3,t9
	bnez	at,@lclip
	slt	at,t4,t9
	beqz	at,@clipped
@lclip:
	sll	t8,t4,16		; left clip
	cfc2	t9,CLIPL
	cfc2	fp,CLIPR
	slt	at,t5,t9
	beqz	at,@rclip
	slt	at,t6,t9
	beqz	at,@rclip
	slt	at,t7,t9
	beqz	at,@rclip
	slt	at,t8,t9
	bnez	at,@clipped
@rclip:
	slt	at,t5,fp		; right clip
	bnez	at,@ok
	slt	at,t6,fp
	bnez	at,@ok
	slt	at,t7,fp
	bnez	at,@ok
	slt	at,t8,fp
	beqz	at,@clipped
	nop
@ok:
	jr	ra
	move	t5,zero
@clipped:
	jr	ra
	ori	t5,zero,1


;---------------------------------------------
;
; Common code in sub-routine for subdivision.
; Initialises initial vertices ready for subdivision.
;
;---------------------------------------------

InitSubdivision:
	sw	t1,spV0+vSX(s1)		; initialise vertex #0
	sh	s4,spV0+vSZ(s1)
	sw	fp,spV0+vRGB(s1)
	sh	t5,spV0+vU(s1)
	sw	t2,spV1+vSX(s1)		; initialise vertex #1
	sh	s5,spV1+vSZ(s1)
	sw	gp,spV1+vRGB(s1)
	sh	t6,spV1+vU(s1)
	sw	t3,spV2+vSX(s1)		; initialise vertex #2
	sh	s6,spV2+vSZ(s1)
	sw	s3,spV2+vRGB(s1)
	sh	t7,spV2+vU(s1)

	la	gp,YOffsets  	; Wibble offsets - for subdiv.

	srl	fp,24
	sll	fp,24
	lui	t1,$ffff
	and	t5,t1
	and	t6,t1
	mtc2	t5,CLUT		; Clut
	mtc2	t6,TPAGE	; TPage

	cfc2	t0,FACE			; fetch original vertices
	cfc2	t5,VERTS

;##	srl	t2,t0,14
	srl	t2,t0,12
	andi	t2,$1fc
	add	s5,gp,t2	; Y Offsets.
	add	t2,t5

;##	srl	t1,t0,6
	srl	t1,t0,5
	andi	t1,$1fc
	add	s4,gp,t1	; Y Offsets.
	add	t1,t5

	sll	t0,2
	andi	t0,$1fc
	add	s3,gp,t0	; Y Offsets.
	add	t0,t5

	lw	t0,0(t0)
	lw	t1,0(t1)
	lw	t2,0(t2)

	andi	t4,t0,YMASK
	sll	t4,3
	bgtz	t0,@noyadd1		; Wibbled vertex ?
	andi	t5,t0,ZMASK		; unpack vertex #0

	lw	t6,0(s3)
	nop
	add	t4,t6      		; re-wibble

@noyadd1:
	sll	t5,10
	andi	t0,XMASK
	sh	t0,spV0+vX(s1)
	sh	t4,spV0+vY(s1)
	sh	t5,spV0+vZ(s1)

	andi	t4,t1,YMASK
	sll	t4,3
	bgtz	t1,@noyadd2		; Wibbled vertex ?
	andi	t5,t1,ZMASK		; unpack vertex #1

	lw	t6,0(s4)
	nop
	add	t4,t6

@noyadd2:
	sll	t5,10
	andi	t1,XMASK
	sh	t1,spV1+vX(s1)
	sh	t4,spV1+vY(s1)
	sh	t5,spV1+vZ(s1)

	andi	t4,t2,YMASK
	sll	t4,3
	bgtz	t2,@noyadd3		; Wibbled vertex ?
	andi	t5,t2,ZMASK		; unpack vertex #2

	lw	t6,0(s5)
	nop
	add	t4,t6         		; re-wibble

@noyadd3:
	sll	t5,10
	andi	t2,XMASK
	sh	t2,spV2+vX(s1)
	sh	t4,spV2+vY(s1)

	jr	ra
	sh	t5,spV2+vZ(s1)


;----------------------------------------------------------------------------
;SubPolyGT3
;
;Purpose:	Subdivides uv's RGB's etc. for tris and quads.
;		Just needs gp setting up with number of points.
;
;--------------------------------------------------------------------------

SubPolyGTLoop:
	lui	t2,$f8
	ori	t2,$f8f8

@loop1:
	lw	t3,0(t0)		; read vertex pair
	addi	t0,4
	srl	t4,t3,16
	andi	t3,$ffff
	add	t3,s1			; t3 = vertex #0
	add	t4,s1			; t4 = vertex #1

	lh	t5,vX(t3)		; subdivide XYZ
	lh	t6,vY(t3)
	lh	t7,vX(t4)
	lh	t8,vY(t4)
	add	t5,t7
	srl	t5,1
	add	t6,t8
	lh	t7,vZ(t3)
	lh	t8,vZ(t4)
	srl	t6,1
	add	t7,t8
	srl	t7,1
	sh	t5,vX(t1)
	sh	t6,vY(t1)

	sll	t6,16
	or	t6,t5
	mtc2	t6,C2_VXY0
	mtc2	t7,C2_VZ0
	sh	t7,vZ(t1)
	GTE_RTPS			; Rotate new point - 14 cycles.

	lbu	t5,vU(t3)		; subdivide UVs
	lbu	t6,vV(t3)
	lbu	t7,vU(t4)
	lbu	t8,vV(t4)
	add	t5,t7
	srl	t5,1
	add	t6,t8
	lw      t7,vRGB(t3)
	lw      t8,vRGB(t4)
	srl	t6,1
	sb	t5,vU(t1)

	swc2	C2_SXY2,vSX(t1)
	swc2	C2_SZ3,vSZ(t1)

	add	t7,t8			; subdivide RGBs
	srl	t7,1
	and	t7,t2			; << $fff8f8f8
	sw	t7,vRGB(t1)
	sb	t6,vV(t1)

	subi	gp,1
	bnez	gp,@loop1
	add	t1,SIZEOF_SVERTEX

@exit:
	jr	ra
	nop

;
;
;

SubdivSetup3:
;	lui	at,$8000	;
;	ori	at,$8000        ;
;	mfc2	t7,C2_SXY0      ;
;	mfc2	t8,C2_SXY1      ; CLIP TOP & LEFT !!!
;	and	at,t7           ;
;	mfc2	t7,C2_SXY2      ;
;	and	at,t8           ;
;	and	at,t7           ;

	swc2	C2_SXY0,gtX0(a3)
	swc2	C2_SXY1,gtX1(a3)
	swc2	C2_SXY2,gtX2(a3)

	lw	t7,vRGB(t3)
	lhu	t8,vU(t3)
	or	t7,fp           	; or prim type
	or	t8,t1			; | Clut.
	sw	t7,gtRGB0(a3)
	sw	t8,gtU0(a3)

	lw	t7,vRGB(t4)
	lhu	t8,vU(t4)
	sw	t7,gtRGB1(a3)
	or	t8,t2			; | TPage.
	sw	t8,gtU1(a3)

	lw	t7,vRGB(t5)
	lhu	t8,vU(t5)
	sw	t7,gtRGB2(a3)

	jr	ra
	sw	t8,gtU2(a3)


;----------------------------------------------------------------------------
;SubPolyGT3
;
;Purpose:	Subdivides a triangle into four POLY_GT3s
;
;               0
;              / \
;             / 1 \
;         C3 /_____\ A5
;           /\     /\
;          /  \ 3 /  \
;         / 2  \ / 4  \
;        /______\______\
;	1       B4       2

;Inputs:	t0 = ptr to poly creation list
;		t1 = ptr to destination polys
;
;Outputs:
;
;Usage:		t5-t9/fp
;		gp - counter 0-3 (A-D), 4 = point E.
;
;Timing:
;
;----------------------------------------------------------------------------


SubPolyGT3:
	move	s7,ra
	jal	SubPolyGTLoop
	ori	gp,zero,3
	move	ra,s7
;
; Add prim loop.
;
	ori	gp,zero,3		; set up loop
	mfc2	t1,CLUT     		; Clut
	mfc2	t2,TPAGE		; TPage
@loop2:
	lw	t3,0(t0)		; read vertex pair
	lh	t5,4(t0)		; read vertex pair
	add	t0,8
	srl	t4,t3,16
	andi	t3,$ffff
	add	t3,s1			; t3 = vertex #0
	add	t4,s1			; t4 = vertex #1
	add	t5,s1			; t5 = vertex #2

	lwc2	C2_SXY0,vSX(t3)		; N-CLIP reg 1
	lwc2	C2_SXY1,vSX(t4)		; N-CLIP reg 2
	lwc2	C2_SXY2,vSX(t5)		; N-CLIP reg 3
	lh	t7,vSZ(t3)		; Gibby lhu
	lh	t8,vSZ(t4)
	GTE_NCLIP			; NormalClip (8)

	slt	at,t7,t8
	beqz	at,@zs1
	lh	t9,vSZ(t5)

	move	t7,t8
@zs1:
	slt	at,t7,t9
	beqz	at,@zs2
	srl	t7,3

	srl	t7,t9,3

@zs2:
	sltiu	at,t7,NEAR_CLIP
	bnez  	at,@nextpoly
	sltiu	at,t7,SUBDIV2
	beqz	at,@dopoly
	sll	t9,t7,2		; t9 = OT

@subdiv:
	bnez	s3,@dopoly	; in 16 loop?
	ori	s3,zero,1	; set 16 loop flag.

	move	s4,gp
	move	s5,ra
	move	s6,t0

	la	t0,TriVertTables
	sll	at,gp,2
	add	t0,at
	lw	t0,0(t0)
	jal	SubPolyGT3
	addi	t1,s1,spV6

	mfc2	t1,CLUT     	; Clut
	mfc2	t2,TPAGE	; TPage
	move	s3,zero		; reset 16 loop flag.
	move	gp,s4
	move	ra,s5
	j	@nextpoly
	move	t0,s6

@dopoly:
	cfc2	t8,DS_FLAG	; fetch double sided flag
	mfc2	t7,C2_MAC0	; fetch Cross Product

	bnez	t8,@draw	; double sided ?
	move	s7,ra

	bltz	t7,@nextpoly
	nop

@draw:
	cfc2	t9,TEMP1		; restore OT
	jal	SubdivSetup3
	add	t9,s0

	move	ra,s7

;	bltz	at,@nextpoly
;	sll	at,16
;	bltz	at,@nextpoly

; -------- AddPrim

;	add	t9,4

	lui	t5,GT3_LEN<<8
	lw	t7,0(t9)
	sw	a3,0(t9)
	or	t7,t5
	sw	t7,0(a3)
	addi	a3,SIZEOF_GT3

@nextpoly:
	bnez	gp,@loop2
	subi	gp,1
@next:

	jr	ra
	nop

;----------------------------------------------------------------------------
;SubPolyGT4
;
;Purpose:	Subdivides a polygon into four POLY_GT4s
;
;	0----A----1
;	|    |    |
;	|    |    |
;	D----E----B
;	|    |    |
;	|    |    |
;	2----C----3
;
;Inputs:	t0 = ptr to poly creation list
;		t1 = ptr to destination polys
;
;Outputs:
;
;Usage:		t5-t9/fp
;		gp - counter 0-3 (A-D), 4 = point E.
;
;Timing:
;
;----------------------------------------------------------------------------


SubPolyGT4:
	move	s7,ra
	jal	SubPolyGTLoop
	ori	gp,zero,5
	move	ra,s7
;
; Add prim loop.
;
	ori	gp,zero,3		; set up loop
	mfc2	t1,CLUT     		; Clut
	mfc2	t2,TPAGE		; TPage
@loop2:
	lw	t3,0(t0)		; read vertex pair
	lw	t5,4(t0)		; read vertex pair
	add	t0,8
	srl	t4,t3,16
	andi	t3,$ffff
	add	t3,s1			; t3 = vertex #0
	add	t4,s1			; t4 = vertex #1

	srl	t6,t5,16
	andi	t5,$ffff
	add	t5,s1			; t5 = vertex #2
	add	t6,s1			; t6 = vertex #3

	lwc2	C2_SXY0,vSX(t3)		; N-CLIP reg 1
	lwc2	C2_SXY1,vSX(t4)		; N-CLIP reg 2
	lwc2	C2_SXY2,vSX(t5)		; N-CLIP reg 3
	lh	t7,vSZ(t3)		; Gibby lhu.
	lh	t8,vSZ(t4)
	GTE_NCLIP			; NormalClip (8)

	slt	at,t7,t8
	beqz	at,@zs1
	lh	t9,vSZ(t5)

	move	t7,t8
@zs1:
	slt	at,t7,t9
	beqz	at,@zs2
	lh	t8,vSZ(t6)

	move	t7,t9
@zs2:
	slt	at,t7,t8
	beqz	at,@zs3
	srl	t7,3

	srl	t7,t8,3
@zs3:
	sltiu	at,t7,NEAR_CLIP
	bnez  	at,@nextpoly
	sltiu	at,t7,SUBDIV2
	beqz	at,@dopoly
	sll	t9,t7,2		; t9 = OT

@subdiv:
	bnez	s3,@dopoly	; in 16 loop?
	ori	s3,zero,1	; set 16 loop flag.

	move	s4,gp
	move	s5,ra
	move	s6,t0

	la	t0,QuadVertTables
	sll	at,gp,2
	add	t0,at
	lw	t0,0(t0)
	jal	SubPolyGT4
	addi	t1,s1,spV9

	mfc2	t1,CLUT     	; Clut
	mfc2	t2,TPAGE	; TPage
	move	s3,zero		; reset 16 loop flag.
	move	gp,s4
	move	ra,s5
	j	@nextpoly
	move	t0,s6

@dopoly:
	cfc2	t8,DS_FLAG	; fetch double sided flag
	mfc2	t7,C2_MAC0	; fetch Cross Product

	bnez	t8,@draw	; double sided ?
	move	s7,ra

	bltz	t7,@nextpoly
	nop

@draw:
	cfc2	t9,TEMP1		; restore OT
	jal	SubdivSetup3
	add	t9,s0

	move	ra,s7

	lw	t5,vSX(t6)
	lw	t7,vRGB(t6)
;	and	at,t5		; CLIP TOP AND LEFT!!
	lhu	t8,vU(t6)
	sw	t5,gtX3(a3)
	sw	t7,gtRGB3(a3)
	sw	t8,gtU3(a3)

;	bltz	at,@nextpoly
;	sll	at,16
;	bltz	at,@nextpoly

; -------- AddPrim

;	add	t9,4


	lui	t5,GT4_LEN<<8
	lw	t7,0(t9)
	sw	a3,0(t9)
	or	t7,t5
	sw	t7,0(a3)
	addi	a3,SIZEOF_GT4

@nextpoly:
	bnez	gp,@loop2
	subi	gp,1
@next:

	jr	ra
	nop

;----------------------------------------------------------------------------
;DrawRoomMesh
;
;Purpose:	Draws a single room mesh
;
;Inputs:	t9 = OT pos
;		s0 = OT base address
;		a3 = prim ptr
;		t1 = sizeof primitive
;		t2 = primitive length (longs)
;
;Outputs:	None
;
;Usage:		a0-a3/t0-t9/v0-v1
;
;----------------------------------------------------------------------------

MyAddPrim:
	add	t9,s0
;	add	t9,4	; Push polys further back.
	lw	t0,0(t9)
	sw	a3,0(t9)
	or	t0,t1
	sw	t0,0(a3)

	jr	ra
	add	a3,t2

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

	XDEF	DrawMesh2
	XDEF	GetBounds
	XDEF	UnpackRGB
	XDEF	DummyTwat2

;----------------------------------------------------------------------------
;DrawRoomMesh
;
;Purpose:	Draws a single room mesh
;
;Inputs:	a0 = mesh #
;		a1 = current drawing environment
;
;Outputs:	None
;
;Usage:		a0-a3/t0-t9/v0-v1
;
;----------------------------------------------------------------------------

DrawMesh2:
	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)
	sw	a1,rega1(sp)

;--------------------------------------
; check bounding box
;--------------------------------------

	lui	a2,RoomBBoxes>>16
	lw	a2,RoomBBoxes&$ffff(a2)
	lw	t3,mhBoundMinIndex(a0)	; read bounding box min # & max #
	lui	t7,$ffff

	sll	t0,t3,3
	andi	t0,$fff8
	add	t0,a2
	lh	t1,4(t0)		; t1 = minz
	srl	t3,13
	lw	t0,0(t0)		; t0 = minx, miny
	andi	t3,$fff8
	add	t3,a2
	lw	t2,0(t3)		; t2 = maxx, maxy
	andi	t4,t0,$ffff
	lh	t3,4(t3)		; t3 = maxz

	mtc2	t0,C2_VXY0		; minx, miny, minz
	mtc2	t1,C2_VZ0
	mtc2	t2,C2_VXY1		; maxx, maxy, minz
	mtc2	t1,C2_VZ1
	mtc2	t2,C2_VXY2		; maxx, maxy, maxz
	mtc2	t3,C2_VZ2
	and	t5,t0,t7
	GTE_RTPT

	move	a2,fp

	andi	t6,t2,$ffff
	and	t7,t2,t7
	or	t4,t7			; t4 = minx, maxy
	or	t5,t6			; t5 = maxx, miny

	ori	s0,zero,SCREEN_WIDTH
	move	s1,zero
	ori	s2,zero,SCREEN_HEIGHT

	mfc2	t1,C2_SZ0		; read transformed vertices
	mfc2	t6,C2_SXY1
	mfc2	t7,C2_SZ1
	mfc2	t8,C2_SXY2
	mfc2	t9,C2_SZ2
	mtc2	t4,C2_VXY0		; minx, maxy, minz
	mtc2	t5,C2_VXY1		; maxx, miny, minz
	mtc2	t0,C2_VXY2		; minx, miny, maxz
	mfc2	t0,C2_SXY0
	move	s3,zero
	GTE_RTPT			; RotTransPers3 (22)

	jal	GetBounds
	move	v0,zero

	mfc2	t0,C2_SXY0		; read transformed vertices
	mfc2	t1,C2_SZ0
	mfc2	t6,C2_SXY1
	mfc2	t7,C2_SZ1
	mfc2	t8,C2_SXY2
	mtc2	t3,C2_VZ0		; minx, maxy, maxz
	mtc2	t3,C2_VZ1		; maxx, miny, maxz
	mfc2	t9,C2_SZ2
	lui	s5,OurSqrt>>16		; s5 = sqrt table
	GTE_RTPT			; RotTransPers3 (22)

	jal	GetBounds
	lb	s6,mhFlags(a0)		; Get room flags

	mfc2	t0,C2_SXY0		; read transformed vertices
	mfc2	t1,C2_SZ0
	mfc2	t6,C2_SXY1
	mfc2	t7,C2_SZ1
	move	t8,t6
	move	t9,t7

	jal	GetBounds
	andi	s6,2			; Get 'ALWAYS DRAW THIS ROOM' flag.

; !!!!!!!!!!!!!!!
; test 'ALWAYS DRAW THIS ROOM' flag before checking if bbox out of Z range
; !!!!!!!!!!!!!!!

;	bnez	s6,@outside

;	sltiu	at,v0,8
;	beqz	at,@exit

; -------- clip mesh bounding box to room clip window

@outside
	lw	s4,riClipL(a2)
	lw	s6,riClipT(a2)
	srl	v0,s4,16		; s5 = right
	andi	s4,$ffff		; s4 = left
	srl	s7,s6,16		; s7 = bottom
	andi	s6,$ffff		; s6 = top

	slt	at,s1,s4
	bnez	at,@exit
	slt	at,s0,v0
	beqz	at,@exit
	slt	at,s3,s6
	bnez	at,@exit
	slt	at,s2,s7
	beqz	at,@exit

	lui	a2,DCACHE>>16		; a2 = vertex cache
	sll	s4,16
	sll	v0,16
	sll	s6,16
	sll	s7,16
	ctc2	s4,CLIPL
	ctc2	v0,CLIPR
	ctc2	s6,CLIPT
	ctc2	s7,CLIPB

;--------------------------------------
; Transform And Apply Dynamic Lights
;--------------------------------------

	la	fp,YOffsets		; Wibble offsets - for subdiv.

	lui	s0,LightOffsetTab>>16	; s0 = lighting offset table
	ori	s0,LightOffsetTab&$ffff
	lui	s1,LightTab>>16		; s1 = lighting table
	ori	s1,LightTab&$ffff
	cfc2	s2,ROOMX		; s2 = room x
	cfc2	s3,ROOMY		; s3 = room y
	cfc2	s4,ROOMZ		; s4 = room z
	ori	s5,OurSqrt&$ffff

	lh	v0,mhVertices(a0)
	addi	a0,mhSIZEOF		; a0 = packed vertices
	ctc2	a0,VERTS
	ctc2	v0,TEMP1
	ctc2	a1,TEMP2
	andi	v0,$ff   		; Number of verts.

; -------- unpack a vertex

@vloop	lw	t0,0(a0)		; read packed vertex
	addi	a0,4
	srl	t3,t0,15		; get RGB in t3
	andi	t2,t0,ZMASK
	sll	t2,10
	andi	t1,t0,YMASK
	sll	t1,3

	srl	t9,t0,30		; Get vertex flags -	01 - Shimmer/underwater gourrad
					;     			10 - Wibble surface
;
; Wibble water vertices.
;
	ctc2	zero,TEMP4	; 'Apply wibble after lighting' flag.

	beqz	t9,@nowater
	andi	t0,XMASK

	add	t6,t0,s2
	srl	t6,6
	add	t7,t1,s3
	srl	t7,6
	add	t8,t2,s4
	srl	t8,7

	add	t6,t7
	add	t6,t8

	cfc2	t7,WIBBLE	; Get water offset.
	mfc2	t8,WIBTAB	; Get water table address.
	andi	t6,$fc
	add	t6,t8

	lh	t6,wtRandom(t6)
	andi	t5,t9,1		; Get gourrad wibble flag.
	srl	at,t6,8
	add	t6,t7
	andi	t6,$fc
	add	t6,t8
	lb	t8,wtShimmer(t6)
	lb	t6,wtChoppy(t6)

	beqz	t5,@nogour	; No Gourrad wibble ?
	andi	t9,2		; Get ripple flag.

	bnez	t9,@watersurface	; If rippling then don't brighten gourrad value.
	nop

	add	t8,at		; For shimmering edges.

@watersurface
	ctc2	t8,TEMP4

@nogour
	beqz	t9,@nowater	; Ripple surface ?

	sw	t6,0(fp)	; Store wibble y offset for subdiv.
	add	t1,t6

@nowater:
	sll	t4,t1,16		; write unpacked vertex
	or	t4,t0
	mtc2	t4,C2_VXY0
	mtc2	t2,C2_VZ0
	add	t0,s2			; add room translation
	GTE_RTPS

	add	t1,s3
	add	t2,s4
	srl	t5,t3,10		; t5 = b
	srl	t4,t3,5			; t4 = g
	andi	t5,31
	andi	t4,31
	andi	t3,31			; t3 = r

; -------- apply all lights

	lui	s6,LIGHTS>>16
	ori	s6,LIGHTS&$ffff

	sra	t0,7
	sra	t1,7

@lloop:
	lw	s7,liFalloff(s6)	; read falloff & rgb
	sra	t9,t2,7
	beqz	s7,@applywibble		; 0 = end of list
	srl	a3,s7,8			; a3 = light r

@lloop1:

; -------- calculate distance to light

	lw	t6,liXPos(s6)	; X
	lw	t7,liYPos(s6)	; Y
	lw	t8,liZPos(s6)	; Z

	sub     t6,t0	; X diff
	sub     t7,t1	; Y diff
	sub     t8,t9	; Z diff

	mtc2	t6,C2_IR1
	mtc2	t7,C2_IR2
	mtc2	t8,C2_IR3
	andi	a3,$1f
	GTE_SQR0			; * Square0 (5) *

	srl	v1,s7,16		; v1 = light g
	andi	v1,$1f
	srl	a1,s7,24		; a1 = light b
	andi	a1,$1f
	addi	s6,LIGHT_INFO

	mfc2	t6,C2_MAC1
	mfc2	t7,C2_MAC2
	mfc2	t8,C2_MAC3
	add	t6,t7
	add	t6,t8

	slt	at,t6,1023
	beqz	at,@lloop

	add	t6,s5
	lb	t6,0(t6)
	andi	s7,$ff			; s7 = falloff
	slt	at,t6,s7		; within falloff ?
	beqz	at,@lloop

; -------- light vertex

	sll	s7,1			; get offset into light table via falloff
	add	s7,s0
	lh	s7,0(s7)
	sll	t6,5
	add	t6,s7
	add	t6,s1			; t6 = &lighttable[falloff][dist][0]

	add	a3,t6			; get red
	add	v1,t6			; get green
	add	a1,t6			; get blue
	lb	a3,0(a3)
	lb	v1,0(v1)
	lb	a1,0(a1)

	add	t4,v1
	add	t5,a1

@lnext:
	j	@lloop
	add	t3,a3			; apply lights

;*******************************
;* Apply water effect, if any. *
;*******************************

@applywibble:
	cfc2	t0,TEMP4	; Apply any wibble ?
	add	fp,4
	beqz	t0,@depthq

      	add	t3,t0
	add	t4,t0
	add	t5,t0

;**************
;* Depth cue. *
;**************

@depthq:
	mfc2	t0,C2_SZ3
	move	v1,zero

	subi	t6,t0,12288	;
	bltz	t6,@off         ; Depth cue over 8 blocks.
	slt	at,t6,8191	;

	beqz	at,@black	; Too far away?
	srl	t6,8

	sub	t3,t6
	sub	t4,t6
	sub	t5,t6

@off:
	sltiu	at,t3,32
	bnez	at,@rok_1
	sltiu	at,t4,32
	srl	t3,27
	xori	t3,31
@rok_1:
	bnez	at,@gok_1
	sltiu	at,t5,32
	srl	t4,27
	xori	t4,31

@gok_1:
	bnez	at,@bok_1
	sll	t4,5
	srl	t5,27
	xori	t5,31
@bok_1:
	sll	t5,10
	or	t3,t4
	or	v1,t3,t5

@black:
	swc2	C2_SXY2,0(a2)
	sll	v1,16
	or	t0,v1
	sw	t0,4(a2)

	subi	v0,1
	bnez	v0,@vloop
	addi	a2,8

;--------------------------------------
; draw triangles
;--------------------------------------

	cfc2	a1,TEMP2		; a1 = Env
	cfc2	v0,TEMP1		; read # vertices & # triangles
	lui	a2,RoomTextInfo>>16
	lw	a2,RoomTextInfo&$ffff(a2)
	lw	a3,dbPrimPtr(a1)	; a3 = POLY_GT4 ptr
	lw	s0,dbOT(a1)		; s0 = OT
	lui	s1,DCACHE>>16		; s1 = vertex cache
	lui	s2,$00f8		; s2 = RGB mask
	addiu	s0,8			; OT fucker
	srl	v0,8			; v0 = # triangles
	andi	v0,$ff

@triloop:
	beqz	v0,@quad
	subi	v0,1
	lw	t0,0(a0)		; read face
	move	s7,zero			; s7 = mipmap offset

	ctc2	t0,FACE			; save for sub-division

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

;##	srl	s6,t0,13		; calc vertex pointers
	srl	s6,t0,11		; calc vertex pointers
	andi	s6,$3f8
	add	s6,s1
;##	srl	s5,t0,5
	srl	s5,t0,4
	andi	s5,$3f8
	add	s5,s1
	sll	s4,t0,3
	andi	s4,$3f8
	add	s4,s1
	lw	t1,0(s4)		; load first three vertices into GTE
	lw	t2,0(s5)
	lw	t3,0(s6)
	mtc2	t1,C2_SXY0
	mtc2	t2,C2_SXY1
	mtc2	t3,C2_SXY2
;##	andi	gp,t0,$80		; gp = double-sided flag
	srl	gp,t0,31		; gp = double-sided flag
	ctc2	gp,DS_FLAG		; Store double-sided flag for subdiv purposes.
;##	srl	t0,24			; t0 = texture #
	srl	t0,21			; t0 = texture #
	GTE_NCLIP			; NormalClip (8)

	andi	t0,$3ff		;##
	jal	ClipXY			; clip poly to screen
	move	t4,t3
	bnez	t5,@tnext		; NE = poly clipped

	lw	s4,4(s4)		; fetch vertex z & rgb components
	lw	s5,4(s5)
	lw	s6,4(s6)

	or	t5,s4,s5
	or	t5,s6
	andi	t5,$ffe0
	beqz	t5,@tnext		; EQ = poly is off the near plane
	andi	t5,s4,$ffff

; -------- far z-sort

	andi	t6,s5,$ffff
	slt	at,t5,t6
	beqz	at,@tz1
	andi	t7,s6,$ffff
	move	t5,t6
@tz1	slt	at,t5,t7
	beqz	at,@tz2
	srl	t5,3
	srl	t5,t7,3

@tz2
	slt	at,t5,OTSIZE
	bnez	at,@tnotout		; NE = outside OT range
	slt	at,t5,SUBDIV1

	lui	t5,$2000
@tnotout
	mfc2	t7,C2_MAC0		; fetch Cross Product
	bnez	at,@ttxt		; NE = subdivision required
	sll	t9,t5,2			; t9 = OT

; -------- normal clip

	bnez	gp,@tmip		; NE = poly is double-sided
	sltiu	t5,t9,MIPMAP1
	bltz	t7,@tnext		; <0 = facing towards screen
	nop
@tmip	bnez	t5,@ttxt		; calculate mipmap #
	sltiu	t5,t9,MIPMAP2
	bnez	t5,@ttxt
	ori	s7,zero,16
	ori	s7,zero,32

; -------- load texture info & convert RGBs to CVECTORs

@ttxt	ctc2	t7,BFACE

	sll	t0,4			; calc MMTEXTINFO index
	move	t7,t0
	sll	t0,1
	add	t0,t7
	add	t0,s7			; + mipmap

	bgtz	t9,@tinot
	add	t0,a2			; + MMTEXTINFO org

@tflat
	lw	t8,tiU2(t0)		; uv3 & primitive ids
	lw	t5,tiU0(t0)		; uv0 & clut
	sll	at,t8,6
	bltz	at,@tnext		; transparent ?
	lui	fp,$2400

	lw	t6,tiU1(t0)		; uv1 & tpage
	sw	fp,ftRGB0(a3)
	sw	t1,ftX0(a3)
	sw	t5,ftU0(a3)
	sw	t2,ftX1(a3)
	sw	t6,ftU1(a3)
	sw	t3,ftX2(a3)
	sw	t8,ftU2(a3)

	ori	t9,zero,((OTSIZE)-1)<<2
	ori	t2,zero,SIZEOF_FT3
	jal	MyAddPrim
	lui	t1,FT3_LEN<<8

	j	@triloop
	addi	a0,4

@tinot
	lw	t7,tiU2(t0)		; uv3 & primitive ids
	jal	UnpackRGB		; unpack rgbs
	sll	t8,t7,8

	lw	t5,tiU0(t0)		; uv0 & clut
	lw	t6,tiU1(t0)		; uv1 & tpage
	cfc2	t0,WATER

; -------- initialise primitive

	sw	fp,gtRGB0(a3)
	subu	t5,t0
	sw	t1,gtX0(a3)
	sw	t5,gtU0(a3)
	sw	gp,gtRGB1(a3)
	sw	t2,gtX1(a3)
	sw	t6,gtU1(a3)
	sw	s3,gtRGB2(a3)
	sw	t3,gtX2(a3)
	beqz	at,@taddp		; EQ = no subdivision required
	sw	t7,gtU2(a3)

;****  Subdivide TRIANGLE. ****

	ctc2	t9,TEMP1		; save OT
	ctc2	a3,TEMP2		; save prim ptr
	jal	InitSubdivision
	addi	a3,SIZEOF_GT3

	move	s3,zero		; 16 loop flag.

	la	t0,TriVertTable
	jal	SubPolyGT3
	addi	t1,s1,spV3

	cfc2	t0,BFACE
	sll	fp,6

	bltz	fp,@tnext
	move	t3,a3

	bltz	t0,@tnext
	nop

	cfc2	t9,TEMP1		; restore OT
	cfc2	a3,TEMP2		; restore prim ptr
	jal	MyAddPrim
	lui	t1,GT3_LEN<<8

	move	a3,t3
	j	@triloop
	addi	a0,4

; -------- AddPrim

@taddp
	ori	t2,zero,SIZEOF_GT3
	jal	MyAddPrim
	lui	t1,GT3_LEN<<8
@tnext:
	j	@triloop
	addi	a0,4

;--------------------------------------
; draw quads
;--------------------------------------

; a2 = MMTEXTINFO array
; a3 = POLY_GT4 ptr
; s0 = OT
; s1 = vertex cache
; s2 = rgb mask

@quad	lw	v0,0(a0)		; read 3 textures
	addi	a0,4
	ori	v1,zero,2
@qloop:
	andi	t0,v0,$3ff		; t0 = current texture
	xori	at,t0,$3ff		; last face ?
	beqz	at,@end
	srl	v0,10

	lw	t1,0(a0)		; t1 = face
	addi	a0,4
	ctc2	t1,FACE			; save for sub-division
;##	andi	gp,t1,$80		; gp = double-sided flag
	srl	gp,t1,31		; gp = double-sided flag

	ctc2	gp,DS_FLAG		; Store double-sided flag for subdiv purposes.

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

;##	srl	t4,t1,21		; calc vertex pointers
	srl	t4,t1,18		; calc vertex pointers
;##	srl	t3,t1,13
	srl	t3,t1,11
	andi	t3,$3f8
	add	s6,t3,s1
;##	srl	t2,t1,5
	srl	t2,t1,4
	andi	t2,$3f8
	add	s5,t2,s1
	sll	t1,3
	andi	t1,$3f8
	add	s4,t1,s1
	lw	t1,0(s4)		; load first three vertices into GTE
	lw	t2,0(s5)
	lw	t3,0(s6)
	mtc2	t1,C2_SXY0
	mtc2	t2,C2_SXY1
	mtc2	t3,C2_SXY2
	andi	t4,$3f8
	add	s7,t4,s1
	GTE_NCLIP			; NormalClip (8)

	jal	ClipXY			; clip poly to screen
	lw	t4,0(s7)
	bnez	t5,@next		; NE = poly clipped

	lw	s4,4(s4)		; fetch vertex z & rgb components
	lw	s5,4(s5)
	lw	s6,4(s6)
	lw	s7,4(s7)

	or	t5,s4,s5
	or	t5,s6
	or	t5,s7
	andi	t5,$ffe0
	beqz	t5,@next		; EQ = poly is off the near plane
	andi	t5,s4,$ffff

; -------- far z-sort

	andi	t6,s5,$ffff
	slt	at,t5,t6
	beqz	at,@qz1
	andi	t7,s6,$ffff
	move	t5,t6
@qz1	slt	at,t5,t7
	beqz	at,@qz2
	andi	t8,s7,$ffff
	move	t5,t7
@qz2	slt	at,t5,t8
	beqz	at,@qz3
	move	t6,zero
	move	t5,t8
@qz3
	mfc2	t7,C2_MAC0		; fetch Cross Product
	cfc2	t9,FACE
	srl	t5,3

	srl	t9,28
	andi	t9,4
	add	t5,t9			; Push flat floor further back.

	slt	at,t5,OTSIZE
	bnez	at,@qnotout		; outside OT range?
	slt	at,t5,SUBDIV1

	lui	t5,$2000

@qnotout
	bnez	at,@qtxt		; NE = subdivision required
	sll	t9,t5,2			; t9 = OT

; -------- normal clip

	bnez	gp,@qmip		; NE = poly is double-sided
	sltiu	t5,t9,MIPMAP1
	bltz	t7,@next		; <0 = facing towards screen
	nop
@qmip	bnez	t5,@qtxt		; calculate mipmap #
	sltiu	t5,t9,MIPMAP2
	bnez	t5,@qtxt
	ori	t6,zero,16
	ori	t6,zero,32

; -------- load texture info & convert RGBs to CVECTORs

@qtxt
	ctc2	t7,BFACE

	sll	t0,4			; calc MMTEXTINFO index
	move	t7,t0
	sll	t0,1
	add	t0,t7
	add	t0,t6			; + mipmap

	bgtz	t9,@qinot
	add	t0,a2			; + MMTEXTINFO org

@qflat
	lw	t8,tiU2(t0)		; uv3 & primitive ids
	lw	t5,tiU0(t0)		; uv0 & clut
	sll	at,t8,6
	bltz	at,@next		; transparent ?
	lui	fp,$2c00

	lw	t6,tiU1(t0)		; uv1 & tpage
	lw	t0,tiU3(t0)		; uv2

	sw	fp,ftRGB0(a3)

	sw	t1,ftX0(a3)
	sw	t5,ftU0(a3)
	sw	t2,ftX1(a3)
	sw	t6,ftU1(a3)
	sw	t3,ftX2(a3)
	sw	t8,ftU2(a3)
	sw	t4,ftX3(a3)
	sw	t0,ftU3(a3)

	ori	t9,zero,((OTSIZE)-1)<<2
	ori	t2,zero,SIZEOF_FT4
	jal	MyAddPrim
	lui	t1,FT4_LEN<<8

	j	@next
	nop
@qinot
	jal	UnpackRGB		; unpack first 3 rgbs
	lw	t8,tiU2(t0)		; uv3 & primitive ids

	srl	t5,s7,7			; unpack 4th rgb
	and	t5,s2
	srl	t6,s7,10
	andi	t6,$f800
	srl	t7,s7,13
	andi	t7,$f8
	or	t7,t5
	or	t7,t6

	lw	t5,tiU0(t0)		; uv0 & clut
	cfc2	a1,WATER
	lw	t6,tiU1(t0)		; uv1 & tpage
	subu	t5,a1
	lw	t0,tiU3(t0)		; uv2

; -------- initialise primitive

	sw	fp,gtRGB0(a3)
	sw	t1,gtX0(a3)
	sw	t5,gtU0(a3)
	sw	gp,gtRGB1(a3)
	sw	t2,gtX1(a3)
	sw	t6,gtU1(a3)
	sw	s3,gtRGB2(a3)
	sw	t3,gtX2(a3)
	sw	t8,gtU2(a3)
	sw	t7,gtRGB3(a3)
	sw	t4,gtX3(a3)
	beqz	at,@qaddp		; EQ = no subdivision required
	sw	t0,gtU3(a3)

; -------- sub-divide QUAD

	ctc2	t9,TEMP1		; save OT
	ctc2	a3,TEMP2		; save prim ptr
	addi	a3,SIZEOF_GT4

	sw	t4,spV3+vSX(s1)		; initialise vertex #3
	sh	s7,spV3+vSZ(s1)
	sw	t7,spV3+vRGB(s1)
	sh	t0,spV3+vU(s1)

	jal	InitSubdivision
	move	t7,t8

	cfc2	t0,FACE			; fetch original vertices
	cfc2	t5,VERTS

;##	srl	t3,t0,22
	srl	t3,t0,19
  	andi	t3,$1fc
	add	s6,gp,t3	; Y Offsets.
	add	t3,t5

	lw	t3,0(t3)
	move	s3,zero		; 16 loop flag.

	andi	t4,t3,YMASK
	sll	t4,3
	bgtz	t3,@noyadd4		; Water room ?
	andi	t5,t3,ZMASK		; unpack vertex #0

	lw	t6,0(s6)
	nop
	add	t4,t6
@noyadd4:
	sll	t5,10
	andi	t3,XMASK
	sh	t3,spV3+vX(s1)
	sh	t4,spV3+vY(s1)
	sh	t5,spV3+vZ(s1)

	la	t0,QuadVertTable
	jal	SubPolyGT4
	addi	t1,s1,spV4

	cfc2	t0,BFACE
	sll	fp,6

	bltz	fp,@next
	move	t3,a3

	bltz	t0,@next
	nop
	cfc2	t9,TEMP1		; restore OT
	cfc2	a3,TEMP2		; restore prim ptr
	jal	MyAddPrim
	lui	t1,GT4_LEN<<8
	j	@next
	move	a3,t3

; -------- AddPrim

@qaddp
	ori	t2,zero,SIZEOF_GT4
	jal	MyAddPrim
	lui	t1,GT4_LEN<<8

@next:
	bnez	v1,@qloop
	subi	v1,1
	j	@quad
	nop
@end:
	lw	a1,rega1(sp)
	nop
	sw	a3,dbPrimPtr(a1)
@exit:
	lw	ra,regra(sp)
	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)
	lw	gp,reggp(sp)
	jr	ra
	addi	sp,STACKFRAME

DummyTwat2:
	jr	ra
	nop

