****************************************************************************
;
; Miscellaneous Control Routines
;
;****************************************************************************

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

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

SONY_SHELL	equ	0


DCACHE		equ	$1f800000

DATA_TYPE	equ	31
END_BIT		equ	$8000

FLOOR_TYPE	equ	0
DOOR_TYPE	equ	1
TILT_TYPE	equ	2
ROOF_TYPE	equ	3
TRIGGER_TYPE	equ	4
LAVA_TYPE	equ	5
CLIMB_TYPE	equ	6
SPLIT1		equ	7
SPLIT2		equ	8
SPLIT3		equ	9
SPLIT4		equ	10

NO_ROOM		equ	$ff

NO_HEIGHT	equ	-0x7f00

WALL_L		equ	1024
WALL_SHIFT	equ     10

WALL		equ	0
SMALL_SLOPE	equ	1
BIG_SLOPE	equ	2
DIAGONAL	equ	3

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

		rsreset
fiIndex		rh	1
fiBox		rh	1
fiPitRoom	rb	1
fiFloor		rb	1
fiSkyRoom	rb	1
fiCeiling	rb	1
FLOOR_INFO	rb	0

; -------- ITEM_INFO

	if	0
		rsreset
iiFloor		rw	1
iiTouchBits	rw	1
iiMeshBits	rw	1
iiObjectNumber	rh	1
iiCurrentAnim	rh	1
iiGoalAnim	rh	1
iiRequiredAnim	rh	1
iiAnimNumber	rh	1
iiFrameNumber	rh	1
iiRoomNumber	rh	1
iiNextItem	rh	1
iiNextActive	rh	1
iiSpeed		rh	1
iiFallSpeed	rh	1
iiHitPoints	rh	1
iiBoxNumber	rh	1
iiTimer		rh	1
iiFlags		rh	1
iiShadeA	rh	1
iiShadeB	rh	1
iiCarriedItem	rh	1
iiData		rw	1	; 52
iiXPos		rw	1
iiYPos		rw	1
iiZPos		rw	1
iiXRot		rh	1
iiYRot		rh	1
iiZRot		rh	1	; 70

	uint16		active:1;                   // Is Item Active or Not??
	uint16 		status:2;					// Bit packing fun
	uint16 		gravity_status:1;
	uint16 		hit_status:1;               // Has item been hit by a bullet

	uint16 		collidable:1;				// Can Lara Collide with It??
	uint16		looked_at:1;				// has item ever been a camera target
	uint16		dynamic_light:1;			// Used in cutscenes to attach light to first pivot point
	uint16		clear_body:1;				// do we want corpse to be cleared away?
} ITEM_INFO;

	endif

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

	XREF	room			; ROOM *room
	XREF	floor_data		; WORD *floor_data
	XREF	GF_NoFloor		; WORD GF_NoFloor

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

	if	0

;----------------------------------------------------------------------------
;DoSplit
;
;Purpose:	Handles triangular splits
;
;Inputs:	t0 = ptr to floor data
;		t1 = jumpblock
;		t2 = floor data type
;
;Outputs:	v0 = height
;
;Usage:		t3-t9
;
;----------------------------------------------------------------------------

DoSplit	lh	t3,0(t0)	; fetch four tilts
	addi	t0,2
	srl	t6,t3,12	; t6 = tilt3
	srl	t5,t3,8		; t5 = tilt2
	andi	t5,15
	srl	t4,t3,8		; t4 = tilt1
	andi	t4,15
	andi	t3,15		; t3 = tilt0

	andi	t7,a1,1023	; t7 = delta x
	andi	t8,a3,1023	; t8 = delta z

; -------- process SPLIT1

	andi	at,t2,DATA_TYPE
	subi	at,SPLIT1
	bnez	@split2
	ori	at,1024

	sub	at,t8		; determine top or bottom triangle
	sle	at,t7,at
	beqz	at,@bot1

	srl	t9,t2,9		; t9 = height shift
	andi	t9,31
	andi	at,t9,$10	; negative shift ?
	beqz	at,@tpos1
	sub	t7,t5,t4	; t7 = x offset
	ori	t9,$fff0
