; 01/10/98
;
; Tomb III ASM... knocked up by Del...
;
;
; Basically contains the following routines...
;
; GetFloor
; GetDoor
; CheckNoColFloorTriangle
; CheckNoColCeilingTriangle
;
;
; Main advantages over C versions:
;
; Shorter (not so much icache pain for u)
; Less Memory Reads/Writes (faster)
; No stack useage (faster,sweeter,shorter)
;
;
; Greetings to... blah blah blah... :)




		opt		l.,c+,m-,at-
		section		.text
		xref		gp_start_address
GPBASE		equs		"gp_start_address"

gpr		macros
		\0	\1,\2-GPBASE(gp)

		xref	room
       		xref	number_rooms
		xref	floor_data

; external functions...
;     		xref	S_ExitSystem

; make my shit visible to C
     		global	GetFloor				;<< now in ASM!
		global	GetDoor					;<< now in ASM!
		global	CheckNoColFloorTriangle			;<< now in ASM!
		global	CheckNoColCeilingTriangle		;<< now in ASM!




	       		rsreset
ROOM_data      		rw	1		;0
ROOM_door      		rw	1		;4
ROOM_floor     		rw	1		;8
ROOM_light     		rw	1		;12
ROOM_mesh      		rw	1		;16
ROOM_x	       		rw	1		;20
ROOM_y	       		rw	1		;24
ROOM_z	       		rw	1		;28
ROOM_minfloor  		rw	1		;32
ROOM_maxceiling		rw	1		;36
ROOM_xsize     		rh	1		;40
ROOM_ysize     		rh	1		;42
ROOM_ambient   		rh	1		;44
ROOM_lighting  		rh	1		;46
ROOM_numlights 		rh	1		;48
ROOM_nummeshes 		rh	1		;50
ROOM_reverbtype		rh	1		;52
ROOM_mesheffect		rb	1		;54
ROOM_boundactive	rb	1		;55
ROOM_left		rh	1		;56
ROOM_right		rh	1		;58
ROOM_top		rh	1		;60
ROOM_bottom		rh	1		;62
ROOM_testleft		rh	1		;64
ROOM_testright		rh	1		;66
ROOM_testtop		rh	1		;68
ROOM_testbottom		rh	1		;70
ROOM_itemnumber		rh	1		;72
ROOM_fxnumber		rh	1		;74
ROOM_flippedroom	rh	1		;76
ROOM_flags		rh	1		;78
ROOM_size		rb	0		;80 bytes...


WALL_SHIFT		EQU	10


