gxlight_ex.s 10.5 KB
/*---------------------------------------------------------------------*
	Copyright (C) 1997, Nintendo.
	
	File		gxlight_ex.s
	Coded    by	Yoshitaka Yasumoto.	Nov 13, 1997.
	
	$Id: gxlight_ex.s,v 1.1.1.1 2002/05/02 03:29:11 blythe Exp $
 *---------------------------------------------------------------------*/

	#---------------------------------------------------------------------
	#   ライティング処理開始アドレス
	#	Overlay のため, このような位置から始まる
	#	オーバーレイ処理で 19-20,gfx1,sys0,return が破壊される.
	#---------------------------------------------------------------------
			.text	caseEX_XfmLight
  FixedAssign(gmode_h, 5)	/* gxvtx_ex.s と共用 */
  FixedAssign(lighton, 6)	/* gxvtx_ex.s と共用 */
ovlyEX_XfmLight:
		lbu	sys0,    RSP_LSTAT_LIGHT_FLAG(zero)
		j	ovlyEX_XfmLight0
		lbu	lighton, RSP_LSTAT_LIGHT_NUM(zero)
		
	#---------------------------------------------------------------------
	#  Clipping コードのオーバーレイ
	#	gxclip_ex.s のクリップ処理コードをロードする.
	#	ovlyEX_Clipping と同じアドレスにする必要がある.
	#	オーバーレイ処理で 19-20,gfx1,sys0,return が破壊される.
	#	return の値を $30 にセーブする.
	#---------------------------------------------------------------------
  FixedAssign(return_save, 30)
			.space	caseEX_Clipping
ovlyEX_Clipping:
		_mov	(return_save, return)
		_li	(sys0, RSP_SUBMOD_OVERLAY_CLIPPING)
		j	LoadOverlay
		_li	(sys1, caseEX_Clipping0)
  EndAssign(return_save, 30)
	
	#---------------------------------------------------------------------
	#  ライトの変換処理
	#	ライトの方向ベクトルに対し, MMtx の回転要素 3x3 の転置行列
	#	を乗じることで, ライトベクトルをモデルのローカル座標系に
	#	変換する.
	#---------------------------------------------------------------------
ovlyEX_XfmLight0:
		#-------------------------------------------------------------
		#  Light 計算をする必要があるかを判定し, Light 計算が必要な
		#  ければ終了する.
		#	フラグに 0 以外の値を代入し処理済みにする.
		#	gfx0 の最下位バイトは 0 でないのでこれで OK
		#
		#  DMA 転送待ちを利用してパラメータを取得する
		#	lstat:     LSTAT 領域の先頭ポインタ
		#
		#  lighton に((ライトの最終データへのポインタ)-(oRSP_LSTAT_L_0))
		#  を設定する. ただし Light が OFF なら lighton = 0
		#	NumLight=1 なら lighton = RSP_LSTAT_L_0-oRSP_LSTAT_L_0
		#				= RSP_LSTAT_OFFSET
		#	NumLight=2 なら lighton = RSP_LSTAT_1_0-oRSP_LSTAT_L_0-48
		#				= RSP_LSTAT_OFFSET+24
		#-------------------------------------------------------------
		bne	sys0, zero, caseEX_G_VTX_MulMP		# 以降で利用
		addi	lighton, lighton, RSP_LSTAT_OFFSET-24
		sb	gfx0, RSP_LSTAT_LIGHT_FLAG(zero) # フラグを非 0 にする
		
		#-------------------------------------------------------------
		#  3x3 転置マトリクスを取得.
		#  ライトの数/ライトデータへのポインタの計算
		#-------------------------------------------------------------
  FixedAssign(lptr, 20)
  Assign(ldir, v7)
  Assign(mtx0, v8)
  Assign(mtx1, v9)
  Assign(mtx2, v10)
  Assign(mtf0, v12)
  Assign(mtf1, v13)
  Assign(mtf2, v14)
						lqv	mtf0[0], RSP_GSTAT_MMTX+32+0(zero)
						lqv	mtx0[0], RSP_GSTAT_MMTX+ 0+0(zero)
						lsv	mtf1[2], RSP_GSTAT_MMTX+40+2(zero)
						lsv	mtx1[2], RSP_GSTAT_MMTX+ 8+2(zero)
		vmov	mtf1[0], mtf0[1]	lsv	mtf2[4], RSP_GSTAT_MMTX+48+4(zero)
		vmov	mtx1[0], mtx0[1]	lsv	mtx2[4], RSP_GSTAT_MMTX+16+4(zero)
		vmov	mtf2[0], mtf0[2]	_li	(lptr, RSP_LSTAT_OFFSET-24*2)
		vmov	mtx2[0], mtx0[2]	lpv	ldir[0], oRSP_LSTAT_LIGHT_DIR_W(lptr)
		vmov	mtf2[1], mtf0[6]	lsv	mtf1[4], RSP_GSTAT_MMTX+48+2(zero)
		vmov	mtx2[1], mtx0[6]	lsv	mtx1[4], RSP_GSTAT_MMTX+16+2(zero)
		vmov	mtf0[1], mtf0[4]	lsv	mtf0[4], RSP_GSTAT_MMTX+48+0(zero)
		vmov	mtx0[1], mtx0[4]	lsv	mtx0[4], RSP_GSTAT_MMTX+16+0(zero)

		#-------------------------------------------------------------
		#  ライトベクトルの行列変換
		#	光線ベクトルを取得し, 3x3 転置行列を乗ずる.
		#	これにより World 座標から Model 座標へと変換される.
		#  結果の保存
		#	nx,ny,nz 値を 2 箇所に保存する.
		#	COLOR の A 値を 0 にセットする.
		#-------------------------------------------------------------
  Assign(ndirf, v11)
  Assign(ndiri, v15)
