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