@tpos1	sub	t8,t3,t4	; t8 = y offset
	sll	t9,8		; update height
	j	@adjust
	add	v0,t9
@bot1:
	srl	t9,t2,4		; t9 = height shift
	andi	t9,31
	andi	at,t9,$10	; negative shift ?
	beqz	at,@bpos1
	sub	t7,t6,t3	; t7 = x offset
	ori	t9,$fff0
@bpos1	sub	t8,t6,t5	; t8 = y offset
	sll	t9,8		; update height
	j	@adjust
	add	v0,t9

; -------- process SPLIT2

	sle	at,t7,t8	; determine top ot bottom triangle
	beqz	at,@bot2

	srl	t9,t2,9		; t9 = height shift
	andi	t9,31
	andi	at,t9,$10	; negative shift ?
	beqz	at,@tpos2
	sub	t7,t5,t4	; t7 = x offset
	ori	t9,$fff0
@tpos2	sub	t8,t6,t5	; t8 = y offset
	sll	t9,8		; update height
	j	@adjust
	add	v0,t9
@bot2:
	srl	t9,t2,4		; t9 = height shift
	andi	t9,31
	andi	at,t9,$10	; negative shift ?
	beqz	at,@bpos2
	sub	t7,t6,t3	; t7 = x offset
	ori	t9,$fff0
@bpos2	sub	t8,t3,t2	; t8 = y offset
	sll	t9,8		; update height
	add	v0,t9

; -------- determine slope type

@adjust	bgez	t7,@x
	move	at,t7
	subi	at,zero,at
@x	sle	at,at,2
	beqz	at,@adjx
	ori	v1,zero,DIAGONAL

	bgez	t8,@y
	move	at,t8
	subi	at,zero,at
@x	sle	at,at,2
	beqz	at,@adjx
	nop
	ori	v1,zero,SMALL_SLOPE

; -------- adjust height

@adjust	bltz	t7,@negx
	ori	t9,zero,WALL_L-1

	sub	at,t9,a3		; WALL_L-1 - z
	and	at,t9			; & WALL_L-1
	mul	at,t7			; * xoff
	addi	at,t7,2			; determine slope size
	bltz	at,@pbigx
	ori	v1,zero,SMALL_SLOPE
@pbigx	ori	v1,zero,DIAGONAL
	mflo	at
	sra	at,2
	j	@adjy
	add	v0,at
@negx:
	and	at,a3,t9		; z & WALL_L-1
	mul	at,t7			; * xoff
	addi	at,t7,2			; determine slope size
	bltz	at,@nbigx
	ori	v1,zero,SMALL_SLOPE
@nbigx	ori	v1,zero,DIAGONAL
	mflo	at
	sra	at,2
	sub	v0,at
@adjy:
	bltz	t8,@negy
	ori	t3,zero,DIAGONAL

	sub	at,t9,a1		; WALL_L-1 - x
	and	at,t9			; & WALL_L-1
	beq	v1,t3,@pslope
	mul	at,t8			; * yoff
	addi	at,t7,2			; determine slope size
	bltz	at,@pbigy
	ori	v1,zero,SMALL_SLOPE
@pbigy	ori	v1,zero,DIAGONAL
@pslope	mflo	at
	sra	at,2
	jr	ra
	add	v0,at
@negy:
	and	at,a3,t9		; x & WALL_L-1
	beq	v1,t1,@nslope
	mul	at,t8			; * yoff
	addi	at,t8,2			; determine slope size
	bltz	at,@nbigy
	ori	v1,zero,SMALL_SLOPE
@nbigy	ori	v1,zero,DIAGONAL
@nslope	mflo	at
	sra	at,2
	jr	ra
	sub	v0,at