XfmLightLoop_ex:
		vmudn	vtmp,  mtf1,  ldir[1]		
		vmadh	vtmp,  mtx1,  ldir[1]
		vmadn	vtmp,  mtf0,  ldir[0]		spv	ndiri[0], oRSP_LSTAT_LIGHT_DIR_M(lptr)
		vmadh	vtmp,  mtx0,  ldir[0]		lw	sys1,     oRSP_LSTAT_LIGHT_DIR_M(lptr)
		vmadn	vtmp,  mtf2,  ldir[2]
		vmadh	vtmp,  mtx2,  ldir[2]
		vsar	ndirf, ndirf, ndirf[1]		sw	sys1,     oRSP_LSTAT_LIGHT_DIR_M+4(lptr)
		vsar	ndiri, ndiri, ndiri[0]		beq	lptr, lighton, caseEX_G_VTX_MulMP
		
		#-------------------------------------------------------------
		#  ライトベクトルの正規化
		#	ベクトルの大きさの 2 乗値を求め, その平方根の逆数を
		#	求める. その値を各要素に乗ずる. そのとき要素の値域が,
		#	0x7fff から -0x8000 となるように予め小数点の位置を操
		#	作しておく.
		#  sys0 の値が初回は 0 であることを利用し, 初回のみ lptr の
		#  加算を回避する.
		#-------------------------------------------------------------
  Assign(invsqf, v16)
  Assign(invsqi, v17)
  Assign(vtmpf,  v18)
		#---- 各要素の 2 乗 ----
		vmudl	vtmp,   ndirf,  ndirf		/* Delay */
		vmadm	vtmp,   ndiri,  ndirf
		vmadn	invsqf, ndirf,  ndiri		beq	sys0, zero, XfmLightLoop_ex_1
		vmadh	invsqi, ndiri,  ndiri		/* Delay */
							addi	lptr, lptr, 24
