1 /*
2 * Glide64 - Glide video plugin for Nintendo 64 emulators.
3 * Copyright (c) 2002 Dave2001
4 * Copyright (c) 2003-2009 Sergey 'Gonetz' Lipski
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 //****************************************************************
22 //
23 // Glide64 - Glide Plugin for Nintendo 64 emulators
24 // Project started on December 29th, 2001
25 //
26 // Authors:
27 // Dave2001, original author, founded the project in 2001, left it in 2002
28 // Gugaman, joined the project in 2002, left it in 2002
29 // Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
30 // Hiroshi 'KoolSmoky' Morii, joined the project in 2007
31 //
32 //****************************************************************
33 //
34 // To modify Glide64:
35 // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
36 // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
37 //
38 //****************************************************************
39 //
40 // December 2008 Created by Gonetz (Gonetz@ngs.ru)
41 //
42 //****************************************************************
43
44 #include <stdint.h>
45
46 #include "../../Graphics/HLE/Microcode/ZSort.h"
47 #include "../../Graphics/RSP/gSP_state.h"
48
49 ZSORTRDP zSortRdp = {{0, 0}, {0, 0}, 0, 0};
50
uc9_draw_object(uint8_t * addr,uint32_t type)51 static void uc9_draw_object (uint8_t * addr, uint32_t type)
52 {
53 uint32_t i;
54 VERTEX vtx[4], *pV[4];
55 uint32_t textured = 0;
56 uint32_t vnum = 0;
57 uint32_t vsize = 0;
58
59 switch (type)
60 {
61 case ZH_NULL:
62 break;
63 case ZH_SHTRI:
64 vnum = 3;
65 vsize = 8;
66 break;
67 case ZH_TXTRI:
68 textured = 1;
69 vnum = 3;
70 vsize = 16;
71 break;
72 case ZH_SHQUAD:
73 vnum = 4;
74 vsize = 8;
75 break;
76 case ZH_TXQUAD:
77 textured = 1;
78 vnum = 4;
79 vsize = 16;
80 break;
81 }
82
83 for (i = 0; i < vnum; i++)
84 {
85 VERTEX *v = (VERTEX*)&vtx[i];
86 v->sx = zSortRdp.scale_x * ((int16_t*)addr)[0^1];
87 v->sy = zSortRdp.scale_y * ((int16_t*)addr)[1^1];
88 v->sz = 1.0f;
89 v->r = addr[4^3];
90 v->g = addr[5^3];
91 v->b = addr[6^3];
92 v->a = addr[7^3];
93 v->flags = 0;
94 v->uv_scaled = 0;
95 v->uv_calculated = 0xFFFFFFFF;
96 v->shade_mod = 0;
97 v->scr_off = 0;
98 v->screen_translated = 2;
99 v->oow = 1.0f;
100 v->w = 1.0f;
101
102 if (textured)
103 {
104 v->ou = ((int16_t*)addr)[4^1];
105 v->ov = ((int16_t*)addr)[5^1];
106 v->w = ZSort_Calc_invw(((int*)addr)[3]) / 31.0f;
107 v->oow = 1.0f / v->w;
108 }
109 addr += vsize;
110 }
111
112 pV[0] = &vtx[0];
113 pV[1] = &vtx[1];
114 pV[2] = &vtx[2];
115 pV[3] = &vtx[3];
116
117 cull_trianglefaces(pV, 1, false, false, 0);
118
119 if (vnum != 3)
120 cull_trianglefaces(pV + 1, 1, false, false, 0);
121 }
122
uc9_load_object(uint32_t zHeader,uint32_t * rdpcmds)123 static uint32_t uc9_load_object (uint32_t zHeader, uint32_t * rdpcmds)
124 {
125 uint32_t w0 = __RSP.w0;
126 uint32_t w1 = __RSP.w1;
127 uint32_t type = zHeader & 7;
128 uint8_t *addr = gfx_info.RDRAM + (zHeader&0xFFFFFFF8);
129
130 switch (type)
131 {
132 case ZH_SHTRI:
133 case ZH_SHQUAD:
134 __RSP.w1 = ((uint32_t*)addr)[1];
135 if (__RSP.w1 != rdpcmds[0])
136 {
137 rdpcmds[0] = __RSP.w1;
138 uc9_rpdcmd(w0, w1);
139 }
140 update();
141 uc9_draw_object(addr + 8, type);
142 break;
143 case ZH_NULL:
144 case ZH_TXTRI:
145 case ZH_TXQUAD:
146 __RSP.w1 = ((uint32_t*)addr)[1];
147 if (__RSP.w1 != rdpcmds[0])
148 {
149 rdpcmds[0] = __RSP.w1;
150 uc9_rpdcmd(w0, w1);
151 }
152 __RSP.w1 = ((uint32_t*)addr)[2];
153 if (__RSP.w1 != rdpcmds[1])
154 {
155 uc9_rpdcmd(w0, w1);
156 rdpcmds[1] = __RSP.w1;
157 }
158 __RSP.w1 = ((uint32_t*)addr)[3];
159 if (__RSP.w1 != rdpcmds[2])
160 {
161 uc9_rpdcmd(w0, w1);
162 rdpcmds[2] = __RSP.w1;
163 }
164 if (type)
165 {
166 update();
167 uc9_draw_object(addr + 16, type);
168 }
169 break;
170 }
171 return RSP_SegmentToPhysical(((uint32_t*)addr)[0]);
172 }
173
uc9_object(uint32_t w0,uint32_t w1)174 static void uc9_object(uint32_t w0, uint32_t w1)
175 {
176 uint32_t cmd1, zHeader;
177 uint32_t rdpcmds[3];
178
179 rdpcmds[0] = 0;
180 rdpcmds[1] = 0;
181 rdpcmds[2] = 0;
182
183 cmd1 = w1;
184 zHeader = RSP_SegmentToPhysical(w0);
185
186 while (zHeader)
187 zHeader = uc9_load_object(zHeader, rdpcmds);
188 zHeader = RSP_SegmentToPhysical(cmd1);
189 while (zHeader)
190 zHeader = uc9_load_object(zHeader, rdpcmds);
191 }
192
uc9_mix(uint32_t w0,uint32_t w1)193 static void uc9_mix(uint32_t w0, uint32_t w1)
194 {
195 }
196
uc9_fmlight(uint32_t w0,uint32_t w1)197 static void uc9_fmlight(uint32_t w0, uint32_t w1)
198 {
199 uint32_t i;
200 M44 *m;
201 int mid = w0 & 0xFF;
202 uint32_t a = -1024 + (w1 & 0xFFF);
203
204 glide64gSPNumLights(1 + _SHIFTR(w1, 12, 8));
205
206 switch (mid)
207 {
208 case 4:
209 m = (M44*)rdp.model;
210 break;
211 case 6:
212 m = (M44*)rdp.proj;
213 break;
214 case 8:
215 m = (M44*)rdp.combined;
216 break;
217 }
218
219 rdp.light[gSP.numLights].col[0] = (float)(((uint8_t*)gfx_info.DMEM)[(a+0)^3]) / 255.0f;
220 rdp.light[gSP.numLights].col[1] = (float)(((uint8_t*)gfx_info.DMEM)[(a+1)^3]) / 255.0f;
221 rdp.light[gSP.numLights].col[2] = (float)(((uint8_t*)gfx_info.DMEM)[(a+2)^3]) / 255.0f;
222 rdp.light[gSP.numLights].col[3] = 1.0f;
223 //FRDP ("ambient light: r: %.3f, g: %.3f, b: %.3f\n", rdp.light[gSP.numLights].r, rdp.light[gSP.numLights].g, rdp.light[gSP.numLights].b);
224 a += 8;
225
226 for (i = 0; i < gSP.numLights; i++)
227 {
228 rdp.light[i].col[0] = (float)(((uint8_t*)gfx_info.DMEM)[(a+0)^3]) / 255.0f;
229 rdp.light[i].col[1] = (float)(((uint8_t*)gfx_info.DMEM)[(a+1)^3]) / 255.0f;
230 rdp.light[i].col[2] = (float)(((uint8_t*)gfx_info.DMEM)[(a+2)^3]) / 255.0f;
231 rdp.light[i].col[3] = 1.0f;
232 rdp.light[i].dir[0] = (float)(((int8_t*)gfx_info.DMEM)[(a+8)^3]) / 127.0f;
233 rdp.light[i].dir[1] = (float)(((int8_t*)gfx_info.DMEM)[(a+9)^3]) / 127.0f;
234 rdp.light[i].dir[2] = (float)(((int8_t*)gfx_info.DMEM)[(a+10)^3]) / 127.0f;
235 //FRDP ("light: n: %d, r: %.3f, g: %.3f, b: %.3f, x: %.3f, y: %.3f, z: %.3f\n", i, rdp.light[i].r, rdp.light[i].g, rdp.light[i].b, rdp.light[i].dir_x, rdp.light[i].dir_y, rdp.light[i].dir_z);
236 InverseTransformVector(&rdp.light[i].dir[0], rdp.light_vector[i], *m);
237 NormalizeVector (rdp.light_vector[i]);
238 //FRDP ("light vector: n: %d, x: %.3f, y: %.3f, z: %.3f\n", i, rdp.light_vector[i][0], rdp.light_vector[i][1], rdp.light_vector[i][2]);
239 a += 24;
240 }
241
242 for (i = 0; i < 2; i++)
243 {
244 float dir_x = (float)(((int8_t*)gfx_info.DMEM)[(a+8)^3]) / 127.0f;
245 float dir_y = (float)(((int8_t*)gfx_info.DMEM)[(a+9)^3]) / 127.0f;
246 float dir_z = (float)(((int8_t*)gfx_info.DMEM)[(a+10)^3]) / 127.0f;
247 if (sqrt(dir_x*dir_x + dir_y*dir_y + dir_z*dir_z) < 0.98)
248 {
249 gSP.lookatEnable = false;
250 return;
251 }
252 rdp.lookat[i][0] = dir_x;
253 rdp.lookat[i][1] = dir_y;
254 rdp.lookat[i][2] = dir_z;
255 a += 24;
256 }
257 gSP.lookatEnable = true;
258 }
259
uc9_light(uint32_t w0,uint32_t w1)260 static void uc9_light(uint32_t w0, uint32_t w1)
261 {
262 VERTEX v;
263 uint32_t i;
264 uint32_t csrs = -1024 + ((w0 >> 12) & 0xFFF);
265 uint32_t nsrs = -1024 + (w0 & 0xFFF);
266 uint32_t num = 1 + ((w1 >> 24) & 0xFF);
267 uint32_t cdest = -1024 + ((w1 >> 12) & 0xFFF);
268 uint32_t tdest = -1024 + (w1 & 0xFFF);
269 int use_material = (csrs != 0x0ff0);
270 tdest >>= 1;
271
272 for (i = 0; i < num; i++)
273 {
274 v.vec[0] = ((int8_t*)gfx_info.DMEM)[(nsrs++)^3];
275 v.vec[1] = ((int8_t*)gfx_info.DMEM)[(nsrs++)^3];
276 v.vec[2] = ((int8_t*)gfx_info.DMEM)[(nsrs++)^3];
277
278 calc_sphere (&v);
279
280 NormalizeVector (v.vec);
281 glide64gSPLightVertex(&v);
282
283 v.a = 0xFF;
284
285 if (use_material)
286 {
287 v.r = (uint8_t)(((uint32_t)v.r * gfx_info.DMEM[(csrs++)^3]) >> 8);
288 v.g = (uint8_t)(((uint32_t)v.g * gfx_info.DMEM[(csrs++)^3]) >> 8);
289 v.b = (uint8_t)(((uint32_t)v.b * gfx_info.DMEM[(csrs++)^3]) >> 8);
290 v.a = gfx_info.DMEM[(csrs++)^3];
291 }
292 gfx_info.DMEM[(cdest++)^3] = v.r;
293 gfx_info.DMEM[(cdest++)^3] = v.g;
294 gfx_info.DMEM[(cdest++)^3] = v.b;
295 gfx_info.DMEM[(cdest++)^3] = v.a;
296 ((int16_t*)gfx_info.DMEM)[(tdest++)^1] = (int16_t)v.ou;
297 ((int16_t*)gfx_info.DMEM)[(tdest++)^1] = (int16_t)v.ov;
298 }
299 }
300
uc9_mtxtrnsp(uint32_t w0,uint32_t w1)301 static void uc9_mtxtrnsp(uint32_t w0, uint32_t w1)
302 {
303 /*
304 M44 *s;
305 switch (w1 & 0xF)
306 {
307 case 4:
308 s = (M44*)rdp.model;
309 LRDP("Model\n");
310 break;
311 case 6:
312 s = (M44*)rdp.proj;
313 LRDP("Proj\n");
314 break;
315 case 8:
316 s = (M44*)rdp.combined;
317 LRDP("Comb\n");
318 break;
319 }
320 float m = *s[1][0];
321 *s[1][0] = *s[0][1];
322 *s[0][1] = m;
323 m = *s[2][0];
324 *s[2][0] = *s[0][2];
325 *s[0][2] = m;
326 m = *s[2][1];
327 *s[2][1] = *s[1][2];
328 *s[1][2] = m;
329 */
330 }
331
uc9_mtxcat(uint32_t w0,uint32_t w1)332 static void uc9_mtxcat(uint32_t w0, uint32_t w1)
333 {
334 M44 *s;
335 M44 *t;
336 DECLAREALIGN16VAR(m[4][4]);
337 uint32_t S = w0 & 0xF;
338 uint32_t T = (w1 >> 16) & 0xF;
339 uint32_t D = w1 & 0xF;
340
341 switch (S)
342 {
343 case 4:
344 s = (M44*)rdp.model;
345 LRDP("Model * ");
346 break;
347 case 6:
348 s = (M44*)rdp.proj;
349 LRDP("Proj * ");
350 break;
351 case 8:
352 s = (M44*)rdp.combined;
353 LRDP("Comb * ");
354 break;
355 }
356
357 switch (T)
358 {
359 case 4:
360 t = (M44*)rdp.model;
361 LRDP("Model -> ");
362 break;
363 case 6:
364 t = (M44*)rdp.proj;
365 LRDP("Proj -> ");
366 break;
367 case 8:
368 LRDP("Comb -> ");
369 t = (M44*)rdp.combined;
370 break;
371 }
372 MulMatrices(*s, *t, m);
373
374 switch (D)
375 {
376 case 4:
377 CopyMatrix(rdp.model, m);
378 break;
379 case 6:
380 CopyMatrix(rdp.proj, m);
381 break;
382 case 8:
383 CopyMatrix(rdp.combined, m);
384 break;
385 }
386 }
387
388 typedef struct
389 {
390 int16_t sy;
391 int16_t sx;
392 int invw;
393 int16_t yi;
394 int16_t xi;
395 int16_t wi;
396 uint8_t fog;
397 uint8_t cc;
398 } zSortVDest;
399
uc9_mult_mpmtx(uint32_t w0,uint32_t w1)400 static void uc9_mult_mpmtx(uint32_t w0, uint32_t w1)
401 {
402 int i, idx, num, src, dst;
403 int16_t *saddr;
404 zSortVDest v, *daddr;
405 num = 1+ ((w1 >> 24) & 0xFF);
406 src = -1024 + ((w1 >> 12) & 0xFFF);
407 dst = -1024 + (w1 & 0xFFF);
408 FRDP ("uc9:mult_mpmtx from: %04lx to: %04lx n: %d\n", src, dst, num);
409 saddr = (int16_t*)(gfx_info.DMEM+src);
410 daddr = (zSortVDest*)(gfx_info.DMEM+dst);
411 idx = 0;
412 memset(&v, 0, sizeof(zSortVDest));
413 //float scale_x = 4.0f/rdp.scale_x;
414 //float scale_y = 4.0f/rdp.scale_y;
415 for (i = 0; i < num; i++)
416 {
417 int16_t sx = saddr[(idx++)^1];
418 int16_t sy = saddr[(idx++)^1];
419 int16_t sz = saddr[(idx++)^1];
420 float x = sx*rdp.combined[0][0] + sy*rdp.combined[1][0] + sz*rdp.combined[2][0] + rdp.combined[3][0];
421 float y = sx*rdp.combined[0][1] + sy*rdp.combined[1][1] + sz*rdp.combined[2][1] + rdp.combined[3][1];
422 float z = sx*rdp.combined[0][2] + sy*rdp.combined[1][2] + sz*rdp.combined[2][2] + rdp.combined[3][2];
423 float w = sx*rdp.combined[0][3] + sy*rdp.combined[1][3] + sz*rdp.combined[2][3] + rdp.combined[3][3];
424 v.sx = (int16_t)(zSortRdp.view_trans[0] + x / w * zSortRdp.view_scale[0]);
425 v.sy = (int16_t)(zSortRdp.view_trans[1] + y / w * zSortRdp.view_scale[1]);
426
427 v.xi = (int16_t)x;
428 v.yi = (int16_t)y;
429 v.wi = (int16_t)w;
430 v.invw = ZSort_Calc_invw((int)(w * 31.0));
431
432 if (w < 0.0f)
433 v.fog = 0;
434 else
435 {
436 int fog = (int)(z / w * gSP.fog.multiplier + gSP.fog.offset);
437 if (fog > 255)
438 fog = 255;
439 v.fog = (fog >= 0) ? (uint8_t)fog : 0;
440 }
441
442 v.cc = 0;
443 if (x < -w)
444 v.cc |= Z_CLIP_MAX;
445 if (x > w)
446 v.cc |= X_CLIP_MAX;
447 if (y < -w)
448 v.cc |= Z_CLIP_MIN;
449 if (y > w)
450 v.cc |= X_CLIP_MIN;
451 if (w < 0.1f)
452 v.cc |= Y_CLIP_MAX;
453
454 daddr[i] = v;
455 }
456 }
457
uc9_link_subdl(uint32_t w0,uint32_t w1)458 static void uc9_link_subdl(uint32_t w0, uint32_t w1)
459 {
460 }
461
uc9_set_subdl(uint32_t w0,uint32_t w1)462 static void uc9_set_subdl(uint32_t w0, uint32_t w1)
463 {
464 }
465
uc9_wait_signal(uint32_t w0,uint32_t w1)466 static void uc9_wait_signal(uint32_t w0, uint32_t w1)
467 {
468 }
469
uc9_send_signal(uint32_t w0,uint32_t w1)470 static void uc9_send_signal(uint32_t w0, uint32_t w1)
471 {
472 }
473
uc9_movemem(uint32_t w0,uint32_t w1)474 static void uc9_movemem(uint32_t w0, uint32_t w1)
475 {
476 int idx = w0 & 0x0E;
477 int ofs = ((w0 >> 6) & 0x1ff)<<3;
478 int len = (1 + ((w0 >> 15) & 0x1ff))<<3;
479 int flag = w0 & 0x01;
480 uint32_t addr = RSP_SegmentToPhysical(w1);
481
482 switch (idx)
483 {
484 case GZF_LOAD:
485 if (flag == 0)
486 {
487 int dmem_addr = (idx<<3) + ofs;
488 memcpy(gfx_info.DMEM + dmem_addr, gfx_info.RDRAM + addr, len);
489 }
490 else
491 {
492 int dmem_addr = (idx<<3) + ofs;
493 memcpy(gfx_info.RDRAM + addr, gfx_info.DMEM + dmem_addr, len);
494 }
495 break;
496
497 case GZM_MMTX:
498 case GZM_PMTX:
499 case GZM_MPMTX:
500 {
501 DECLAREALIGN16VAR(m[4][4]);
502 load_matrix(m, addr);
503 switch (idx)
504 {
505 case GZM_MMTX:
506 modelview_load (m);
507 break;
508 case GZM_PMTX:
509 projection_load (m);
510 break;
511 case GZM_MPMTX:
512 LRDP("Combined load\n");
513 g_gdp.flags &= ~UPDATE_MULT_MAT;
514 CopyMatrix(rdp.combined, m);
515 break;
516 }
517 }
518 break;
519
520 case GZM_OTHERMODE:
521 LRDP("Othermode - IGNORED\n");
522 break;
523
524 case GZM_VIEWPORT:
525 {
526 uint32_t a = addr >> 1;
527 int16_t scale_x = ((int16_t*)gfx_info.RDRAM)[(a+0)^1] >> 2;
528 int16_t scale_y = ((int16_t*)gfx_info.RDRAM)[(a+1)^1] >> 2;
529 int16_t scale_z = ((int16_t*)gfx_info.RDRAM)[(a+2)^1];
530 int16_t trans_x = ((int16_t*)gfx_info.RDRAM)[(a+4)^1] >> 2;
531 int16_t trans_y = ((int16_t*)gfx_info.RDRAM)[(a+5)^1] >> 2;
532 int16_t trans_z = ((int16_t*)gfx_info.RDRAM)[(a+6)^1];
533
534 glide64gSPFogFactor(
535 ((int16_t*)gfx_info.RDRAM)[(a+3)^1], /* fm */
536 ((int16_t*)gfx_info.RDRAM)[(a+7)^1] /* fo */
537 );
538
539 gSP.viewport.vscale[0] = scale_x * rdp.scale_x;
540 gSP.viewport.vscale[1] = scale_y * rdp.scale_y;
541 gSP.viewport.vscale[2] = 32.0f * scale_z;
542 gSP.viewport.vtrans[0] = trans_x * rdp.scale_x;
543 gSP.viewport.vtrans[1] = trans_y * rdp.scale_y;
544 gSP.viewport.vtrans[2] = 32.0f * trans_z;
545
546 zSortRdp.view_scale[0] = (float)(scale_x*4);
547 zSortRdp.view_scale[1] = (float)(scale_y*4);
548 zSortRdp.view_trans[0] = (float)(trans_x*4);
549 zSortRdp.view_trans[1] = (float)(trans_y*4);
550 zSortRdp.scale_x = rdp.scale_x / 4.0f;
551 zSortRdp.scale_y = rdp.scale_y / 4.0f;
552
553 g_gdp.flags |= UPDATE_VIEWPORT;
554
555 glide64gSPTexture(
556 0xFFFF, /* sc */
557 0xFFFF, /* tc */
558 0, /* level */
559 0, /* tile */
560 1 /* on */
561 );
562
563 glide64gSPSetGeometryMode(0x0200);
564
565 FRDP ("viewport scale(%d, %d, %d), trans(%d, %d, %d), from:%08lx\n", scale_x, scale_y, scale_z,
566 trans_x, trans_y, trans_z, a);
567 FRDP ("fog: multiplier: %f, offset: %f\n", gSP.fog.multiplier, gSP.fog.offset);
568 }
569 break;
570
571 default:
572 FRDP ("** UNKNOWN %d\n", idx);
573 }
574 }
575
uc9_setscissor(uint32_t w0,uint32_t w1)576 static void uc9_setscissor(uint32_t w0, uint32_t w1)
577 {
578 rdp_setscissor(w0, w1);
579
580 if ((g_gdp.__clip.xl - g_gdp.__clip.xh) > (zSortRdp.view_scale[0] - zSortRdp.view_trans[0]))
581 {
582 float w = (g_gdp.__clip.xl - g_gdp.__clip.xh) / 2.0f;
583 float h = (g_gdp.__clip.yl - g_gdp.__clip.yh) / 2.0f;
584
585 gSP.viewport.vscale[0] = w * rdp.scale_x;
586 gSP.viewport.vscale[1] = h * rdp.scale_y;
587 gSP.viewport.vtrans[0] = w * rdp.scale_x;
588 gSP.viewport.vtrans[1] = h * rdp.scale_y;
589
590 zSortRdp.view_scale[0] = w * 4.0f;
591 zSortRdp.view_scale[1] = h * 4.0f;
592 zSortRdp.view_trans[0] = w * 4.0f;
593 zSortRdp.view_trans[1] = h * 4.0f;
594 zSortRdp.scale_x = rdp.scale_x / 4.0f;
595 zSortRdp.scale_y = rdp.scale_y / 4.0f;
596
597 g_gdp.flags |= UPDATE_VIEWPORT;
598
599 glide64gSPTexture(
600 0xFFFF, /* sc */
601 0xFFFF, /* tc */
602 0, /* level */
603 0, /* tile */
604 1 /* on */
605 );
606
607 glide64gSPSetGeometryMode(0x0200);
608 }
609 }
610