gflight.s 7.62 KB

 ##########################################################################
 #
 # Vertex Lighting Routine
 #
 # When entering this code we have 
 #
 ##########################################################################

 #### REGISTERS SHARED WITH VERTEX ROUTINE
.name	gmode,		$3
.name	clr1,		$15
.name	clr2,		$16
.name	tmp,		$8
.name	vtmp,		$v3
.name	scratch,	$7
.name	mtx0,		$v8
.name	mtx1,		$v9
.name	mtx2,		$v10
.name	mtx3,		$v11
.name	mtf0,		$v12
.name	mtf1,		$v13
.name	mtf2,		$v14
.name	mtf3,		$v15
.name	st12,		$v18


 #### REGISTERS UNIQUE TO FAST LIGHT ROUTINE
.name	norm,		$v4
.name	lightdir,	$v5
.name	ndotl,		$v6
.name	color,		$v7
.name	sumcol,		$v27
.name	lptr,		$1
 #.name	stdot,		$v19
.name	stdot,		$v20

doLight:
 #lightBegin:
	lw	lptr,RSP_L_NUM(zero)		# pointer to first light

	sw	clr1,0(scratch)			# store normal 1
	sw	clr2,4(scratch)			# store normal 2
	bltz	lptr,xformLights		# transform lights if neccessary
	lpv	norm[0],0(scratch) 		# get normal
 ### JUMP OCCURS to xformLights if lights need transforming.

	luv	color[0],(RSP_L_COL+RSP_L_0 - RSP_L_LEN)(lptr)	# ambient
	vxor	sumcol,sumcol,sumcol				# zero color sum

lightLoop:
	vge	color,color,vconst[0]		# clamp color to 0
	lpv	lightdir[0],(RSP_L_DIR+RSP_L_BASE)(lptr) # dir
	vadd	sumcol,sumcol,color		# accumulate color
	luv	color[0],(RSP_L_COL+RSP_L_BASE)(lptr)	 # col

	vor	stdot,ndotl,vconst[0]		# save previous dot product

	vmulf	ndotl,norm,lightdir		# n dot l
	vadd	vtmp,ndotl,ndotl[1q]		# sum ndotl
	vadd	ndotl,vtmp,ndotl[2h]		# sum ndotl into 1st element
	vmulf	color,color,ndotl[0h]		# color *= ndotl
						#
	bgtz	lptr,lightLoop			# loop if more lights
	addi	lptr,lptr,(-1*RSP_L_LEN)	# next light
 ### LOOP OCCURS to lightLoop: if more lights are on
						#
	suv	sumcol[0],0(scratch)		# store color

	andi	tmp,gmode,G_TEXTURE_GEN_H	# texture coord generation on?
	sb	clr1,3(scratch)			# insert alpha 1
	sb	clr2,7(scratch)			# insert alpha 2
	lw	clr1,0(scratch)			# get color 1
	beq	tmp,zero,lightReturn		# if no tex gen, return
	lw	clr2,4(scratch)			# get color 2
 ### BRANCH OCCURS to retun to lightReturn: if no texture coord generation.

 #
 # TEXTURE COORDINATE GENERATION / REFLECTION MAPPING
 #

 #
 # at this point ndotl = T calculation; stdot = S calculation (both s.15)
 # T * [0, 0.5, 0] is in vector accumulator
 #

	andi	tmp,gmode,G_TEXTURE_GEN_LINEAR_H # linear texture coords on?
	lpv	color[0],(RSP_SELECT_S-RSP_STATE_OFFSET)(rsp_state) # select s
	ldv	ndotl[0],DOLIGHT(zero)		# constants
	vmadn	stdot,color,stdot[0h]		# add S + T-> el[0h][1h]
	beq	tmp,zero,texGenRet		# skip linear if turned off
	vmadm	st12,vconst,vconst[0]		# add S + T-> el[0h][1h]
 ### BRANCH OCCURS to texGenRet if linear texture generation is off.

 #
 # at this point st12 has 
 #   vtx 1's generated T in element 0
 #   vtx 1's generated S in element 1
 #   vtx 2's generated T in element 4
 #   vtx 2's generated S in element 5
 #
 # all numbers range from -0x4000 to +0x4000
 #


 ####
 #### S,T=ARCCOS(S,T)
 ####

	vmulf	color,st12,st12			# st^2
	vmulf	color,color,st12		# st^3
	vmulf	stdot,color,ndotl[1]		# st^3 * 1
	vmacf	stdot,color,ndotl[3]		# st^3 + st^3 * (0x3A0B)
	vmacf	st12,st12,ndotl[2]		# ...+ st * (0x517d)