XfmLightLoop_ex_1:
		#---- 2 乗値の合計 ----
		vaddc	vtmpf,  invsqf, invsqf[1]	_li	(sys0, 1)	# sys0 を非 0 にする
		vadd	vtmp,   invsqi, invsqi[1]
		vaddc	invsqf, vtmpf,  invsqf[2]
		vadd	invsqi, vtmp,   invsqi[2]
		#---- 平方根の逆数 (s8.23) ----		#---- 次のライトの取得 ----
		vrsqh	vtmp  [0], invsqi[0]		lpv	ldir[0], oRSP_LSTAT_LIGHT_DIR_W+24(lptr)
		vrsql	invsqf[0], invsqf[0]
		vrsqh	invsqi[0], _0x0000
		#---- 各要素への乗算 (s15.16)x(s8.23)=(s8.23) ----
		vmudl	vtmp,  ndirf, invsqf[0]
		vmadm	vtmp,  ndiri, invsqf[0]
		vmadn	ndirf, ndirf, invsqi[0]
		vmadh	ndiri, ndiri, invsqi[0]
		#---- 小数点の移動 (s8.23)->(s0.31) ----
		vmudn	ndirf, ndirf, _0x0100
		j	XfmLightLoop_ex
		vmadh	ndiri, ndiri, _0x0100	# +7fff 〜 -8000 でクランプ

  EndAssign(invsqf, v16)
  EndAssign(invsqi, v17)
  EndAssign(vtmpf,  v18)	
  EndAssign(ndirf,  v11)
  EndAssign(ndiri,  v15)
  EndAssign(lptr, 20)
  EndAssign(ldir, v7)
  EndAssign(mtx0, v8)
  EndAssign(mtx1, v9)
  EndAssign(mtx2, v10)
  EndAssign(mtf0, v12)
  EndAssign(mtf1, v13)
  EndAssign(mtf2, v14)

	#---------------------------------------------------------------------
	#  頂点カラーの計算
	#---------------------------------------------------------------------
caseEX_Lighting:
  FixedAssign(lptr,   9)
  FixedAssign(src,    14)	/* gxvtx_ex.s と共用 */
  FixedAssign(lstat,  13)	/* gxvtx_ex.s と共用 */
  FixedAssign(st12,  v22)	/* gxvtx_ex.s と共用 */
  FixedAssign(normX,  v7)
  FixedAssign(normY,  v6)
  FixedAssign(normZ,  v5)
  FixedAssign(color1, v4)
  FixedAssign(color2, v3)
  FixedAssign(ldir1,  v2)
  FixedAssign(ldir2, v20)	/* Vtx では vin12i  */
  FixedAssign(dotp1, v21)	/* Vtx では vin12f  */
  FixedAssign(dotp2, v28)
  FixedAssign(vscn12i, v25)	/* gxvtx_ex.s と共用 */
  FixedAssign(normXu,  v27)
  EndAssign(vtmp, v29)
  FixedAssign(sumcol, v29)	/* Vtx では vtmp    */
	#---- 法線ベクトルの取得 ----
	vadd	normY,   vzero,   normX[1h]	lpv	ldir2[0],  oRSP_LSTAT_LIGHT_DIR_M-24(lptr)
	vadd	normZ,   vzero,   normX[2h]	luv	normXu[0], 8(src)
	vne	color1,  vconst0, vconst0[3h]	luv	sumcol[0], oRSP_LSTAT_LIGHT_COLOR+24(lptr)
L1:	#---- Light と法線の内積計算 (結果を正にクランプする) ----
	vmulu	dotp1,  normX,  ldir1[0h]	luv	color1[0], oRSP_LSTAT_LIGHT_COLOR-24*0(lptr)
	vmacu	dotp1,  normY,  ldir1[1h]	beq	lptr, lstat, L3
	vmacu	dotp1,  normZ,  ldir1[2h]	/*Delay*/
	vmulu	dotp2,  normX,  ldir2[0h]	luv	color2[0], oRSP_LSTAT_LIGHT_COLOR-24*1(lptr)
	vmacu	dotp2,  normY,  ldir2[1h]	addi	sys0, lptr, -24
	vmacu	dotp2,  normZ,  ldir2[2h]	addi	lptr, lptr, -48
	vmrg	sumcol, sumcol, normXu		mtc2	zero, color1[6]
	vmrg	color2, color2, _0x0000		mtc2	zero, color1[14]
	vand	dotp1,  dotp1,  _0x7fff		lpv	ldir1[0], oRSP_LSTAT_LIGHT_DIR_M-24*0(lptr)
	vand	dotp2,  dotp2,  _0x7fff		lpv	ldir2[0], oRSP_LSTAT_LIGHT_DIR_M-24*1(lptr)
	/*V*/					/*S*/
	#---- カラー値の加算 ----
	vmulf	sumcol, sumcol, _0x7fff		/*S*/
	vmacf	sumcol, color1, dotp1[0h]	bne	sys0, lstat, L1
	vmacf	sumcol, color2, dotp2[0h]	/*Delay*/
	#----  環境マップパラメータ計算(内積計算) ----
	vmrg	color2, vzero,   _0x4000	llv	st12[4], 24(src)
  EndAssign  (normXu,  v27)
  FixedAssign(vfog12,  v27)	/* gxvtx_ex.s と共用 */
