;****************************************************************************
;
; DRAWSKY.MIP
;
;****************************************************************************

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

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

DCACHE	equ	$1f800000
OTSIZE	equ	2562

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

; -------- 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
STACKFRAME	rb	0

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

	XREF	db
	XREF	phd_top
	XREF	phd_bottom
	XREF	phd_left
	XREF	phd_right
	XREF	psxtextinfo
	XREF	horizon_colour
	XREF	HorizonClip

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

	XDEF	DrawSkyMesh

;----------------------------------------------------------------------------
;DrawSkyMesh
;
;Purpose:	Draws the horizon mesh
;
;Inputs:	a0 = mesh ptr
;
;Outputs:	None
;
;Usage:		a0-a3/t0-t9/v0-v1
;
;----------------------------------------------------------------------------

DrawSkyMesh:
	subi	sp,STACKFRAME
	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)

	lw	v1,0(a0)		; read header
	addi	a0,4			; a0 = vertex ptr
	andi	v0,v1,$ffff		; v0 = # vertices
	sll	a1,v0,3			; a1 = face ptr
	add	a1,a0

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

	lui	a2,DCACHE>>16		; a2 = vertex buffer
	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)
@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)

	swc2	C2_SXY0,0(a2)		; store transformed vertices
	swc2	C2_SXY1,4(a2)
	swc2	C2_SXY2,8(a2)

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

;--------------------------------------
; Draw Faces
;--------------------------------------

	lui	a0,DCACHE>>16		; a0 = vertex buffer
	GPR.lw	a3,db+dbOT		; a3 = OT
	GPR.lw	a2,db+dbPrimPtr		; a2 = primitive buffer
	addi	a3,(OTSIZE+1)*4
	GPR.lw	s0,phd_top		; s0-s3 = clip window
	GPR.lw	s1,phd_bottom
	GPR.lw	s2,phd_left
	GPR.lw	s3,phd_right
	sll	s0,16
	sll	s1,16
	sll	s2,16
	sll	s3,16
	GPR.lw	s4,psxtextinfo		; s4 = TEXTINFO structures
	lui	s5,$2c86 		; s5 = primtive ID & RGB
	ori	s5,$8686
	lui	s6,FT4_LEN<<8		; s6 = primitive size
	lui	t9,-1000		; t9 = lowest upper poly pos
	lui	s7,-1000		; s7 = lowest poly pos

	srl	v0,v1,16		; v0 = # faces
@tloop:
	lw	v1,0(a1)		; read 2 textures
@floop:
	lw	t1,4(a1)		; t1 = face
	andi	t0,v1,$ffff		; t0 = current texture

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

	srl	t4,t1,22		; calc vertex pointers
	srl	t3,t1,14
	andi	t3,$3fc
	add	t3,a0
	srl	t2,t1,6
	andi	t2,$3fc
	add	t2,a0
	sll	t1,2
	andi	t1,$3fc
	add	t1,a0
	lw	t1,0(t1)		; load first three vertices into GTE
	lw	t2,0(t2)
	lw	t3,0(t3)
	mtc2	t1,C2_SXY0
	mtc2	t2,C2_SXY1
	mtc2	t3,C2_SXY2
	andi	t4,$3fc
	add	t4,a0
	NCLIP			; NormalClip (8)

	lw	t4,0(t4)		; fetch 4th veretx

; -------- clip poly to screen

	slt	at,t1,s0		; top clip
	beqz	at,@bclip
	sll	t5,t1,16
	slt	at,t2,s0
	beqz	at,@bclip
	slt	at,t3,s0
	beqz	at,@bclip
	slt	at,t4,s0
	bnez	at,@next
@bclip:
	slt	at,t1,s1		; bottom clip
	bnez	at,@lclip
	sll	t6,t2,16
	slt	at,t2,s1
	bnez	at,@lclip
	slt	at,t3,s1
	bnez	at,@lclip
	slt	at,t4,s1
	beqz	at,@next
@lclip:
	sll	t7,t3,16
	slt	at,t5,s2		; left clip
	beqz	at,@rclip
	sll	t8,t4,16
	slt	at,t6,s2
	beqz	at,@rclip
	slt	at,t7,s2
	beqz	at,@rclip
	slt	at,t8,s2
	bnez	at,@next
@rclip:
	slt	at,t5,s3		; right clip
	bnez	at,@ok
	slt	at,t6,s3
	bnez	at,@ok
	slt	at,t7,s3
	bnez	at,@ok
	slt	at,t8,s3
	beqz	at,@next
@ok:
	sll	t0,4			; t0 = TEXTINFO ptr
	mfc2	at,C2_MAC0		; fetch Cross Product
	add	t0,s4
	bltz	at,@next

; -------- construct primitive

	lw	t5,0(t0)		; fetch UV0 & Clut
	lw	t6,4(t0)		; fetch UV1 & Tpage
	lw	t7,8(t0)		; fetch UV2
	lw	t8,12(t0)		; fetch UV3

	sw	s5,ftRGB0(a2)
	sw	t1,ftX0(a2)
	sw	t5,ftU0(a2)
	sw	t2,ftX1(a2)
	sw	t6,ftU1(a2)
	sw	t3,ftX2(a2)
	sw	t7,ftU2(a2)
	sw	t4,ftX3(a2)
	sw	t8,ftU3(a2)

; -------- update lowest poly pos

	slt	at,t3,s7
	bnez	at,@bot1
	slt	at,t4,s7
	move	s7,t3
@bot1	bnez	at,@bot2
	slt	at,t1,t9
	move	s7,t4
@bot2
	bnez	at,@y2
	lw	t0,0(a3)
	move	t9,t1
@y2	slt	at,t2,t9
	bnez	at,@addp
	sw	a2,0(a3)
	move	t9,t2

; -------- AddPrim

@addp	or	t0,s6
	sw	t0,0(a2)
	addi	a2,SIZEOF_FT4
@next:
	subi	v0,1
	beqz	v0,@fill
	srl	v1,16
	bnez	v1,@floop
	addi	a1,4
	j	@tloop
	addi	a1,4

;--------------------------------------
; Draw Ceiling
;--------------------------------------

@fill	slt	at,t9,s1
	bnez	at,@yok
	lui	t0,$ffff
	move	t9,s1
@yok	bltz	t9,@end
	and	t9,t0

	srl	t0,s2,16
	or	t0,s0
	srl	t1,s3,16
	or	t1,s0
	srl	t2,s2,16
	or	t2,t9
	srl	t3,s3,16
	GPR.lw	t4,horizon_colour
	or	t3,t9

	sw	t4,fRGB0(a2)		; initialise primitive
	sw	t0,fX0(a2)
	sw	t1,fX1(a2)
	sw	t2,fX2(a2)
	sw	t3,fX3(a2)

	lw	t0,0(a3)		; AddPrim
	sw	a2,0(a3)
	lui	t1,F4_LEN<<8
	or	t0,t1
	sw	t0,0(a2)
	addi	a2,SIZEOF_F4
@end:
	GPR.sw	a2,db+dbPrimPtr		; a2 = primitive buffer
	sra	s7,16
	GPR.sh	s7,HorizonClip
	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)
	jr	ra
	addi	sp,STACKFRAME