#if 0

/*
	vmulf	stdot,st12,st12		# s^2
	vadd	stdot,st12,stdot[0h]	# t+s^2
*/

 ###
 ### FUNKY STUFF
 ###


	vmulf	stdot,st12,st12		# s^2
	vmudh	vtmp,stdot,vconst[3]	# -s^2

	vlt	ndotl,st12,vconst[0]	# is t negative?

	cfc2	tmp,$vcc
	srl	tmp,tmp,1
	ctc2	tmp,$vcc

	vmrg	ndotl,vtmp,stdot	# 



/*
	vmulf	stdot,stdot,vtmp[1]
	vmadn	stdot,vconst,vconst[0]
*/
	vadd	stdot,st12,ndotl[0h]	# t+s^2
 ###
 ### FUNKY STUFF
 ###

	sqv	stdot,0(scratch)
	lsv	st12[2],2(scratch)	
	lsv	st12[10],10(scratch)	

/*
	vadd	st12,st12,st12[0]	# t += s
*/
#endif /* 0 */

texGenRet:

/*
 lsv     $v19[0], RSP_STATE_PERSPNORM(rsp_state)
*/


	j	lightReturn			# return when finished
	vadd	st12,st12,vconst[4]		# ...+ (0x4000)
 ### JUMP OCCURS TO return

 ####
 #### S,T=ARCCOS(S,T)
 ####


.unname	ndotl
.unname	vtmp
.unname	norm
.unname	color
.unname	stdot
.unname	st12

.name	modnormi,	$v3
.name	modnormf,	$v6
.name	vtmpi,		$v4
.name	vtmpf,		$v7


xformLights:
	andi	lptr,lptr,0xfff			# clear "untransformed" flag
	sw	lptr,RSP_L_NUM(zero)		#

	jal	getMatrix3			# get the M matrix
	addi	tmp,zero,RSP_CURR_MMTX_OFFSET	# address of Model Matrix
 ### JUMP OCCURS to getMatrix3 to load the 3x3 model matrix

#if	(defined(NEWCOM)||defined(F3DLP_GBI))
	ori	tmp, zero, (RSP_SCRATCH_FLIGHT+15)&0xfff0-16
#else
	ori	tmp, zero, RSP_SCRATCH_OFFSET
#endif
	stv	mtx0[2],16(tmp)		# transpose matrix
	stv	mtx0[4],32(tmp)		#
	stv	mtx0[12],48(tmp)	#
	stv	mtx0[14],64(tmp)	#
	ltv	mtx0[14],16(tmp)	#
	ltv	mtx0[12],32(tmp)	#
	ltv	mtx0[4],48(tmp)		#
	ltv	mtx0[2],64(tmp)		#

	sdv	mtf0[8],16(tmp)		# move float part from 8..15 to 0..7
	sdv	mtf1[8],32(tmp)		#
	sdv	mtf2[8],48(tmp)		#
	ldv	mtf0[0],16(tmp)		#
	ldv	mtf1[0],32(tmp)		#
	ldv	mtf2[0],48(tmp)		#
	

litXformLoop:
	lpv	lightdir[0],(RSP_L_DIR_VIEW+RSP_L_BASE)(lptr) # light dir

	vmulf	lightdir, lightdir, vconst[4]	# half (to avoid overflow)

	vmudn	modnormf, mtf0, lightdir[0h]	# transform normal with 3x3
	vmadn	modnormf, mtf1, lightdir[1h]	# transpose MP matrix
	vmadn	modnormf, mtf2, lightdir[2h]	#
	vmadm	modnormi, vconst, vconst[0]	#

	vmudm	modnormf, modnormi, vconst[2]	# shift frac part right in acc

	vmacf	modnormi, mtx0, lightdir[0h]	# do integer part
	vmacf	modnormi, mtx1, lightdir[1h]	#
	vmacf	modnormi, mtx2, lightdir[2h]	#
	vmadn	modnormf, vconst, vconst[0]	#
	
 ### BEGIN NORMALIZE
 ### BEGIN NORMALIZE