L2:	vge	vfog12, vscn12i, _0x7f00	andi	sys0, gmode_h, G_TEXTURE_GEN_H
	vmulf	dotp1,  normX,  ldir1[0h]	beq	sys0, zero, caseEX_G_VTX_Return
						#---- カラー値の出力 ----
	/*Delay*/				suv	sumcol[0],  8(src)
	vmacf	dotp1,  normY,  ldir1[1h]	andi	sys1, gmode_h, G_TEXTURE_GEN_LINEAR_H
	vmacf	dotp1,  normZ,  ldir1[2h]	/*S*/
	vxor	color1, color2, _0x4000		/*S*/
	vmulf	dotp2,  normX,  ldir2[0h]	/*S*/
	vmacf	dotp2,  normY,  ldir2[1h]	/*S*/
	vmacf	dotp2,  normZ,  ldir2[2h]	/*S*/
#define	vconstTmp	ldir1
	/* V */					lqv	vconstTmp[0], RSP_LSTAT_VCONST_TMP(zero)
	#---- 内積値を 0 から 1 へ正規化する (0.5*dotp+0.5) ----
	vmudh	st12,  vone,   _0x4000		/*S*/
	vmacf	st12,  color2, dotp1[0h]	beq	sys1, zero, caseEX_G_VTX_Return
	vmacf	st12,  color1, dotp2[0h]	/*Delay*/
	#---- ArcSin の計算 (3 次式 A*x^3+C*x で概算する) ----
	vmadh	st12,  vone,    _0xc000
	/* V x 3 */
	vmulf	color1, st12,   st12		# x*x
	vmulf	color2, st12,   _0x7fff		# A*x (A=0xecb2=
	vmacf	color2, st12,   _0x6cb3		#	0x7fff+0x6cb3=1.8492)
	vmudh	dotp1,  vone,   _0x4000		# +0.5
	vmacf	st12,   st12,   _0x44d3		# C*x (C=0x44d3=0.5377)
	/* V */
	j	caseEX_G_VTX_Return
	vmacf	st12,   color1, color2		# A*x*x*x+C*x+0.5
#undef	vconstTmp
  EndAssign  (vfog12,  v27)	/* gxvtx_ex.s と共用 */
  FixedAssign(normXu,  v27)
	#---- Light が奇数個の時の処理 ----
L3:	vmrg	sumcol, sumcol,  normXu		/*S*/
	vmrg	color1, color1,  _0x0000	/*S*/
	vand	dotp1,  dotp1,   _0x7fff	/*S*/
	veq	color2, vconst0, vconst0[3h]	lpv	ldir1[0], oRSP_LSTAT_LIGHT_DIR_M-24*2(lptr)
	vmrg	color2, vzero,   _0x4000	llv	st12[4], 24(src)
	vmulf	sumcol, sumcol, _0x7fff 	j	L2
	vmacf	sumcol, color1, dotp1[0h]	/*Delay*/
  EndAssign(lptr,    9)
  EndAssign(lstat,  13)		/* gxvtx_ex.s と共用 */
  EndAssign(gmode_h, 5)		/* gxvtx_ex.s と共用 */
  EndAssign(lighton, 6)		/* gxvtx_ex.s と共用 */
  EndAssign(src,    14)		/* gxvtx_ex.s と共用 */
  EndAssign(normX,  v7)
  EndAssign(normY,  v6)
  EndAssign(normZ,  v5)
  EndAssign(color1, v4)
  EndAssign(color2, v3)
  EndAssign(ldir1,  v2)
  EndAssign(ldir2,  v20)	/* Vtx では vin12i  */
  EndAssign(dotp1,  v21)	/* Vtx では vin12f  */
  EndAssign(st12,   v22)
  EndAssign(dotp2,  v28)
  EndAssign(vscn12i,v25)	/* gxvtx_ex.s と共用 */
  EndAssign(normXu, v27)
  EndAssign(sumcol, v29)	/* Vtx では vtmp    */
  FixedAssign(vtmp, v29)
	
/*======== End of gxlight_ex.s ========*/