;****************************************************************************
;
; DrawRooms
;
;****************************************************************************

	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
MAX_DYNAMICS	equ	32

ROOMX	equr	C2_RBK
ROOMY	equr	C2_GBK
ROOMZ	equr	C2_BBK

WIBBLE	equr	C2_LB3
WIBTAB	equr	C2_RGB0		; mtc2

WATER	equr	C2_RFC

HORIZON	equr	C2_L33

UNDERWATER	equ	1
SWAMP		equ	128
MIST		equ	256

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

; -------- local scratchpad usage

		rsreset
spregs0		rw	1
spregs1		rw	1
spregs2		rw	1
spregs3		rw	1
spregs4		rw	1
spregs5		rw	1
spregs6		rw	1
spregs7		rw	1
spregra		rw	1
spregfp		rw	1
spreggp		rw	1
STACK_SIZE	rb	0

		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_MATRIX	rb	0

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

		rsreset
dynX		rw	1
dynY		rw	1
dynZ		rw	1

dynFalloff	rh	1
dynUsed		rb	1
dynPad1		rb	1

dynOn		rb	1
dynR		rb	1
dynG		rb	1
dynB		rb	1

SIZEOF_DYNAMICS	rb	0

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

	XREF	room			; ROOM room[]
	XREF	Matrix			; MATRIX3D *Matrix
	XREF	CamPos			; VECTOR3D CamPos
	XREF	draw_rooms		; WORD draw_rooms[]
	XREF	number_draw_rooms       ; long number_draw_rooms
	XREF	dynamics
	XREF	WaterTable		; For water surface, water wibble
	XREF	wibble			; LONG wibble

	XREF	db
	XREF	RoomBBoxes

	XREF	DrawMesh2
	XREF	HorizonClip		; WORD HorizonClip


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

	XDEF	DrawRoomletListAsm

;**************************************************
; Draw the roomlets associated with draw_rooms[]. *
;**************************************************

DrawRoomletListAsm:
	subi	sp,STACK_SIZE
	sw	s0,spregs0(sp)
	sw	s1,spregs1(sp)
	sw	s2,spregs2(sp) 	;
	sw	s3,spregs3(sp)	; Stack s0 - s7
	sw	s4,spregs4(sp)	;
	sw	s5,spregs5(sp)
	sw	s6,spregs6(sp)
	sw	s7,spregs7(sp)
	sw	ra,spregra(sp)
	sw	fp,spregfp(sp)
	sw	gp,spreggp(sp)

	ctc2	a0,WATER

; -------- load current matrix onto GTE

	GPR.lw	s7,Matrix
	GPR.lw	s0,number_draw_rooms	; s0 = number of rooms.
;	lw	t1,m00(s7)
;	lw	t2,m02(s7)
;	lw	t3,m11(s7)
;	lw	t4,m20(s7)
;	lw	t5,m22(s7)
;	ctc2	t1,C2_R11R12
;	ctc2	t2,C2_R13R21
;	ctc2	t3,C2_R22R23
;	ctc2	t4,C2_R31R32
;	ctc2	t5,C2_R33

; -------- initialise constants

	GPR.lh	at,HorizonClip
	GPR.lw	s3,RoomBBoxes		; s3 = mesh bounding boxes
	GPla	s4,draw_rooms
	ctc2	at,HORIZON
@roomloop:
	lh	t0,0(s4)
	addi	s4,2

	sll	t0,4			; fp = current room ptr
	sll	at,t0,2
	GPR.lw	t1,room
	add	t0,at
	add	fp,t0,t1

;
; Get correct wibble table for type of room.
;
	lbu	t0,riMeshEffect(fp)

	lui	t1,WaterTable>>16
	ori	t1,WaterTable&$ffff

	GPR.lw	t2,wibble

	sll	t0,8
	add	t1,t0

        andi	t2,0xfc

	ctc2	t2,WIBBLE		; Water effect offset.
	mtc2	t1,WIBTAB		; Water effect table.

	lw	s1,riData(fp)	; Pointer to roomlet count.

	lw	t0,riX(fp)
  	lw	t1,riY(fp)
	lw	t2,riZ(fp)

	ctc2	t0,ROOMX	;
	ctc2	t1,ROOMY	; Stash room X Y Z on gte regs.
	ctc2	t2,ROOMZ	;

