gxlight_lxrej.s
9.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
/*---------------------------------------------------------------------*
Copyright (C) 1997, Nintendo.
File gxlight_lxrej.s
Coded by Yoshitaka Yasumoto. Nov 13, 1997.
$Id: gxlight_lxrej.s,v 1.1.1.1 2002/05/02 03:29:11 blythe Exp $
*---------------------------------------------------------------------*/
#---------------------------------------------------------------------
# ライトの変換処理
# ライトの方向ベクトルに対し, MMtx の回転要素 3x3 の転置行列
# を乗じることで, ライトベクトルをモデルのローカル座標系に
# 変換する.
#---------------------------------------------------------------------
FixedAssign(gmode_h, 5) /* gxvtx_ex.s と共用 */
FixedAssign(lighton, 6) /* gxvtx_ex.s と共用 */
caseLXRej_XfmLight:
#-------------------------------------------------------------
# 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
#-------------------------------------------------------------
Assign(mtf0, v12)
lbu sys0, RSP_LSTAT_LIGHT_FLAG(zero)
lbu lighton, RSP_LSTAT_LIGHT_NUM(zero)
lqv mtf0[0], RSP_GSTAT_MMTX+32+0(zero)
bne sys0, zero, caseLXRej_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(mtf1, v13)
Assign(mtf2, v14)
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 箇所に保存する.
#-------------------------------------------------------------
Assign(ndirf, v11)
Assign(ndiri, v15)
XfmLightLoop_lxrej:
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, caseLXRej_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_lxrej_1
vmadh invsqi, ndiri, ndiri /* Delay */
addi lptr, lptr, 24
XfmLightLoop_lxrej_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_lxrej
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)
#---------------------------------------------------------------------
# 頂点カラーの計算
#---------------------------------------------------------------------
caseLXRej_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, caseLXRej_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, caseLXRej_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 caseLXRej_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_lxrej.s ========*/