gxclip_ex.s
11.8 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
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
/*---------------------------------------------------------------------*
Copyright (C) 1997, Nintendo.
File gxclip_ex.s
Coded by Yoshitaka Yasumoto. Dec 22, 1997.
$Id: gxclip_ex.s,v 1.1.1.1 2002/05/02 03:29:11 blythe Exp $
*---------------------------------------------------------------------*/
#!Reserved (0,11,12,22,23,24,25,26,27,31)
#!Reserved (v0,v1,v29,v30,v31)
#---------------------------------------------------------------------
# ライトコードのオーバーレイ
# gxlight_ex.s のライト処理コードをロードする.
# caseEX_XfmLight と同じアドレスにする必要がある.
#---------------------------------------------------------------------
caseEX_XfmLight:
_li (sys0, RSP_SUBMOD_OVERLAY_LIGHTING)
j LoadOverlay
_li (sys1, ovlyEX_XfmLight)
#---------------------------------------------------------------------
# クリッピング処理
# flat,v1,v2 を頂点とする 3 角形に対してクリップ処理を行なう
# RSP_WORK_CLIPBUF_0,1 にそれぞれ 10 個分の Vtx Ptr 保持領域
# を設ける. EX マイクロコードは 頂点数が 32 個しかないので
# RSP_SAVE_POINTS 領域に空きがあるので, その領域を Buffer と
# して使用する.
#---------------------------------------------------------------------
FixedAssign(v0, 1) # gxsetup からの入力
FixedAssign(v1, 2) # gxsetup からの入力
FixedAssign(v2, 3) # gxsetup からの入力
FixedAssign(flat, 4) # gxsetup からの入力
FixedAssign(fogon, 7) # gxvtx_ex 用レジスタ
FixedAssign(dest2, 8) # gxvtx_ex 用レジスタ
FixedAssign(cflag, 10) # gxvtx_ex 用レジスタ
FixedAssign(lstat, 13) # gxvtx_ex 用レジスタ
FixedAssign(dest,15) # gxvtx_ex 用レジスタ
FixedAssign(cliptest_save, 29)
FixedAssign(return_save, 30)
FixedAssign(clipbuf, 18)
Assign(plane, 5)
#------ Clipping 処理の開始 ------
#
# $31 を $30 へ保存する
#
caseEX_Clipping:
_mov (return_save, return)
#------ ClipBuf の初期化 ------
#
# plane は 20 から 0 まで 4 ずつ変化し, これによって CC のマスク値と
# クリップ面と辺の交差判定式の各項の値を取得する
#
caseEX_Clipping0:
_liu (plane, 20) # Clipping Plane 選択
_liu (clipbuf, 6) # ClipBuf へのポインタ
_liu (dest, RSP_WORK_CLIPVTX) # Clipping で生成され
# る頂点Cache
#------ ClipBuf の初期化 ------
sh v0, RSP_SUBMOD_EX_CLIPBUF-6(clipbuf) # v0
sh v1, RSP_SUBMOD_EX_CLIPBUF-4(clipbuf) # v1
sh v2, RSP_SUBMOD_EX_CLIPBUF-2(clipbuf) # v2
sh zero, RSP_SUBMOD_EX_CLIPBUF-0(clipbuf) # End Mark
#------ ClipTest 値の保存(再 setup において使用) ------
#
# 処理の途中で頂点が 3 個未満になったとき, Clip_EX_Return に
# 飛ぶが, このときに cliptest_save を書き込むことの対策
# NEARCLIP_ON 0x30304040
# NEARCLIP_OFF 0x30304080
#
lw cliptest_save, RSP_SUBMOD_EX_CLIPTEST(zero)
EndAssign(v0, 1)
FixedAssign(num, 1) # gxvtx_ex 用レジスタ
FixedAssign(src, 14) # gxvtx_ex 用レジスタ
Assign(clipmask, 9)
Assign(ccsave, 16)
Assign(ibufp, 17)
FixedAssign(obufp, 21)
EXClip_InitPlane:
#------ CC のマスク値の取得 ------
lw clipmask, RSP_SUBMOD_EX_CLIPMASK(plane)
#------ 最終 CC の取得 ------
#
# 最初の頂点と隣り合う頂点=最終頂点 ここでは v2
#
lw ccsave, oRSP_POINT_CC(v2)
and ccsave, ccsave, clipmask
#------ ClipBuf のポインタの取得 ------
#
# クリップ面毎にバッファの In,Out を交換する
# clipbuf は 6 <-> RSP_SUBMOD_CLIPBUF_SZ+6 と変化
#
addi ibufp, clipbuf, -6
xori clipbuf, clipbuf, (RSP_SUBMOD_EX_CLIPBUF_SZ+6)^6
addi obufp, clipbuf, -6
#------ CC を比較し変化を調べる ------
#
# クリップ面に対応する CC を辺の両端の頂点組ごとに比較する.
# 異なっていた場合, クリップ面と辺が交差することになる.
#
EXClip_NextVtx:
lhu v1, RSP_SUBMOD_EX_CLIPBUF(ibufp) # 頂点ポインタの取得
addi ibufp, ibufp, 2 # ClipBuf の加算
beq v1, zero, EXClip_NextPlane # v1 が 0 なら次の面へ
lw sys0, oRSP_POINT_CC(v1) # cc の取得
and sys0, sys0, clipmask # cc をマスク
beq sys0, ccsave, EXClip_EntryVtx # cc が同じなら Jump
_mov (ccsave, sys0) # cc のセーブ
#------ 新しい頂点の生成(v1 と v2 の間) ------
#
# 同次座標系において交差位置(内分比 n)を計算する.
# n = (x1-w1)/((x1-x2)-(w1-w2))
#
Assign(selp, v2)
Assign(seln, v3)
Assign(vtx1f, v4)
Assign(vtx1i, v5)
Assign(vtx2f, v6)
Assign(vtx2i, v7)
Assign(topf, v8)
Assign(topi, v9)
Assign(botf, v10)
Assign(boti, v11)
Assign(v1s, 19)
EXClip_NewVtx:
#------ vv1 を内側 v2 を外側とする ------
beq ccsave, zero, EXClip_NewVtx0
_mov (v1s, v1)
_mov (v1s, v2)
_mov (v2, v1)
EXClip_NewVtx0:
sll sys0, plane, 1 # 2 倍する 0,8,16,...
ldv selp[0], RSP_LSTAT_CLIPSELECT(sys0)
ldv vtx1f[0], oRSP_POINT_XF(v1s)
ldv vtx1i[0], oRSP_POINT_XI(v1s)
ldv vtx2f[0], oRSP_POINT_XF(v2)
ldv vtx2i[0], oRSP_POINT_XI(v2)
#------ 分子分母の計算 ------
vmudh seln, selp, _0xffff # selp=[1 0 0 -1] のとき
vmudn topf, vtx1f, selp
vmadh topi, vtx1i, selp # top=[x1 0 0 -w1]
vmadn botf, vtx2f, seln
vmadh boti, vtx2i, seln # bot=[x1-x2 0 0 w2-w1]
EndAssign(selp, v2)
EndAssign(seln, v3)
Assign(vconstTmp, v25)
vaddc topf, topf, topf[0q] lqv vconstTmp[0], RSP_LSTAT_VCONST_TMP(zero)
vadd topi, topi, topi[0q]
vaddc botf, botf, botf[0q]
vadd boti, boti, boti[0q]
vaddc topf, topf, topf[1h]
vadd topi, topi, topi[1h] # top[3]=(x1-w1)
vaddc botf, botf, botf[1h]
vadd boti, boti, boti[1h] # bot[3]=(x1-x2)-(w1-w2)
# スケールファクタの取得
Assign(wsclf, v2)
Assign(wscli, v3)
vor vtmp, boti, _0x0001 # 非 0 にする
vrcph wscli[3], boti[3]
vrcpl wsclf[3], botf[3]
vrcph wscli[3], _0x0000
# 頂点合わせ+絶対値計算
vabs vtmp, vtmp, _0x0002 # vtmp[3]=((wscli[3]>0)?2:-2)
vmudn wsclf, wsclf, vtmp[3]
vmadh wscli, wscli, vtmp[3]
# 1 未満にまるめる
veq wscli, wscli, _0x0000 # if wscl >= 1.0
vmrg wsclf, wsclf, _0xffff # then wscl = 0.99999
EndAssign(wscli, v3)
# スケールファクタを乗ずる
vmudl vtmp, botf, wsclf[3]
vmadm boti, boti, wsclf[3]
vmadn botf, vzero, _0x0000
# Newton 法を使用し逆数計算を行なう
# vrcph/l で求めるのは 1/2X の値. (R=1/X)
# 1/X = R*(2-R*X) = R/2*(4+R/2*X*(-4))
Assign(rbotf, v12)
Assign(rboti, v13)
vrcph rboti[3], boti[3]
vrcpl rbotf[3], botf[3]
vrcph rboti[3], _0x0000 # R/2
#if 1
vmudl vtmp, rbotf, botf
vmadm vtmp, rboti, botf
vmadn botf, rbotf, boti
vmadh boti, rboti, boti # R/2*X
vmudh vtmp, vone, _0x0004
vmadn botf, botf, _0xfffc
vmadh boti, boti, _0xfffc # 4+R/2*X*(-4)
vmudl vtmp, rbotf, botf
vmadm vtmp, rboti, botf
vmadn rbotf, rbotf, boti
vmadh rboti, rboti, boti # R/2*(4+R/2*X*(-4))
#else
vmudn rbotf, rbotf, _0x0002
vmadh rboti, rboti, _0x0002 # R
vmudl vtmp, rbotf, botf
vmadm vtmp, rboti, botf
vmadn botf, rbotf, boti
vmadh boti, rboti, boti # R*X
vmudh vtmp, vone, _0x0002
vmadn botf, botf, _0xffff
vmadh boti, boti, _0xffff # 2-R*X
vmudl vtmp, rbotf, botf
vmadm vtmp, rboti, botf
vmadn rbotf, rbotf, boti
vmadh rboti, rboti, boti # R*(2-R*X)
#endif
EndAssign(vconstTmp, v25)
EndAssign(botf, v10)
EndAssign(boti, v11)
Assign(nf, v10)
Assign(ni, v11)
Assign(st1, v25)
Assign(st2, v26)
# n=top/bot を求める
vmudl vtmp, topf, rbotf luv st2[0], oRSP_POINT_R(v2)
vmadm vtmp, topi, rbotf llv st2[8], oRSP_POINT_S(v2)
vmadn nf, topf, rboti luv st1[0], oRSP_POINT_R(v1s)
vmadh ni, topi, rboti llv st1[8], oRSP_POINT_S(v1s)
EndAssign(v1s, 19)
EndAssign(topf, v8)
EndAssign(topi, v9)
EndAssign(rbotf, v12)
EndAssign(rboti, v13)
#------ スケールファクタを乗ずる ------
vmudl vtmp, nf, wsclf[3]
vmadm ni, ni, wsclf[3]
vmadn nf, nf, _0x0000
EndAssign(wsclf, v2)
#------ n をクランプする ------
# 0x0001 から 0xffff までに納める
#
vlt ni, ni, _0x0001
vmrg nf, nf, _0xffff
vsubc vtmp, nf, _0x0001
vge ni, ni, _0x0000
vmrg nf, nf, _0x0001
Assign(negnf, v2)
#------ 1-n の計算 ------
vmudn negnf, nf, _0xffff
EndAssign(ni, v11)
FixedAssign(vout12f, v23)
FixedAssign(vout12i, v24)
#
# 新頂点座標の計算 v1*(1-n)+v2*n
#
vmudl vtmp, vtx2f, nf[3]
vmadm vtmp, vtx2i, nf[3]
vmadl vtmp, vtx1f, negnf[3]
vmadm vout12i, vtx1i, negnf[3]
vmadn vout12f, vzero, _0x0000
EndAssign(vtx1f, v4)
EndAssign(vtx1i, v5)
EndAssign(vtx2f, v6)
EndAssign(vtx2i, v7)
# 新頂点のアトリビュート値の計算 [R|G|B|A|S|T|-|-]
FixedAssign(st12, v22)
vmudm vtmp, st2, nf[3]
vmadm st12, st1, negnf[3]
EndAssign(st1, v25)
EndAssign(st2, v26)
EndAssign(nf, v10)
EndAssign(negnf, v2)
#
# gxvtx_ex と一致するように調整
# out12f(v23)
# out12i(v24)
# fogon(7) =0
# num(1) =2
# dest(3) 頂点キャッシュバッファ(VTX 処理内で +80 される)
# st12(v22) gxvtx_ex 内で変化無いので return 後再設定する
#
# GetTrans で以下が取得できる
# lstat(13),vpscale(v16),vptrans(v17),txscale(v18),dest2(8)
#
# GetTrans 後 G_VTX_Return へ Jump する.
#
_li (fogon, 0)
_li (num, 2)
sh dest, RSP_SUBMOD_EX_CLIPBUF(obufp)
j caseEX_G_VTX_GetTrans
_li (return, caseEX_G_VTX_Return+0x8000) # return<0 なら vtx 処理後,ここへ戻る
FixedAssign(vscn12i, v25)
FixedAssign(vscn12f, v26)
FixedAssign(vcolor, v3)
#------ 残りパラメータの書き込み ------
caseEX_ClipRet:
#ifndef NO_CLAMP_Z
slv vscn12i[0], 24-80(dest) # Xs,Ys1
#else
sdv vscn12i[0], 24-80(dest) # Xs,Ys,Zs1
#endif
ssv vscn12f[4], 30-80(dest) # Zsf1
suv st12[0], 16-80(dest) # R,G,B,A
slv st12[8], 20-80(dest) # S,T
#ifndef NO_CLAMP_Z
ssv vcolor[4], 28-80(dest) # Zs1
#endif
addi dest, dest, -40
addi obufp, obufp, 2
EndAssign(st12, v22)
EndAssign(vout12f, v23)
EndAssign(vout12i, v24)
EndAssign(vscn12i, v25)
EndAssign(vscn12f, v26)
EndAssign(vcolor, v3)
EXClip_EntryVtx:
#------ 頂点 v1 が画面内ならバッファに登録 ------
bne ccsave, zero, EXClip_NextVtx # 画面外なら次の頂点へ
_mov (v2, v1) # v1 のセーブ
sh v2, RSP_SUBMOD_EX_CLIPBUF(obufp)# ClipBuf への登録
j EXClip_NextVtx
addi obufp, obufp, 2
EXClip_NextPlane:
#------ 頂点が無くなったら終了する ------
#
# obufp が clipbuf に到達しないのは頂点が 3 個未満の時
#
sub sys0, obufp, clipbuf
bltz sys0, Clip_EX_Return
#------ 次のクリップ面へ ------
sh zero, RSP_SUBMOD_EX_CLIPBUF(obufp) # End Mark の設定
lhu v2, RSP_SUBMOD_EX_CLIPBUF-2(obufp) # 最終 Vtx の取得
bne plane, zero, EXClip_InitPlane
addi plane, plane, -4
EndAssign(num, 1)
EndAssign(src, 14)
EndAssign(dest, 15)
EndAssign(lstat, 13)
EndAssign(fogon, 7)
EndAssign(dest2, 8)
EndAssign(cflag, 10)
EndAssign(plane, 5)
EndAssign(clipmask, 9)
EndAssign(ccsave, 16)
EndAssign(ibufp, 17)
FixedAssign(v0, 1)
FixedAssign(vptr, v2) # gxsetup_ex.s で共用
FixedAssign(quart, v3) # gxsetup_ex.s で共用
FixedAssign(vtx1, v4) # gxsetup_ex.s で共用
#------ Setup ルーチンにおける Clip 判定を無効にする ------
#
# RSP_SUBMOD_CLIPTEST を 0 にすると Clip 処理が無効になる
# 有効にするには cliptest_save に保存しておいた値を書き戻す
#
sw zero, RSP_SUBMOD_EX_CLIPTEST(zero) # 0 クリア
#------ クリップ処理後の 3 角形の描画 ------
Clip_EX_Draw: lhu v0, RSP_SUBMOD_EX_CLIPBUF-6(clipbuf)
lhu v1, RSP_SUBMOD_EX_CLIPBUF-4(clipbuf)
lhu v2, RSP_SUBMOD_EX_CLIPBUF-2(obufp)
mtc2 v0, vptr[10] vor quart, vzero, _0x4000
mtc2 v1, vtx1[12]
jal Setup_EX_Clipped
mtc2 v2, vptr[14]
bne obufp, clipbuf, Clip_EX_Draw
addi clipbuf, clipbuf, 2
#------ Setup ルーチンにおける Clip 判定を有効にする ------
Clip_EX_Return: jr return_save
sw cliptest_save, RSP_SUBMOD_EX_CLIPTEST(zero)
EndAssign(v0, 1) # gxsetup_ex.s で共用
EndAssign(v1, 2) # gxsetup_ex.s で共用
EndAssign(v2, 3) # gxsetup_ex.s で共用
EndAssign(flat, 4) # gxsetup_ex.s で共用
EndAssign(clipbuf, 18)
EndAssign(obufp, 21)
EndAssign(cliptest_save, 29)
EndAssign(return_save, 30)
EndAssign(vptr, v2) # gxsetup_ex.s で共用
EndAssign(quart, v3) # gxsetup_ex.s で共用
EndAssign(vtx1, v4) # gxsetup_ex.s で共用
/*======== End of gxclip_ex.s ========*/