gflight.s
7.6 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
##########################################################################
#
# Vertex Lighting Routine
#
# When entering this code we have already loaded the overlay. To see how
# overlay loading works, please see the comments in goverlays.s
#
##########################################################################
#### 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
ori tmp, zero, RSP_SCRATCH_OFFSET
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
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