DoSkip	jr	ra
	addi	t0,2

DoLava	subi	at,t0,2
	jr	ra
	GPR.sw	trigger_index,at

DoClimb	GPR.lw	t3,trigger_index
	subi	at,t0,2
	beqz	t3,@exit
	nop
	jr	ra
	GPR.sw	trigger_index,at
@exit:
	jr	ra
	nop


;----------------------------------------------------------------------------
;DoTrig
;
;Purpose:	Handles triggered objects
;
;Inputs:	t0 = ptr to floor data
;		t1 = jumpblock
;		t2 = floor data type
;
;Outputs:	v0 = height
;
;Usage:		t3-t9
;
;----------------------------------------------------------------------------

DoTrig	GPR.lw	t3,trigger_index
	subi	at,t0,2
	beqz	t3,@loop
	nop
	GPR.sw	trigger_index,at
@loop:
	lh	t3,0(a0)		; read trigger
	addi	a0,2

; -------- handle non-objects

	andi	t4,t3,$3fff		; t4 = TRIG_BITS
	srl	t4,10
	subi	at,t4,TO_OBJECT
	beqz	at,@obj
	subi	at,t4,TO_CAMERA
	bnez	at,@next
	nop
	lh	t3,0(a0)		; read trigger
	j	@next
	addi	a0,2

; -------- handle objects

@obj	andi	t3,VALUE_BITS


;	item = &items[trigger & VALUE_BITS];
;
;	if (objects[item->object_number].floor)
;		(*objects[item->object_number].floor)(item, x, y, z, &height);

@next:
	bgez	t3,@loop
	nop
	jr	ra
	nop

	endif

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

;	XDEF	GetDoor
;	XDEF	GetFloor
;	XDEF	GetWaterHeight

;----------------------------------------------------------------------------
;GetDoor
;
;Purpose:	Searches for a door within a floor space
;
;Inputs:	a0 = ptr to floor data
;
;Outputs:	None
;
;Usage:		t0-t1/at/v0
;
;----------------------------------------------------------------------------

GetDoor	lhu	t1,fiIndex(a0)
	GPR.lw	t0,floor_data
	beqz	t1,@exit
	sll	t1,1
	add	t0,t1

	lh	t1,0(t0)
	addi	t0,2
	andi	at,t1,DATA_TYPE
	subi	at,DOOR_TYPE
	beqz	at,@door
	nop
	bltz	t1,@exit
	addi	t0,2

	lh	t1,0(t0)
	addi	t0,2
	andi	at,t1,DATA_TYPE
	subi	at,DOOR_TYPE
	beqz	at,@door
	nop
	bltz	t1,@exit
	addi	t0,2

	lh	t1,0(t0)
	addi	t0,2
	andi	at,t1,DATA_TYPE
	subi	at,DOOR_TYPE
	bnez	at,@exit
	nop
@door:
	lh	v0,0(t0)
	jr	ra
	nop				; grrr
@exit:
	jr	ra
	ori	v0,zero,NO_ROOM

;----------------------------------------------------------------------------
;GetFloor
;
;Purpose:	Locates the room and FLOOR_INFO structure for a given
;		position
;
;Inputs:	a0 = x
;		a1 = y
;		a2 = z
;		a3 = pointer to current room #
;
;Outputs:	Pointer to floor data
;
;Usage:		t0-t9/at/v0/v1
;
;----------------------------------------------------------------------------

GetFloor:
	GPR.lw	t0,room			; t0 = room structures
	lhu	t1,0(a3)		; t1 = current room #
	GPR.lw	t2,floor_data		; t2 = floor wad ptr
	lui	t3,$ffff		; t3 = fiFloor/fiCeiling mask
	or	t3,$ff00

;--------------------------------------
; Test Doorway
;--------------------------------------