.unname	lightdir
.name	invsqti,	$v26
.name	invsqtf,	$v5

	vmudl	invsqtf,modnormf,modnormf	# invsqt = x^2, y^2, z^2
	vmadm	invsqtf,modnormi,modnormf	#
	vmadn	invsqtf,modnormf,modnormi	#
	vmadh	invsqti,modnormi,modnormi	#
 #	vmadn	invsqtf,vconst,vconst[0]	#


	vaddc	vtmpf,invsqtf,invsqtf[1q]	# sum 3 terms
	vadd	vtmpi,invsqti,invsqti[1q]	# (into 3rd element)
	vaddc	vtmpf,invsqtf,vtmpf[0h]		#
	vadd	vtmpi,invsqti,vtmpi[0h]		#

.unname	mtx3
.unname	mtf3
.name	sqguessi,		$v11
.name	sqguessf,		$v15
.name	const3,			$v2

	vrsqh	sqguessi[0],vtmpi[2]		# 1/sqrt(sum)
	vrsql	sqguessf[0],vtmpf[2]		# (into 0th element)
	vrsqh	sqguessi[0],vconst[0]		#

	vmudl	sqguessf,sqguessf,vconst1[3]	# multiply * 1/128 (1/sqrt moves
	vmadm	sqguessi,sqguessi,vconst1[3]	# radix point 7 places)
	vmadn	sqguessf,vconst,vconst[0]	# (actually 1/128 * .99 to
						# ensure result <1 so no clamp)
.unname	vtmpi
.unname	vtmpf
.name	lightdiri,	$v4
.name	lightdirf,	$v7

	vmudl	lightdirf,modnormf,sqguessf[0]	# 1/sqrt * normal
	vmadm	lightdirf,modnormi,sqguessf[0]	#
	vmadn	lightdirf,modnormf,sqguessi[0]	#
	vmadh	lightdiri,modnormi,sqguessi[0]	#
	vmadn	lightdirf,vconst,vconst[0]	#

 ### clamp to max or min
	ldv	const3[0],VCONST3_OFFSET-RSP_STATE_OFFSET(rsp_state)
	vge	lightdirf,lightdirf,const3[0]	# if < -1fff then =-1fff
	vlt	lightdirf,lightdirf,const3[1]	# if >  1fff then = 1fff
	vmudn	lightdirf,lightdirf,const3[2]	# multiply * 4
	

.unname	sqguessi
.unname	sqguessf
.unname	const3
	
 ### END NORMALIZE
 ### END NORMALIZE

	spv	lightdirf[0],(RSP_R_DIR+RSP_L_BASE)(lptr)
	lw	tmp,(RSP_R_DIR+RSP_L_BASE)(lptr)
	sw	tmp,(RSP_R_DIR+RSP_L_BASE+4)(lptr)

.unname	lightdiri
.unname	lightdirf
.name	mtx3,		$v11
.name	mtf3,		$v15
	
	bgtz	lptr,litXformLoop		# loop if more lights
	addi	lptr,lptr,(-1*RSP_L_LEN)	# next light
 ### LOOP OCCURS to litXformLoop: if more lights are on

	j	getMatrix			# reload the matrix
endofGflight:	
	lh	return,DOLIGHT(zero)		# return address
 ### JUMP OCCURS to getMatrix: and then to doLight:

.unname	invsqti
.unname	invsqtf
.unname	modnormi
.unname	modnormf
.unname	clr1
.unname	clr2
.unname	tmp
.unname	lptr
.unname	sumcol
.unname	scratch
.unname	mtx0
.unname	mtx1
.unname	mtx2
.unname	mtx3
.unname	mtf0
.unname	mtf1
.unname	mtf2
.unname	mtf3
.unname	gmode