; GetFloor
;
; r4 = X
; r5 = Y
; r6 = Z
; r7 = room_number
;
; Now updated to not stack/unstack shitloads of crap, becuase i`m calling minimal ASM routines :)
;

GetFloor
	subu	sp,sp,20
	sw	r31,16(sp)			;stack r31

	move	r10,r4				;r10 = X
	move	r11,r5				;r11 = Y			(fill delay slot)
	move	r12,r6				;r12 = Z
	move	r13,r7				;r13 = room_number




	lh	r4,0(r13)			;r4 = *(room_number)
	gpr.lw	r2,room				;r2 = room
	sll	r3,r4,2				;r3 = *(room_number)<<2
	addu	r3,r3,r4			;r2 = *(room_number)*5
	sll	r3,r3,4				;r3 = *(room_number)*80

.doloop1
	addu	r15,r2,r3			;r15 = r = room+(*(room_number)*80)

;/* Clip position to edge of room (that way doorways are detected) */
	lw	r2,ROOM_z(r15)			;r2 = r->z
	lw	r3,ROOM_x(r15)			;r3 = r->x
	lh	r6,ROOM_xsize(r15)		;r6 = r->xsize
	lh	r7,ROOM_ysize(r15)		;r7 = r->ysize
; r6=xsize
; r7=ysize
	subu	r2,r12,r2			;r2 = (Z - r->z)
	sra	r5,r2,WALL_SHIFT  		;r5 = x_floor			((Z - r->z)>>10)
	subu	r3,r10,r3			;r3 = (X - r->x)
	bgtz	r5,.xfloor_positive   		;x_floor>0 ??
	sra	r3,r3,WALL_SHIFT  		;r3 = y_floor			((X - r->x)>>10)		(fill delay slot)
; r5=x_floor
; r3=y_floor

;	/* Gav 19/9/96: this more complex code is just to ensure we don't test
;	 * the corner of a room's floor data, as this can cause problems when 4
;	 * rooms join at a point */

;x_floor is <= 0
	blez	r3,.y_floor1 			;y_floor < 1 ??
	move	r5,r0				;x_floor=0			(fill delay slot)
	j	.y_floor_y_size_check2
	nop					;fill delay slot

.xfloor_positive
	addu	r4,r6,-1			;r4 = r->x_size-1
	slt	r2,r5,r4			;x_floor >= ((r->x_size)-1) ??
	bne	r2,r0,.check_yfloor   		;x_floor >= ((r->x_size)-1) ??
	nop					;fill delay slot
	bgtz	r3,.y_floor_y_size_check2 	;y_floor>0 ??
	move	r5,r4				;x_floor=((r->x_size)-1) 	(fill delay slot)

.y_floor1
	j	.door_check
	li	r3,1				;y_floor=1			(fill delay slot)

.y_floor_y_size_check2
	addu	r4,r7,-2			;r4 = r->y_size-2
	slt	r2,r4,r3			;y_floor > r->y_size-2 ??
	beq	r2,r0,.door_check		;y_floor > r->y_size-2 ??
	nop					;fill delay slot
	j	.door_check
	move	r3,r4				;y_floor=r->y_size-2		(fill delay slot)

.check_yfloor
	bgez	r3,.check_yfloor2  		;y_floor>=0 ??
	nop					;fill delay slot
	j	.door_check
	move	r3,r0				;y_floor=0   			(fill delay slot)

.check_yfloor2
	slt	r2,r3,r7
	bne	r2,r0,.door_check
	nop					;fill delay slot
	addu	r3,r7,-1			;y_floor=r->y_size-1




;/* If doorway, go through and retest, else move onto next stage */
.door_check
	mult	r3,r6				;y_floor*r->x_size
	lw	r3,ROOM_floor(r15)		;r3 = r->floor
	mflo	r8				;r8 = y_floor*r->x_size
	addu	r2,r5,r8			;r2 = x_floor+(y_floor*r->x_size)
	sll	r2,r2,3				;r2 = (x_floor+(y_floor*r->x_size))<<3
	addu	r14,r3,r2			;r14 = r->floor + ((x_floor+(y_floor*r->x_size))<<3)
; r14 = floor
	jal	GetDoor				;GetDoor(floor)
	move	r4,r14				;r4 = floor			(fill delay slot)

;modded this bit to assume GetDoor returns an unsigned int (it does now ;)
	move	r4,r2				;r4 = data
	li	r3,255				;r3 = 255
	beq	r2,r3,.break_out_of_first_loop	;data==255 ??
	sll	r2,r2,2				;r2 = data<<2			(fill delay slot)

	addu	r2,r2,r4			;r2 = data*5
	sh	r4,0(r13)			;*(room_number)=data
	gpr.lw	r3,room				;r3 = room
	j	.doloop1			;loop... :)
	sll	r2,r2,4				;r2 = data*80			(fill delay slot)



;/* If below floor and pit, go down */

.break_out_of_first_loop
	lb	r2,5(r14)
	nop
	sll	r2,r2,8
	slt	r2,r11,r2
	bne	r2,r0,.ll208
	nop					;fill delay slot
.ll184:

	lbu	r3,4(r14)
	li	r2,255
	beq	r3,r2,.exit2
	move	r4,r14				;fill delay slot


	move	r5,r10
	jal	CheckNoColFloorTriangle
	move	r6,r12				;fill delay slot

	move	r3,r2
	li	r2,1
	beq	r3,r2,.exit2
	li	r2,-1				;fill delay slot


	bne	r3,r2,.ll189
	nop					;fill delay slot

	lw	r2,ROOM_minfloor(r15)
	nop
	slt	r2,r11,r2
	bne	r2,r0,.exit
	move	r2,r14				;fill delay slot

.ll189:

	lbu	r2,4(r14)
	nop
	sh	r2,0(r13)

	lbu	r3,4(r14)
	nop
	sll	r2,r3,2
	addu	r2,r2,r3
	gpr.lw	r3,room
	sll	r2,r2,4
	addu	r15,r3,r2

	lw	r2,20(r15)
	lh	r3,40(r15)
	subu	r2,r10,r2
	sra	r2,r2,10
	mult	r2,r3
	lw	r2,28(r15)
	lw	r3,8(r15)
	subu	r2,r12,r2
	sra	r2,r2,10
	mflo	r8
	addu	r2,r2,r8
	sll	r2,r2,3
	addu	r14,r3,r2

	lb	r2,5(r14)
	nop
	sll	r2,r2,8
	slt	r2,r11,r2
	beq	r2,r0,.ll184
	move	r2,r14				;fill delay slot


	j	.exit
	nop					;fill delay slot

.ll194:

	lbu	r3,6(r14)
	nop
	beq	r3,r2,.exit2
	move	r4,r14				;fill delay slot


	move	r5,r10
	jal	CheckNoColCeilingTriangle
	move	r6,r12				;fill delay slot

	move	r3,r2
	li	r2,1
	beq	r3,r2,.exit2
	li	r2,-1				;fill delay slot


	bne	r3,r2,.ll199
	nop					;fill delay slot

	lw	r2,24(r15)
	nop
	slt	r2,r11,r2
	beq	r2,r0,.exit
	move	r2,r14				;fill delay slot

.ll199:

	lbu	r2,6(r14)
	nop
	sh	r2,0(r13)

	lbu	r3,6(r14)
	nop
	sll	r2,r3,2
	addu	r2,r2,r3
	gpr.lw	r3,room
	sll	r2,r2,4
	addu	r15,r3,r2

	lw	r2,20(r15)
	lh	r3,40(r15)
	subu	r2,r10,r2
	sra	r2,r2,10
	mult	r2,r3
	lw	r2,28(r15)
	lw	r3,8(r15)
	subu	r2,r12,r2
	sra	r2,r2,10
	mflo	r8
	addu	r2,r2,r8
	sll	r2,r2,3
	addu	r14,r3,r2

.ll208:
	lb	r2,7(r14)
	nop
	sll	r2,r2,8
	slt	r2,r11,r2
	bne	r2,r0,.ll194
	li	r2,255				;fill delay slot

.exit2

	move	r2,r14

.exit

	lw	r31,16(sp)
	addu	sp,sp,20
	j	r31
	nop







NO_ROOM		equ	255
DATA_TYPE	equ	31
END_BIT		equ	$8000


FLOOR_TYPE	equ	0
DOOR_TYPE	equ     1
TILT_TYPE	equ     2	;1
ROOF_TYPE	equ     3	;2
TRIGGER_TYPE	equ     4
LAVA_TYPE	equ     5
CLIMB_TYPE	equ     6
SPLIT1		equ     7	;1
SPLIT2		equ     8	;1
SPLIT3		equ     9	;2
SPLIT4		equ     10	;2
NOCOLF1T	equ     11	;1
NOCOLF1B	equ     12	;1
NOCOLF2T	equ     13	;1
NOCOLF2B	equ     14	;1
NOCOLC1T	equ     15	;2
NOCOLC1B	equ     16	;2
NOCOLC2T	equ     17	;2
NOCOLC2B	equ     18	;2
MONKEY_TYPE	equ     19
MINEL_TYPE	equ     20
MINER_TYPE	equ     21




; GetDoor, Who knows what it does... but at least its asm now...
;
; r4 = floor
;
; returns r2 info u need... :)
;
; uses at,r2,r3,r4

GetDoor	lhu	r3,0(r4)		;r3 = floor->index
	gpr.lw	r2,floor_data		;r2 = floor_data
	beq	r3,r0,.exitnoroom	;if (!floor->index)
	sll	r3,r3,1			;r3 = floor->index<<1		(fill delay slot)

	addu	r4,r2,r3		;r4 = floor_data + (floor->index<<1)
	lhu	r3,0(r4)		;r3 = type

;/* First item may be TILT_TYPE: skip it */
	li	r2,TILT_TYPE
	andi	r5,r3,DATA_TYPE		;r5 = type&DATA_TYPE
	beq	r5,r2,.gimmie1 		;(type&DATA_TYPE)==TILT_TYPE ??
	addu	r4,r4,2			;data++				(fill delay slot)

	addu	r2,r5,-7		;r2 = (type&DATA_TYPE)-7
	sltu	r2,r2,2			;<2 ??
	bne	r2,r0,.gimmie11
	andi	r2,r3,END_BIT		;r2 = type&END_BIT		(fill delay slot)

	addu	r2,r5,-11		;r2 = (type&DATA_TYPE)-11
	sltu	r2,r2,2			;<2 ??
	bne	r2,r0,.gimmie11
	andi	r2,r3,END_BIT		;r2 = type&END_BIT		(fill delay slot)

	addu	r2,r5,-13		;r2 = (type&DATA_TYPE)-13
	sltu	r2,r2,2			;<2 ??
	beq	r2,r0,.second_check
	li	r2,ROOF_TYPE  		;r2 = ROOF_TYPE	 		(fill delay slot)
.gimmie1
	andi	r2,r3,END_BIT		;r2 = type&END_BIT
.gimmie11
	bne	r2,r0,.exit		;type&END_BIT != 0 ??
	li	r2,NO_ROOM   		;fill delay slot

	lhu	r3,2(r4)		;r3 = *(data)
	addu	r4,r4,4			;data+=2
	andi	r5,r3,DATA_TYPE		;r5 = type&DATA_TYPE
	li	r2,ROOF_TYPE	   	;r2 = ROOF_TYPE



;/* Second may be ROOF_TYPE: skip it */
.second_check
	beq	r5,r2,.gimmie2 		;(type & DATA_TYPE)==ROOF_TYPE ??
	addu	r2,r5,-9		;fill delay slot

	sltu	r2,r2,2
	bne	r2,r0,.ggimmie2
	andi	r2,r3,END_BIT		;fill delay slot

	addu	r2,r5,-15
	sltu	r2,r2,2
	bne	r2,r0,.ggimmie2
	andi	r2,r3,END_BIT		;fill delay slot

	addu	r2,r5,-17
	sltu	r2,r2,2
	beq	r2,r0,.checkdoortype
	nop
.gimmie2

	andi	r2,r3,END_BIT
.ggimmie2
	bne	r2,r0,.exit
	li	r2,NO_ROOM 		;fill delay slot

	lhu	r3,2(r4)		;type = *(data)
	addu	r4,r4,4			;data+=2



.checkdoortype
	andi	r3,r3,DATA_TYPE
	li	r2,DOOR_TYPE
	beq	r3,r2,.doorme
	nop

.exitnoroom
	j	r31
	li	r2,NO_ROOM		;fill delay slot

.doorme	lhu	r2,0(r4)		;r2 = *(data)
.exit	j	r31
	nop






;r4 = floor
;r5 = x
;r6 = z
;
; uses r2,r3,r4,r5,r6,r7,r8
;

CheckNoColFloorTriangle
	lhu	r3,0(r4)		;r3 = floor->index
	gpr.lw	r2,floor_data		;r2 = floor_data
	beq	r3,r0,.ret0 		;floor->index==0 ??
	sll	r3,r3,1			;r3 = floor->index<<1		(fill delay slot)


;// Search for a no collision triangle and see if player is on it.
;/*
; * -------
; * |    /|
; * | T / |     	Split type 1
; * |  /  |
; * | / B |
; * |/    |
; * -------
; */

	addu	r2,r2,r3		;r2 = floor_data+(floor->index<<1)
	lhu	r2,0(r2)		;r2 = type
	nop
	andi	r3,r2,$1f		;type&=DATA_TYPE

	addu	r2,r3,-11		;r2 = type-11
	sltu	r2,r2,2			;
	bne	r2,r0,.checkit 		;
	move	r4,r3			;r4 = type			(fill delay slot)

	addu	r2,r3,-13		;r2 = type-13
	sltu	r2,r2,2
	beq	r2,r0,.exit		;return(0)
	move	r2,r0			;fill delay slot


.checkit
;// Shouldn't (in theory) be any other than these types because there is a pit room on this block.

	andi	r5,r5,$3ff		;x&=1023
	move	r8,r5			;r8=dx
	andi	r6,r6,$3ff		;z&=1023

	li	r2,NOCOLF1T		;r2=NOCOLF1T
	bne	r3,r2,.not_nocolf1t	;type!=NOCOLF1T
	move	r7,r6			;r7=dz			(fill delay slot)

	li	r2,1024			;r2 = 1024
	subu	r2,r2,r6		;r2 = 1024-dz
	slt	r2,r2,r5		;dx<=(1024-dz) ??
	beq	r2,r0,.exit		;dx<=(1024-dz) ??
	li	r2,-1			;fill delay slot

.not_nocolf1t
	move	r3,r4			;r3 = type
	li	r2,NOCOLF1B	 	;r2 = NOCOLF1B
	bne	r3,r2,.not_nocolf1b	;type!=NOCOLF1B
	li	r2,NOCOLF2T 		;r2 = NOCOLF2T		(fill delay slot)

	li	r2,1024			;r2 = 1024
	subu	r2,r2,r7		;r2 = (1024-dz)
	slt	r2,r2,r8		;dx > (1024-dz) ??
	bne	r2,r0,.exit		;dx > (1024-dz) ??
	li	r2,-1			;fill delay slot


	move	r3,r4			;r3 = type
	li	r2,13


.not_nocolf1b
	bne	r3,r2,.not_nocolf2t 	;type!=NOCOLF2T
	nop
	slt	r2,r7,r8		;dx <= dz ??
	beq	r2,r0,.retm1 		;dx <= dz ??
	nop

.not_nocolf2t
	li	r3,NOCOLF2B
	bne	r4,r3,.exit		;type!=NOCOLF2B
	li	r2,1			;fill delay slot

	slt	r3,r7,r8		;dx > dz ??
	beq	r3,r0,.exit		;dx > dz ??
	nop

.retm1	j	r31
	li	r2,-1			;fill delay slot
.ret0	move	r2,r0
.exit	j	r31
	nop








;r4 = floor
;r5 = x
;r6 = z

CheckNoColCeilingTriangle
	lhu	r2,0(r4)		;r2 = floor->index
	gpr.lw	r3,floor_data		;r3 = floor_data
	beq	r2,r0,.ret0 		;floor->index==0 ??
	sll	r2,r2,1			;r2 = floor->index<<1		(fill delay slot)


;// Search for a no collision triangle and see if player is on it.
;
;/*
; * -------
; * |    /|
; * | T / |     	Split type 3
; * |  /  |
; * | / B |
; * |/    |
; * -------
; */


;// Search for floor tilts first.

	addu	r3,r3,r2		;r3 = floor_data+(floor->index<<1)
	lhu	r7,0(r3)		;r7 = type
	li	r2,TILT_TYPE 		;r2 = TILT_TYPE
	andi	r7,r7,$1f		;r7 = type&DATA_TYPE

	beq	r7,r2,.tilt 		;type==TILT_TYPE
	move	r4,r7			;r4 = type			(fill delay slot)

	addu	r2,r7,-7		;r2 = type-7
	sltu	r2,r2,2
	bne	r2,r0,.tilt
	addu	r2,r7,-11		;fill delay slot
	sltu	r2,r2,2
	bne	r2,r0,.tilt
	addu	r2,r7,-13		;fill delay slot
	sltu	r2,r2,2
	beq	r2,r0,.not_tilt
	addu	r2,r4,-15		;fill delay slot

.tilt
	lhu	r2,4(r3)
	nop
	andi	r4,r2,$1f		;r4 = type =  *(data+2)&DATA_TYPE
	addu	r2,r4,-15		;r2 = type-15

.not_tilt
	sltu	r2,r2,2
	bne	r2,r0,.checkit
	addu	r2,r4,-17		;fill delay slot

	sltu	r2,r2,2
	beq	r2,r0,.exit
	move	r2,r0			;fill delay slot

.checkit
;// Shouldn't (in theory) be any other than these types because there is a sky room on this block.

	andi	r5,r5,$3ff		;r5 = x&1023
	move	r8,r5			;r8 = dx
	andi	r6,r6,$3ff		;r6 = z*1023
	move	r3,r4			;r3 = type
	li	r2,NOCOLC1T		;r2 = NOCOLC1T
	bne	r3,r2,.not_nocolc1t
	move	r7,r6			;r7 = dz		(fill delay slot)

	li	r2,1024			;r2 = 1024
	subu	r2,r2,r6		;r2 = 1024-dz
	slt	r2,r2,r5		;dx <= (1024-dz) ??
	beq	r2,r0,.exit		;dx <= (1024-dz) ??
	li	r2,-1			;fill delay slot

	move	r3,r4			;r3 = type

.not_nocolc1t
	li	r2,NOCOLC1B
	bne	r3,r2,.not_nocolc1b
	li	r2,NOCOLC2T  		;r2=NOCOLC2T			(fill delay slot)

	li	r2,1024			;r2 = 1024
	subu	r2,r2,r7		;r2 = 1024-dz
	slt	r2,r2,r8		;dx > (1024-dz) ??
	bne	r2,r0,.exit		;dx > (1024-dz) ??
	li	r2,-1			;fill delay slot

	move	r3,r4			;r3 = type
	li	r2,NOCOLC2T		;r2 = NOCOLC2T

.not_nocolc1b
	bne	r3,r2,.not_nocolc2t 	;type!=NOCOLC2T
	nop
	slt	r2,r7,r8		;dx <= dz ??
	beq	r2,r0,.retm1		;dx <= dz ??
	nop

.not_nocolc2t
	li	r3,NOCOLC2B		;r3=NOCOLC2B
	bne	r4,r3,.exit		;type!=NOCOLC2B
	li	r2,1			;fill delay slot

	slt	r3,r7,r8		;dx > dz ??
	beq	r3,r0,.exit		;dx > dz ??
	nop

.retm1	j	r31
	li	r2,-1			;fill delay slot
.ret0	move	r2,r0
.exit	j	r31
	nop