@doors	sll	t1,4			; t1 = current room ptr
	sll	at,t1,2
	add	t1,at
	add	t1,t0

	lw	t4,riZ(t1)		; t4 = x
	lw	t5,riX(t1)		; t5 = y
	lw	t6,riWidth(t1)		; t6 = x_size
	sub	t4,a2,t4
	sra	t4,WALL_SHIFT
	sub	t5,a0,t5
	sra	t5,WALL_SHIFT
	srl	t7,t6,16		; t7 = y_size
	andi	t6,$ffff

; -------- x clip

	bgtz	t4,@rclip
	subi	t8,t7,2			; t8 = y_size - 2
	j	@xtclip
	move	t4,zero			; clip to left edge
@rclip:
	subi	t9,t6,1			; t9 = x_size - 1
	slt	at,t4,t9
	bnez	at,@yclip
	nop
	move	t4,t9			; clip to right edge
@xtclip:
	slti	at,t5,1			; y < 1 ?
	beqz	at,@xbclip
	slt	at,t5,t8		; y > y_size - 2 ?
	j	@clipok
	ori	t5,zero,1		; clip to top edge
@xbclip:
	bnez	at,@clipok
	nop
	j	@clipok
	move	t5,t8			; clip to bottom edge

; -------- y clip

@yclip	bgtz	t5,@posy
	slt	at,t5,t7
	j	@clipok
	move	t5,zero			; clip to top edge
@posy:
	bnez	at,@clipok
	sub	t8,t7,1			; t8 = y_size - 1
	move	t5,t8			; clip to bottom edge

; ------ calculate floor ptr

@clipok	mult	t5,t6			; y * x_size
	lw	v0,riFloor(t1)
	mflo	at
	add	at,t4			; + x
	sll	at,3			; * sizeof(FLOOR_INFO)
	add	v0,at

; ------ inline GetDoor

	lhu	t8,fiIndex(v0)
	ori	v1,zero,NO_ROOM
	beqz	t8,@dexit
	sll	t8,1
	add	t8,t2

	lh	t9,0(t8)
	addi	t8,2
	andi	at,t9,DATA_TYPE
	subi	at,DOOR_TYPE
	beqz	at,@ddoor
	nop
	bltz	t9,@dexit
	addi	t8,2

	lh	t9,0(t8)
	addi	t8,2
	andi	at,t9,DATA_TYPE
	subi	at,DOOR_TYPE
	beqz	at,@ddoor
	nop
	bltz	t9,@dexit
	addi	t8,2

	lh	t9,0(t8)
	addi	t8,2
	andi	at,t9,DATA_TYPE
	subi	at,DOOR_TYPE
	bnez	at,@dexit
	nop
@ddoor:
	lh	v1,0(t8)
	nop
@dexit:

; -------- recalc room

	sub	at,v1,NO_ROOM
	beqz	at,@pit
	nop
	sh	v1,0(a3)

	j	@doors
	move	t1,v1

;--------------------------------------
; Handle Pit Rooms
;--------------------------------------

@pit	lh	t8,fiPitRoom(v0)
	ori	t9,zero,NO_ROOM
	and	v1,t8,t3		; v1 = fiFloor << 8
	slt	at,a1,v1
	bnez	at,@sky
	andi	t8,$ff			; t8 = pit room
@pitloop:
	beq	t8,t9,@exit		; no pit room ?

; -------- recalc room ptr

	sll	t1,t8,4			; t1 = pit room ptr
	sll	at,t1,2
	add	t1,at
	add	t1,t0
	sh	t8,0(a3)

; -------- recalc floor ptr

	lw	t5,riX(t1)		; t5 = y
	lh	t6,riWidth(t1)		; t6 = x_size
	sub	t5,a0,t5
	sra	t5,WALL_SHIFT
	mult	t5,t6			; y * x_size
	lw	t4,riZ(t1)		; t4 = x
	lw	v0,riFloor(t1)
	sub	t4,a2,t4
	sra	t4,WALL_SHIFT
	mflo	at
	add	at,t4			; + x
	sll	at,3			; * sizeof(FLOOR_INFO)
	add	v0,at

	lh	t8,fiPitRoom(v0)
	nop
	and	v1,t8,t3		; t7 = fiFloor << 8
	slt	at,a1,v1
	beqz	at,@pitloop
	andi	t8,$ff			; t8 = pit room
	jr	ra
	nop