; -------- mTranslateXYZ

	bgez    t0,@posx
	sra     t3,t0,15
	subu    t0,zero,t0
	sra     t3,t0,15
	andi    t0,$7fff
	subu    t3,zero,t3
	j	@y
	subu    t0,zero,t0
@posx	andi    t0,$7fff

@y	bgez    t1,@posy
	sra     t4,t1,15
	subu    t1,zero,t1
	sra     t4,t1,15
	andi    t1,$7fff
	subu    t4,zero,t4
	j	@z
	subu    t1,zero,t1
@posy	andi    t1,t1,$7fff

@z	bgez    t2,@posz
	sra     t5,t2,15
	subu    t2,zero,t2
	sra     t5,t2,15
	andi    t2,t2,$7fff
	subu    t5,zero,t5
	j	@doit
	subu    t2,zero,t2
@posz	andi    t2,t2,$7fff

@doit	mtc2    t3,C2_IR1
	mtc2    t4,C2_IR2
	mtc2    t5,C2_IR3
	nop
	MVMVA	0,0,3,3,0		; [rt] * [ir]

	lw	t3,mx(s7)		; add current translation
	lw	t4,my(s7)
	lw	t5,mz(s7)
	ctc2	t3,C2_TRX
	ctc2	t4,C2_TRY
	ctc2	t5,C2_TRZ

	mfc2    t3,C2_MAC1
	mfc2    t4,C2_MAC2
	mtc2    t0,C2_IR1
	mtc2    t1,C2_IR2
	mtc2    t2,C2_IR3
	mfc2    t5,C2_MAC3

	MVMVA	1,0,3,0,0		; ([rt] * [ir]) >> 12) + [tr]

	bgez    t3,@lab8
	sll     t0,t3,3
	subu    t3,zero,t3
	sll     t3,3
	subu    t0,zero,t3
@lab8
	bgez    t4,@lab9
	sll     t1,t4,3
	subu    t4,zero,t4
	sll     t4,3
	subu    t1,zero,t4
@lab9
	bgez    t5,@lab10
	sll     t2,t5,3
	subu    t5,zero,t5
	sll     t5,3
	subu    t2,zero,t5
@lab10
	mfc2	t3,C2_MAC1
	mfc2	t4,C2_MAC2
	mfc2	t5,C2_MAC3
	addu	t0,t3
	addu	t1,t4
	addu	t2,t5

	ctc2	t0,C2_TRX		; load compound translation onto GTE
	ctc2	t1,C2_TRY
	ctc2	t2,C2_TRZ

	lw	s6,0(s1)	; Get roomlet start & count.
	add	s1,4

@roomletloop:
	beqz	s6,@roomletend

	lw	a0,0(s1)	; Get mesh ptr.
	add	s1,4

	lw	t5,0(a0)	; Get min and max ptrs.
	move	s5,a0

	sll	t0,t5,3
	andi	t0,$fff8
	add	t0,s3
	lh	t2,4(t0)		; t2 = minz
	lw	t0,0(t0)		; t0 = minx, miny

	srl	t5,13
	andi	t5,$fff8
	add	t5,s3
	lw	t3,0(t5)		; t3 = maxx, maxy
	lh	t5,4(t5)		; t5 = maxz

	srl	t1,t0,16		; t1 = miny
	andi	t0,$ffff		; t0 = minx
	srl	t4,t3,16		; t4 = maxy
	andi	t3,$ffff		; t3 = maxx

	cfc2	t7,ROOMX
	cfc2	t8,ROOMY
	cfc2	t9,ROOMZ
	add	t0,t7
	add	t1,t8
	add	t2,t9   	;
	add	t3,t7           ; Add room X Y & Z to bounding boxes.
	add	t4,t8           ;
	add	t5,t9

;
; Check dynamic lights.
;

	move	t6,zero
	ori	t7,zero,1	; set value.
	lui	t8,DCACHE>>16	; lightlist
	move	t9,zero

	GPla	a0,dynamics
	addi	at,a0,SIZEOF_DYNAMICS*MAX_DYNAMICS

	ori	a3,zero,MAX_DYNAMICS