;--------------------------------------
; Handle Sky Rooms
;--------------------------------------

@sky	lh	t8,fiSkyRoom(v0)
	ori	t9,zero,NO_ROOM
	and	v1,t8,t3		; v1 = fiCeiling << 8
	slt	at,a1,v1
	beqz	at,@exit
	andi	t8,$ff			; t8 = sky room
@skyloop:
	beq	t8,t9,@exit		; no sky room ?

; -------- recalc room ptr

	sll	t1,t8,4			; t1 = sky room ptr
	sll	at,t1,2
	add	t1,at
	add	t1,t0
	sh	t8,0(a3)

; -------- recalc floor ptr

	lw	t5,riX(t1)		; t5 = y
	lh	t6,riWidth(t1)		; t6 = x_size
	sub	t5,a0,t5
	sra	t5,WALL_SHIFT
	mult	t5,t6			; y * x_size
	lw	t4,riZ(t1)		; t4 = x
	lw	v0,riFloor(t1)
	sub	t4,a2,t4
	sra	t4,WALL_SHIFT
	mflo	at
	add	at,t4			; + x
	sll	at,3			; * sizeof(FLOOR_INFO)
	add	v0,at

	lh	t8,fiSkyRoom(v0)
	nop
	and	v1,t8,t3		; t7 = fiCeiling << 8
	slt	at,a1,v1
	bnez	at,@skyloop
	andi	t8,$ff			; t8 = sky room
@exit
	jr	ra
	nop

;----------------------------------------------------------------------------
;GetWaterHeight
;
;Purpose:	Determines the height of water, if any, at the given position
;
;Inputs:	a0 = x
;		a1 = y
;		a2 = z
;		a3 = room #
;
;Outputs:	Height of water surface
;
;Usage:		t0-t9/at/v0/v1
;
;----------------------------------------------------------------------------

GetWaterHeight:
	GPR.lw	t0,room			; t0 = room structures
	GPR.lw	t2,floor_data		; t2 = floor wad ptr
	lui	t3,$ffff		; t3 = fiFloor/fiCeiling mask
	or	t3,$ff00

;--------------------------------------
; Test Doorway
;--------------------------------------

@doors	sll	t1,a3,4			; t1 = current room ptr
	sll	at,t1,2
	add	t1,at
	add	t1,t0

	lw	t4,riZ(t1)		; t4 = x
	lw	t5,riX(t1)		; t5 = y
	lw	t6,riWidth(t1)		; t6 = x_size
	sub	t4,a2,t4
	sra	t4,WALL_SHIFT
	sub	t5,a0,t5
	sra	t5,WALL_SHIFT
	srl	t7,t6,16		; t7 = y_size
	andi	t6,$ffff

; -------- x clip

	bgtz	t4,@rclip
	subi	t8,t7,2			; t8 = y_size - 2
	j	@xtclip
	move	t4,zero			; clip to left edge
@rclip:
	subi	t9,t6,1			; t9 = x_size - 1
	slt	at,t4,t9
	bnez	at,@yclip
	nop
	move	t4,t9			; clip to right edge
@xtclip:
	slti	at,t5,1			; y < 1 ?
	beqz	at,@xbclip
	slt	at,t5,t8		; y > y_size - 2 ?
	j	@clipok
	ori	t5,zero,1		; clip to top edge
@xbclip:
	bnez	at,@clipok
	nop
	j	@clipok
	move	t5,t8			; clip to bottom edge

; -------- y clip

@yclip	bgtz	t5,@posy
	slt	at,t5,t7
	j	@clipok
	move	t5,zero			; clip to top edge
@posy:
	bnez	at,@clipok
	sub	t8,t7,1			; t8 = y_size - 1
	move	t5,t8			; clip to bottom edge

; ------ calculate floor ptr

@clipok	mult	t5,t6			; y * x_size
	lw	v0,riFloor(t1)
	mflo	at
	add	at,t4			; + x
	sll	at,3			; * sizeof(FLOOR_INFO)
	add	v0,at

; ------ inline GetDoor

	lhu	t8,fiIndex(v0)
	ori	v1,zero,NO_ROOM
	beqz	t8,@dexit
	sll	t8,1
	add	t8,t2

	lh	t9,0(t8)
	addi	t8,2
	andi	at,t9,DATA_TYPE
	subi	at,DOOR_TYPE
	beqz	at,@ddoor
	nop
	bltz	t9,@dexit
	addi	t8,2

	lh	t9,0(t8)
	addi	t8,2
	andi	at,t9,DATA_TYPE
	subi	at,DOOR_TYPE
	beqz	at,@ddoor
	nop
	bltz	t9,@dexit
	addi	t8,2

	lh	t9,0(t8)
	addi	t8,2
	andi	at,t9,DATA_TYPE
	subi	at,DOOR_TYPE
	bnez	at,@dexit
	nop
@ddoor:
	lh	v1,0(t8)
	nop

; -------- recalc room

@dexit	sub	at,v1,NO_ROOM
	beqz	at,@dir
	nop
	j	@doors
	move	a3,v1

;--------------------------------------
; Determine Direction
;--------------------------------------

@dir	lh	t8,riFlags(t1)
	nop
	andi	t8,UNDERWATER|SWAMP
	bnez	t8,@sky
	nop

;--------------------------------------
; Handle Pit Rooms
;--------------------------------------

	lh	t8,fiPitRoom(v0)
	ori	t9,zero,NO_ROOM
	and	v0,t8,t3		; v0 = fiFloor << 8
@pitloop:
	andi	t8,$ff			; t8 = pit room
	beq	t8,t9,@nowater		; no pit room ?

; -------- recalc room ptr

	sll	t1,t8,4			; t1 = pit room ptr
	sll	at,t1,2
	add	t1,at
	add	t1,t0

; -------- hit water ?

	lh	t8,riFlags(t1)
	lw	t5,riX(t1)		; t5 = y
	andi	t8,UNDERWATER|SWAMP
	bnez	t8,@exit

; -------- recalc floor ptr

	lh	t6,riWidth(t1)		; t6 = x_size
	sub	t5,a0,t5
	sra	t5,WALL_SHIFT
	mult	t5,t6			; y * x_size
	lw	t4,riZ(t1)		; t4 = x
	lw	v0,riFloor(t1)
	sub	t4,a2,t4
	sra	t4,WALL_SHIFT
	mflo	at
	add	at,t4			; + x
	sll	at,3			; * sizeof(FLOOR_INFO)
	add	v0,at

	lh	t8,fiPitRoom(v0)
	j	@pitloop
	and	v0,t8,t3		; v0 = fiFloor << 8

;--------------------------------------
; Handle Sky Rooms
;--------------------------------------

@sky	lh	t8,fiSkyRoom(v0)
	ori	t9,zero,NO_ROOM
	and	v0,t8,t3		; v0 = fiCeiling << 8
@skyloop:
	andi	t8,$ff			; t8 = sky room
	beq	t8,t9,@nowater		; no sky room ?

; -------- recalc room ptr

	sll	t1,t8,4			; t1 = sky room ptr
	sll	at,t1,2
	add	t1,at
	add	t1,t0

; -------- left water ?

	lh	t8,riFlags(t1)
	lw	t5,riX(t1)		; t5 = y
	andi	t8,UNDERWATER|SWAMP
	beqz	t8,@exit