@set0loop:
	sb	zero,dynOn(at)
	subi	a3,1
	bnez	a3,@set0loop
	add	at,SIZEOF_DYNAMICS

	ori	a3,zero,MAX_DYNAMICS
@dynloop:
	lb	at,dynOn(a0)
	nop

	beqz	at,@subnext	; Light on ?

	lh	a2,dynFalloff(a0)
	lw	v0,dynX(a0)
	srl	a2,1

	add	v1,v0,a2	; maxval
	sub	v0,a2		; minval

	slt	at,v1,t0
	bnez	at,@clear
	slt	at,v0,t3
	beqz	at,@clear

@checky:
	lw	v0,dynY(a0)
	nop

	add	v1,v0,a2	; maxval
	sub    	v0,a2		; minval

	slt	at,v1,t1
	bnez	at,@clear
	slt	at,v0,t4
	beqz	at,@clear

@checkz:
	lw	v0,dynZ(a0)
	nop

	add	v1,v0,a2	; maxval
	sub	v0,a2		; minval

	slt	at,v1,t2
	bnez	at,@clear
	slt	at,v0,t5
	beqz	at,@clear
	srl	a2,7

	sb	t7,dynUsed(a0)
	add	t9,a2		; Total up falloffs
	sw	a0,0(t8)	; Store address of this used light.
	addi	t8,4
	addi	t6,1

	j	@dynnext
	subi	a3,1

@clear:
	sb	zero,dynUsed(a0)

@subnext:
	subi	a3,1

@dynnext:
	bnez	a3,@dynloop
	addi	a0,SIZEOF_DYNAMICS

;--------------------------------------
; Mix lights into an acceptable amount.
;--------------------------------------

	GPla	t8,dynamics
	addi	t8,SIZEOF_DYNAMICS*MAX_DYNAMICS

@mixloop1:
	slti	at,t9,96     	; Total falloffs > 64 ?
	bnez	at,@setlights   ;

	lui	t7,$fff		; Maxval
	move	t2,zero         ;
	move	t3,zero		; Two closest lights.

	lui	a0,DCACHE>>16	; lightlist1
	move	t5,t6

@mixloop2:
	beqz	t5,@mixloop1
	lw	a2,0(a0)
	addi	a0,4

	beqz	a2,@mixloop2
	subi	t5,1

	move	a1,a0
	subi	t4,t5,1

@mixloop3:
	beqz	t4,@mixed
	lw	a3,0(a1)
	addi	a1,4

	beqz	a3,@mixloop3
	subi	t4,1

	lw	t0,dynX(a2)
	lw	at,dynX(a3)

	lw	t1,dynY(a2)
	sub	t0,at
	bgtz	t0,@absx
	lw	at,dynY(a3)
	sub	t0,zero,t0	; neg X diff
@absx:
	sltiu	s2,t0,$800	; 2 blocks or more away in X?
	beqz	s2,@mixloop3
	sub	t1,at
	lw	ra,dynZ(a2)
	bgtz	t1,@absy
	lw	at,dynZ(a3)
	sub	t1,zero,t1	; neg Y diff
@absy:
	sltiu	s2,t1,$800	; 2 blocks or more away in Y?
	beqz	s2,@mixloop3

	sub	ra,at
	bgtz	ra,@absz
	add	t0,t1
	sub	ra,zero,ra	; neg Z diff
@absz:
	sltiu	s2,ra,$800	; 2 blocks or more away in Z?
	beqz	s2,@mixloop3
	add	t0,ra
	slt	at,t0,t7	; less than current closest 2 ?
	beqz	at,@mixloop3
	nop

	move	t7,t0
	subi	v0,a0,4
	subi	v1,a1,4
	move	t2,a2
	j	@mixloop3
	move	t3,a3

@mixed:
	beqz	t3,@setlights

	lh	t0,dynFalloff(t2)	; t2 = dptr
	lh	t1,dynFalloff(t3)	; t3 = dptr2
	sw	zero,0(v1)

	slt	at,t0,t1
	bnez	at,@larger2
	sw	t8,0(v0)