; -------- recalc floor ptr

	lw	t5,riX(t1)		; t5 = y
	lh	t6,riWidth(t1)		; t6 = x_size
	sub	t5,a0,t5
	sra	t5,WALL_SHIFT
	mult	t5,t6			; y * x_size
	lw	t4,riZ(t1)		; t4 = x
	lw	v0,riFloor(t1)
	sub	t4,a2,t4
	sra	t4,WALL_SHIFT
	mflo	at
	add	at,t4			; + x
	sll	at,3			; * sizeof(FLOOR_INFO)
	add	v0,at

	lh	t8,fiSkyRoom(v0)
	j	@skyloop
	and	v0,t8,t3		; v0 = fiCeiling << 8
@nowater:
	lui	v0,$ffff
	jr	ra
	ori	v0,NO_HEIGHT&$ffff
@exit
	jr	ra
	nop

;----------------------------------------------------------------------------
;GetHeight
;
;Purpose:	Determines the height for a given world position
;
;Inputs:	a0 = pointer to floor data
;		a1 = x
;		a2 = y
;		a3 = z
;
;Outputs:	;
;
;Usage:		t0-t1/at/v0
;
;----------------------------------------------------------------------------

	if	0

GetHeight:
	move	t0,ra			; t0 = ra
	ori	t1,zero,WALL		; t1 = height type

;--------------------------------------
; Handle Pit Rooms
;--------------------------------------

	GPR.lw	t2,room			; t2 = room structures

@pit	lbu	t3,fiPitRoom(a0)
	ori	t4,zero,NO_ROOM
	beq	t3,t4,@nopit		; no pit room ?

; -------- recalc room ptr

	sll	t3,4			; t3 = pit room ptr
	sll	at,t3,2
	add	t3,at
	add	t3,t2

; -------- recalc floor ptr

	lw	t4,riX(t3)		; t4 = y
	lh	t5,riWidth(t3)		; t5 = x_size
	sub	t4,a1,t4
	sra	t4,WALL_SHIFT
	mult	t4,t5			; y * x_size
	lw	t5,riZ(t3)		; t5 = x
	lw	a0,riFloor(t3)
	sub	t5,a3,t5
	sra	t5,WALL_SHIFT
	mflo	at
	add	at,t5			; + x
	sll	at,3			; * sizeof(FLOOR_INFO)
	j	@pit
	add	a0,at

;--------------------------------------
; Determine Data Type
;--------------------------------------

	lb	v0,fiFloor(a0)		; v0 = height
	GPR.lw	t3,GF_NoFloor		; t3 = floor wad ptr
	sll	v0,8
	sub	at,v0,t3
	beqz	at,@
	lhu	t4,fiIndex(a0)
@	ori	v0,zero,$4000

	beqz	t4,@exit
	GPR.sw	zero,trigger_index


	GPR.lw	t0,floor_data		; t0 = floor wad ptr
	sll	t4,1
	add	t0,t4
	lui	t1,HeightRtn>>16	; t1 = jumpblock
	ori	t1,HeightRtn&$ffff
@loop:
	lh	t2,0(t0)		; t2 = floor data
	addi	t0,2
	andi	t3,t2,DATA_TYPE		; t3 = floor data type
	sll	t3,1
	add	t3,t1
	lh	t3,0(t3)
	nop
	jal	t3
	nop

	bgez	t2,@loop
	nop
@exit:
	jr	t1
	nop

	endif

	if	!SONY_SHELL

	XDEF	PCopen0
	XDEF	PCclose0
	XDEF	PClseek0
	XDEF	PCread0
	XDEF	PCwrite0
	XDEF	PCcreat0

	XREF	PCopen
	XREF	PCclose
	XREF	PClseek
	XREF	PCread
	XREF	PCwrite
	XREF	PCcreat
	XREF	EnterCriticalSection
	XREF	ExitCriticalSection
	XREF	printf