@larger1:
	sh	t0,dynFalloff(t8)
	srl	t1,8
	j	@extra
	sub	t9,t1

@larger2:
	sh	t1,dynFalloff(t8)
	srl	t0,8
	sub	t9,t0

@extra:
	lw	t0,dynOn(t2)
	lw	t1,dynOn(t3)

	srl	v0,t0,8
	srl	v1,t1,8
	andi	v0,$1f
	andi	v1,$1f
	add	v0,v1
	srl	v0,1
	sll	t7,v0,8		; New red value

	srl	v0,t0,16
	srl	v1,t1,16
	andi	v0,$1f
	andi	v1,$1f
	add	v0,v1
	srl	v0,1
	sll	v0,16		; New green
	or	t7,v0

	srl	v0,t0,24
	srl	v1,t1,24
	add	v0,v1
	srl	v0,1
	sll	v0,24		; New blue value
	or	t7,v0
	ori	t7,1		; Set light on

	sw	t7,dynOn(t8)
	sb	t7,dynUsed(t8)

	lw	v0,dynX(t2)
	lw	v1,dynX(t3)
	lw	t0,dynY(t2)
	lw	t1,dynY(t3)
	add	v0,v1
	srl	v0,1	; Average X pos.
	add	t0,t1
	sra	t0,1	; Average Y pos.

	sw	v0,dynX(t8)	; Store new X.

	lw	v0,dynZ(t2)
	lw	v1,dynZ(t3)

	sw	t0,dynY(t8)  	; Store new Y.
	add	v0,v1
	srl	v0,1		; Average Z pos.
	sw	v0,dynZ(t8)	; Store new Z.

	sb	zero,dynUsed(t2)
	sb	zero,dynUsed(t3)

	j	@mixloop1
	addi	t8,SIZEOF_DYNAMICS



@setlights:
	GPla	a0,dynamics

	lui	a1,DCACHE>>16		; Store for light on scratch pad.
	addi	a1,768

	ori	v1,zero,15	; Max number of lights applicable to 1 mesh.
	ori	v0,zero,MAX_DYNAMICS*2

@setlightloop:
	lb	at,dynOn(a0)
	lb	t0,dynUsed(a0)	; Light used ?
	nop
	and	at,t0

	beqz	at,@nextlight	; Light on ?

	lw	t0,dynX(a0)
	lw	t1,dynY(a0)
	lw	t2,dynZ(a0)
	srl	t0,7
	sw	t0,0(a1)
	sra	t1,7
	sw	t1,4(a1)
	srl	t2,7
	sw	t2,8(a1)

	lw	t1,dynOn(a0)
	lh	t0,dynFalloff(a0)
	srl	t1,8
	sll	t1,8
	srl	t0,8
	or	t1,t0
	sw	t1,12(a1)
	addi	a1,16
	subi	v1,1    	; Ran out of light space on scratchpad?
	beqz	v1,@stop

@nextlight:
	subi	v0,1
	bnez	v0,@setlightloop
	addi	a0,SIZEOF_DYNAMICS
@stop:
	sw	zero,12(a1)	; Limiter for drawmesh2

	GPla	a1,db
	jal	DrawMesh2
	move	a0,s5

	j	@roomletloop
	subi	s6,1	; decrease roomlet count

@roomletend:

; Clear bound_active and clip values.

;##	ori	t0,zero,CLIPX
;##	ori	t1,zero,CLIPY
;##	sh	zero,riBoundActive(fp)
;##	sw	t0,riClipL(fp)
;##	sw	t1,riClipT(fp)

	subi	s0,1
	bnez	s0,@roomloop
	nop

@end:
	lw	s0,spregs0(sp)
	lw	s1,spregs1(sp)
	lw	s2,spregs2(sp)
	lw	s3,spregs3(sp)
	lw	s4,spregs4(sp)
	lw	s5,spregs5(sp)
	lw	s6,spregs6(sp)
	lw	ra,spregra(sp)
	lw	s7,spregs7(sp)
	lw	fp,spregfp(sp)
	lw	gp,spreggp(sp)
	jr	ra
	addi	sp,STACK_SIZE