;Message	db	'.',0,0,0,0
;	cnop	0,4

PCopen0:
	move	at,zero
	move	v0,zero
	move	v1,zero
	move	t0,zero
	move	t1,zero
	move	t2,zero
	move	t3,zero
	move	t4,zero
	move	t5,zero
	move	t6,zero
	move	t7,zero
	move	t8,zero
	move	t9,zero
	j	PCopen
	move	a3,zero

PClseek0:
	subi	sp,16
	sw	ra,0(sp)
	sw	a0,4(sp)
	sw	a1,8(sp)
	jal	EnterCriticalSection
	sw	a2,12(sp)

	move	at,zero
	move	v0,zero
	move	v1,zero
	move	t0,zero
	move	t1,zero
	move	t2,zero
	move	t3,zero
	move	t4,zero
	move	t5,zero
	move	t6,zero
	move	t7,zero
	move	t8,zero
	move	t9,zero
	move	a3,zero
	lw	a0,4(sp)
	lw	a1,8(sp)
	jal	PClseek
	lw	a2,12(sp)

	jal	ExitCriticalSection
	nop
	lw	ra,0(sp)
	addi	sp,16
	jr	ra
	nop

PCread0:
	subi	sp,160
	sw	ra,16(sp)
	sw	a0,20(sp)
	sw	a1,24(sp)
	sw	a2,28(sp)
@loop:
	lw	a0,20(sp)
	lw	a1,24(sp)
	lw	a2,28(sp)
	nop
	slti	at,a2,$ffff
	beqz	at,@more
	nop
	sw	zero,28(sp)
	j	@ok
	nop
@more:
	addi	at,a1,$ffff
	sw	at,24(sp)
	subi	at,a2,$ffff
	sw	at,28(sp)
	ori	a2,zero,$ffff
@ok:
	move	at,zero
	move	v0,zero
	move	v1,zero
	move	t0,zero
	move	t1,zero
	move	t2,zero
	move	t3,zero
	move	t4,zero
	move	t5,zero
	move	t6,zero
	move	t7,zero
	move	t8,zero
	move	t9,zero
	jal	PCread
	move	a3,zero

;	la	a0,Message
;	jal	printf
;	nop

	lw	a2,28(sp)
	nop
	bnez	a2,@loop
	nop

	lw	ra,16(sp)
	addi	sp,160
	jr	ra
	nop

PCclose0:
	move	at,zero
	move	v0,zero
	move	v1,zero
	move	t0,zero
	move	t1,zero
	move	t2,zero
	move	t3,zero
	move	t4,zero
	move	t5,zero
	move	t6,zero
	move	t7,zero
	move	t8,zero
	move	t9,zero
	move	a1,zero
	move	a2,zero
	j	PCclose
	move	a3,zero

PCwrite0:
	move	at,zero
	move	v0,zero
	move	v1,zero
	move	t0,zero
	move	t1,zero
	move	t2,zero
	move	t3,zero
	move	t4,zero
	move	t5,zero
	move	t6,zero
	move	t7,zero
	move	t8,zero
	move	t9,zero
	j	PCwrite
	move	a3,zero

PCcreat0:
	move	at,zero
	move	v0,zero
	move	v1,zero
	move	t0,zero
	move	t1,zero
	move	t2,zero
	move	t3,zero
	move	t4,zero
	move	t5,zero
	move	t6,zero
	move	t7,zero
	move	t8,zero
	move	t9,zero
	move	a2,zero
	j	PCcreat
	move	a3,zero

	endif

	XDEF	S_SetupBelowWater
	XDEF	S_SetupAboveWater
	XREF	GdwUWClutSub
	XREF	swClutSub

S_SetupBelowWater:
	GPR.lw	a0,GdwUWClutSub
S_SetupAboveWater:
	nop
	ctc2	a0,C2_DQB
	jr	ra
	GPR.sw	a0,swClutSub

