Replace Tmem_nasm.asm with C++ code. Patch by pyro.
[Glide64.git] / ucode06.h
blobe85d8f9d7c5cec24c4993b218e489a2de0f3943b
1 /*
2 * Glide64 - Glide video plugin for Nintendo 64 emulators.
3 * Copyright (c) 2002 Dave2001
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 //****************************************************************
22 // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64)
23 // Project started on December 29th, 2001
25 // To modify Glide64:
26 // * 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.
27 // * 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.
29 // Official Glide64 development channel: #Glide64 on EFnet
31 // Original author: Dave2001 (Dave2999@hotmail.com)
32 // Other authors: Gonetz, Gugaman
34 //****************************************************************
36 //****************************************************************
38 // STANDARD DRAWIMAGE - draws a 2d image based on the following structure
40 void uc6_sprite2d ();
42 typedef struct DRAWIMAGE_t {
43 float frameX;
44 float frameY;
45 WORD frameW;
46 WORD frameH;
47 WORD imageX;
48 WORD imageY;
49 WORD imageW;
50 WORD imageH;
51 DWORD imagePtr;
52 BYTE imageFmt;
53 BYTE imageSiz;
54 WORD imagePal;
55 BYTE flipX;
56 BYTE flipY;
57 float scaleX;
58 float scaleY;
59 } DRAWIMAGE;
61 void DrawHiresDepthImage (DRAWIMAGE *d)
63 WORD * src = (WORD*)(gfx.RDRAM+d->imagePtr);
64 WORD image[512*512];
65 WORD * dst = image;
66 for (int h = 0; h < d->imageH; h++)
68 for (int w = 0; w < d->imageW; w++)
70 *(dst++) = src[(w+h*d->imageW)^1];
72 dst += (512 - d->imageW);
74 GrTexInfo t_info;
75 t_info.format = GR_TEXFMT_RGB_565;
76 t_info.data = image;
77 t_info.smallLodLog2 = GR_LOD_LOG2_512;
78 t_info.largeLodLog2 = GR_LOD_LOG2_512;
79 t_info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
81 grTexDownloadMipMap (rdp.texbufs[1].tmu,
82 rdp.texbufs[1].begin,
83 GR_MIPMAPLEVELMASK_BOTH,
84 &t_info);
85 grTexSource (rdp.texbufs[1].tmu,
86 rdp.texbufs[1].begin,
87 GR_MIPMAPLEVELMASK_BOTH,
88 &t_info);
89 grTexCombine( GR_TMU1,
90 GR_COMBINE_FUNCTION_LOCAL,
91 GR_COMBINE_FACTOR_NONE,
92 GR_COMBINE_FUNCTION_LOCAL,
93 GR_COMBINE_FACTOR_NONE,
94 FXFALSE,
95 FXFALSE );
96 grTexCombine( GR_TMU0,
97 GR_COMBINE_FUNCTION_SCALE_OTHER,
98 GR_COMBINE_FACTOR_ONE,
99 GR_COMBINE_FUNCTION_SCALE_OTHER,
100 GR_COMBINE_FACTOR_ONE,
101 FXFALSE,
102 FXFALSE );
103 grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
104 GR_COMBINE_FACTOR_ONE,
105 GR_COMBINE_LOCAL_NONE,
106 GR_COMBINE_OTHER_TEXTURE,
107 FXFALSE);
108 grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
109 GR_COMBINE_FACTOR_ONE,
110 GR_COMBINE_LOCAL_NONE,
111 GR_COMBINE_OTHER_TEXTURE,
112 FXFALSE);
113 grAlphaBlendFunction (GR_BLEND_ONE,
114 GR_BLEND_ZERO,
115 GR_BLEND_ONE,
116 GR_BLEND_ZERO);
117 grDepthBufferFunction (GR_CMP_ALWAYS);
118 grDepthMask (FXFALSE);
120 GrLOD_t LOD = GR_LOD_LOG2_1024;
121 if (settings.scr_res_x > 1024)
122 LOD = GR_LOD_LOG2_2048;
124 float lr_x = (float)d->imageW * rdp.scale_x;
125 float lr_y = (float)d->imageH * rdp.scale_y;
126 float lr_u = (float)d->imageW * 0.5f;// - 0.5f;
127 float lr_v = (float)d->imageH * 0.5f;// - 0.5f;
128 VERTEX v[4] = {
129 { 0, 0, 1.0f, 1.0f, 0, 0, 0, 0 },
130 { lr_x, 0, 1.0f, 1.0f, lr_u, 0, lr_u, 0 },
131 { 0, lr_y, 1.0f, 1.0f, 0, lr_v, 0, lr_v },
132 { lr_x, lr_y, 1.0f, 1.0f, lr_u, lr_v, lr_u, lr_v }
134 for (int i=0; i<4; i++)
136 v[i].uc(0) = v[i].uc(1) = v[i].u0;
137 v[i].vc(0) = v[i].vc(1) = v[i].v0;
139 grTextureBufferExt( rdp.texbufs[0].tmu, rdp.texbufs[0].begin, LOD, LOD,
140 GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH );
141 grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT );
142 grAuxBufferExt( GR_BUFFER_AUXBUFFER );
143 grSstOrigin(GR_ORIGIN_UPPER_LEFT);
144 grBufferClear (0, 0, 0xFFFF);
145 grDrawTriangle (&v[0], &v[2], &v[1]);
146 grDrawTriangle (&v[2], &v[3], &v[1]);
147 grRenderBuffer( GR_BUFFER_BACKBUFFER );
148 grTextureAuxBufferExt( rdp.texbufs[0].tmu, rdp.texbufs[0].begin, LOD, LOD,
149 GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH );
150 grAuxBufferExt( GR_BUFFER_TEXTUREAUXBUFFER_EXT );
151 grDepthMask (FXTRUE);
155 extern BOOL depthbuffersave;
156 void DrawDepthImage (DRAWIMAGE *d)
158 if (!fullscreen || !settings.fb_depth_render)
159 return;
160 if (d->imageH > d->imageW)
161 return;
162 RDP("Depth image write\n");
163 float scale_x_dst = rdp.scale_x;
164 float scale_y_dst = rdp.scale_y;
165 float scale_x_src = 1.0f/rdp.scale_x;
166 float scale_y_src = 1.0f/rdp.scale_y;
167 int src_width = d->imageW;
168 int src_height = d->imageH;
169 int dst_width = min(int(src_width*scale_x_dst), (int)settings.scr_res_x);
170 int dst_height = min(int(src_height*scale_y_dst), (int)settings.scr_res_y);
172 #if 1
173 if (0 && grFramebufferCopyExt) {
174 static unsigned int last;
175 unsigned int crc = CRC_Calculate(0, gfx.RDRAM+d->imagePtr,
176 d->imageW * d->imageH * 2);
177 printf("depth CRC %x\n", crc);
178 if (last == crc) {
179 // ZIGGY
180 // using special idiot setting FRONT-->FRONT so the wrapper knows what to
181 // do (i.e. delay actual copy until after next buffer clear)
182 // UGLY !!
183 grFramebufferCopyExt(0, 0, dst_width, dst_height,
184 GR_FBCOPY_BUFFER_FRONT, GR_FBCOPY_BUFFER_FRONT,
185 GR_FBCOPY_MODE_DEPTH);
186 depthbuffersave = TRUE;
187 return;
190 last = crc;
191 depthbuffersave = TRUE;
193 } else {
194 if (settings.fb_hires)
196 DrawHiresDepthImage(d);
197 return;
200 #endif
202 WORD * src = (WORD*)(gfx.RDRAM+d->imagePtr);
203 WORD * dst = new WORD[dst_width*dst_height];
205 for (int y=0; y < dst_height; y++)
207 for (int x=0; x < dst_width; x++)
209 dst[x+y*dst_width] = src[(int(x*scale_x_src)+int(y*scale_y_src)*src_width)^1];
212 grLfbWriteRegion(GR_BUFFER_AUXBUFFER,
215 GR_LFB_SRC_FMT_ZA16,
216 dst_width,
217 dst_height,
218 FXFALSE,
219 dst_width<<1,
220 dst);
221 delete[] dst;
224 void DrawImage (DRAWIMAGE *d)
226 if (d->imageW == 0 || d->imageH == 0 || d->frameH == 0) return;
228 int x_size;
229 int y_size;
230 int x_shift;
231 int y_shift;
232 int line;
234 // choose optimum size for the format/size
235 if (d->imageSiz == 0)
237 x_size = 128;
238 y_size = 64;
239 x_shift = 7;
240 y_shift = 6;
241 line = 8;
243 if (d->imageSiz == 1)
245 x_size = 64;
246 y_size = 64;
247 x_shift = 6;
248 y_shift = 6;
249 line = 8;
251 if (d->imageSiz == 2)
253 x_size = 64;
254 y_size = 32;
255 x_shift = 6;
256 y_shift = 5;
257 line = 16;
259 if (d->imageSiz == 3)
261 x_size = 32;
262 y_size = 16;
263 x_shift = 4;
264 y_shift = 3;
265 line = 16;
267 if (rdp.ci_width == 512 && !no_dlist) //RE2
269 WORD width = (WORD)(*gfx.VI_WIDTH_REG & 0xFFF);
270 d->frameH = d->imageH = (d->frameW*d->frameH)/width;
271 d->frameW = d->imageW = width;
272 if (rdp.zimg == rdp.cimg)
274 DrawDepthImage(d);
275 rdp.update |= UPDATE_ZBUF_ENABLED | UPDATE_COMBINE |
276 UPDATE_ALPHA_COMPARE | UPDATE_VIEWPORT;
277 return;
280 if (d->imageW%2 == 1) d->imageW -= 1;
281 if (d->imageH%2 == 1) d->imageH -= 1;
282 if (d->imageY > d->imageH) d->imageY = (d->imageY%d->imageH);
283 // if (d->imageX > d->imageW) d->imageX = (d->imageX%d->imageW);
285 if (!settings.PPL)
287 if ( (d->frameX > 0) && (d->frameW == rdp.ci_width) )
288 d->frameW -= (WORD)(2.0f*d->frameX);
289 if ( (d->frameY > 0) && (d->frameH == rdp.ci_height) )
290 d->frameH -= (WORD)(2.0f*d->frameY);
293 int ul_u = (int)d->imageX;
294 int ul_v = (int)d->imageY;
295 int lr_u = (int)d->imageX + (int)(d->frameW * d->scaleX);
296 int lr_v = (int)d->imageY + (int)(d->frameH * d->scaleY);
298 float ul_x, ul_y, lr_x, lr_y;
299 if (d->flipX)
301 ul_x = d->frameX + d->frameW;
302 lr_x = d->frameX;
304 else
306 ul_x = d->frameX;
307 lr_x = d->frameX + d->frameW;
309 if (d->flipY)
311 ul_y = d->frameY + d->frameH;
312 lr_y = d->frameY;
314 else
316 ul_y = d->frameY;
317 lr_y = d->frameY + d->frameH;
320 int min_wrap_u = ul_u / d->imageW;
321 //int max_wrap_u = lr_u / d->wrapW;
322 int min_wrap_v = ul_v / d->imageH;
323 //int max_wrap_v = lr_v / d->wrapH;
324 int min_256_u = ul_u >> x_shift;
325 //int max_256_u = (lr_u-1) >> x_shift;
326 int min_256_v = ul_v >> y_shift;
327 //int max_256_v = (lr_v-1) >> y_shift;
330 // SetTextureImage ()
331 rdp.timg.format = d->imageFmt; // RGBA
332 rdp.timg.size = d->imageSiz; // 16-bit
333 rdp.timg.addr = d->imagePtr;
334 rdp.timg.width = d->imageW;
335 rdp.timg.set_by = 0;
337 // SetTile ()
338 TILE *tile = &rdp.tiles[0];
339 tile->format = d->imageFmt; // RGBA
340 tile->size = d->imageSiz; // 16-bit
341 tile->line = line;
342 tile->t_mem = 0;
343 tile->palette = (BYTE)d->imagePal;
344 tile->clamp_t = 1;
345 tile->mirror_t = 0;
346 tile->mask_t = 0;
347 tile->shift_t = 0;
348 tile->clamp_s = 1;
349 tile->mirror_s = 0;
350 tile->mask_s = 0;
351 tile->shift_s = 0;
353 rdp.tiles[0].ul_s = 0;
354 rdp.tiles[0].ul_t = 0;
355 rdp.tiles[0].lr_s = x_size-1;
356 rdp.tiles[0].lr_t = y_size-1;
358 if (rdp.cycle_mode == 2)
360 rdp.allow_combine = 0;
361 rdp.update &= ~UPDATE_TEXTURE;
363 update (); // note: allow loading of texture
365 float Z = 1.0f;
367 if (fullscreen)
370 //grFogMode (GR_FOG_DISABLE);
372 grFogMode (GR_FOG_DISABLE);
373 if (rdp.zsrc == 1 && (rdp.othermode_l & 0x00000030)) // othermode check makes sure it
374 // USES the z-buffer. Otherwise it returns bad (unset) values for lot and telescope
375 //in zelda:mm.
377 RDP("Background uses depth compare\n");
378 Z = ScaleZ(rdp.prim_depth);
379 grDepthBufferFunction (GR_CMP_LEQUAL);
380 grDepthMask (FXTRUE);
382 else
384 RDP("Background not uses depth compare\n");
385 grDepthBufferFunction (GR_CMP_ALWAYS);
386 grDepthMask (FXFALSE);
389 // grClipWindow (0, 0, settings.res_x, settings.res_y);
390 if (rdp.ci_width == 512 && !no_dlist)
391 // grClipWindow (0, 0, (DWORD)(d->frameW * rdp.scale_x), (DWORD)(d->frameH * rdp.scale_y));
392 grClipWindow (0, 0, settings.scr_res_x, settings.scr_res_y);
393 else
394 grClipWindow (rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x, rdp.scissor.lr_y);
396 grCullMode (GR_CULL_DISABLE);
397 // if (!settings.PPL)
398 if (rdp.cycle_mode == 2)
400 rdp.allow_combine = 0;
401 cmb.tmu0_func = GR_COMBINE_FUNCTION_LOCAL;
402 cmb.tmu0_a_func = GR_COMBINE_FUNCTION_LOCAL;
404 grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
405 GR_COMBINE_FACTOR_ONE,
406 GR_COMBINE_LOCAL_NONE,
407 GR_COMBINE_OTHER_TEXTURE,
408 FXFALSE);
409 grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
410 GR_COMBINE_FACTOR_ONE,
411 GR_COMBINE_LOCAL_NONE,
412 GR_COMBINE_OTHER_TEXTURE,
413 FXFALSE);
414 grConstantColorValue (0xFFFFFFFF);
415 grAlphaBlendFunction (GR_BLEND_ONE, // use alpha compare, but not T0 alpha
416 GR_BLEND_ZERO,
417 GR_BLEND_ZERO,
418 GR_BLEND_ZERO);
419 rdp.update |= UPDATE_COMBINE;
423 // Texture ()
424 rdp.cur_tile = 0;
425 rdp.tex = 1;
427 float nul_x, nul_y, nlr_x, nlr_y;
428 int nul_u, nul_v, nlr_u, nlr_v;
429 float ful_u, ful_v, flr_u, flr_v;
430 float ful_x, ful_y, flr_x, flr_y;
432 float mx = (float)(lr_x - ul_x) / (float)(lr_u - ul_u);
433 float bx = ul_x - mx * ul_u;
435 float my = (float)(lr_y - ul_y) / (float)(lr_v - ul_v);
436 float by = ul_y - my * ul_v;
438 int cur_wrap_u, cur_wrap_v, cur_u, cur_v;
439 int cb_u, cb_v; // coordinate-base
440 int tb_u, tb_v; // texture-base
442 nul_v = ul_v;
443 nul_y = ul_y;
445 // #162
447 cur_wrap_v = min_wrap_v + 1;
448 cur_v = min_256_v + 1;
449 cb_v = ((cur_v-1)<<y_shift);
450 while (cb_v >= d->imageH) cb_v -= d->imageH;
451 tb_v = cb_v;
453 while (1)
455 cur_wrap_u = min_wrap_u + 1 + 1024; // x wrapping is not required
456 cur_u = min_256_u + 1;
458 // calculate intersection with this point
459 nlr_v = min (min (cur_wrap_v*d->imageH, (cur_v<<y_shift)), lr_v);
460 nlr_y = my * nlr_v + by;
462 nul_u = ul_u;
463 nul_x = ul_x;
464 cb_u = ((cur_u-1)<<x_shift);
465 while (cb_u >= d->imageW) cb_u -= d->imageW;
466 tb_u = cb_u;
468 while (1)
470 // calculate intersection with this point
471 nlr_u = min (min (cur_wrap_u*d->imageW, (cur_u<<x_shift)), lr_u);
472 nlr_x = mx * nlr_u + bx;
474 // ** Load the texture, constant portions have been set above
475 // SetTileSize ()
476 rdp.tiles[0].ul_s = tb_u;
477 rdp.tiles[0].ul_t = tb_v;
478 rdp.tiles[0].lr_s = tb_u+x_size-1;
479 rdp.tiles[0].lr_t = tb_v+y_size-1;
481 // LoadTile ()
482 rdp.cmd0 = ((int)rdp.tiles[0].ul_s << 14) | ((int)rdp.tiles[0].ul_t << 2);
483 rdp.cmd1 = ((int)rdp.tiles[0].lr_s << 14) | ((int)rdp.tiles[0].lr_t << 2);
484 rdp_loadtile ();
486 TexCache ();
487 // **
489 ful_u = (float)nul_u - cb_u;
490 flr_u = (float)nlr_u - cb_u;
491 ful_v = (float)nul_v - cb_v;
492 flr_v = (float)nlr_v - cb_v;
494 ful_u *= rdp.cur_cache[0]->scale;
495 ful_v *= rdp.cur_cache[0]->scale;
496 flr_u *= rdp.cur_cache[0]->scale;
497 flr_v *= rdp.cur_cache[0]->scale;
499 ful_x = nul_x * rdp.scale_x;
500 flr_x = nlr_x * rdp.scale_x;
501 ful_y = nul_y * rdp.scale_y;
502 flr_y = nlr_y * rdp.scale_y;
504 // Make the vertices
506 if ((flr_x <= rdp.scissor.lr_x) || (ful_x < rdp.scissor.lr_x))
508 VERTEX v[4] = {
509 { ful_x, ful_y, Z, 1.0f, ful_u, ful_v },
510 { flr_x, ful_y, Z, 1.0f, flr_u, ful_v },
511 { ful_x, flr_y, Z, 1.0f, ful_u, flr_v },
512 { flr_x, flr_y, Z, 1.0f, flr_u, flr_v } };
513 AllowShadeMods (v, 4);
514 for (int s = 0; s < 4; s++)
515 apply_shade_mods (&(v[s]));
516 ConvertCoordsConvert (v, 4);
518 if (fullscreen)// && /*hack for Zelda MM. Gonetz*/rdp.cur_cache[0]->addr > 0xffff && rdp.cur_cache[0]->crc != 0)
520 grDrawVertexArrayContiguous (GR_TRIANGLE_STRIP, 4, v, sizeof(VERTEX));
523 if (debug.capture)
525 VERTEX vl[3];
526 vl[0] = v[0];
527 vl[1] = v[2];
528 vl[2] = v[1];
529 add_tri (vl, 3, TRI_BACKGROUND);
530 rdp.tri_n ++;
531 vl[0] = v[2];
532 vl[1] = v[3];
533 vl[2] = v[1];
534 add_tri (vl, 3, TRI_BACKGROUND);
535 rdp.tri_n ++;
537 else
538 rdp.tri_n += 2;
540 else
542 rdp.tri_n += 2;
543 RDP("Clipped!\n");
546 // increment whatever caused this split
547 tb_u += x_size - (x_size-(nlr_u-cb_u));
548 cb_u = nlr_u;
549 if (nlr_u == cur_wrap_u*d->imageW) {
550 cur_wrap_u ++;
551 tb_u = 0;
553 if (nlr_u == (cur_u<<x_shift)) cur_u ++;
554 if (nlr_u == lr_u) break;
555 nul_u = nlr_u;
556 nul_x = nlr_x;
559 tb_v += y_size - (y_size-(nlr_v-cb_v));
560 cb_v = nlr_v;
561 if (nlr_v == cur_wrap_v*d->imageH) {
562 cur_wrap_v ++;
563 tb_v = 0;
565 if (nlr_v == (cur_v<<y_shift)) cur_v ++;
566 if (nlr_v == lr_v) break;
567 nul_v = nlr_v;
568 nul_y = nlr_y;
571 rdp.allow_combine = 1;
573 rdp.update |= UPDATE_ZBUF_ENABLED | UPDATE_COMBINE | UPDATE_TEXTURE | UPDATE_ALPHA_COMPARE
574 | UPDATE_VIEWPORT;
576 if (fullscreen && settings.fog && (rdp.flags & FOG_ENABLED))
578 grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
583 void DrawHiresImage(DRAWIMAGE *d, BOOL screensize = FALSE)
585 FRDP("DrawHiresImage. addr: %08lx\n", d->imagePtr);
586 if (!fullscreen)
587 return;
588 HIRES_COLOR_IMAGE *hires_tex = (rdp.motionblur)?&(rdp.texbufs[rdp.cur_tex_buf^1].images[0]):rdp.hires_tex;
590 if (rdp.cycle_mode == 2)
592 rdp.allow_combine = 0;
593 rdp.update &= ~UPDATE_TEXTURE;
595 update (); // note: allow loading of texture
597 float Z = 1.0f;
598 if (rdp.zsrc == 1 && (rdp.othermode_l & 0x00000030))
600 RDP("Background uses depth compare\n");
601 Z = ScaleZ(rdp.prim_depth);
602 grDepthBufferFunction (GR_CMP_LEQUAL);
604 else
606 RDP("Background not uses depth compare\n");
607 grDepthBufferFunction (GR_CMP_ALWAYS);
609 grDepthMask (FXFALSE);
610 grClipWindow (0, 0, settings.res_x, settings.res_y);
611 grCullMode (GR_CULL_DISABLE);
612 if (rdp.cycle_mode == 2)
614 grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
615 GR_COMBINE_FACTOR_ONE,
616 GR_COMBINE_LOCAL_NONE,
617 GR_COMBINE_OTHER_TEXTURE,
618 FXFALSE);
619 grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
620 GR_COMBINE_FACTOR_ONE,
621 GR_COMBINE_LOCAL_NONE,
622 GR_COMBINE_OTHER_TEXTURE,
623 FXFALSE);
624 grConstantColorValue (0xFFFFFFFF);
625 grAlphaBlendFunction (GR_BLEND_ONE, // use alpha compare, but not T0 alpha
626 GR_BLEND_ZERO,
627 GR_BLEND_ZERO,
628 GR_BLEND_ZERO);
629 rdp.allow_combine = 1;
632 if (hires_tex->tmu == GR_TMU0)
634 grTexCombine( GR_TMU1,
635 GR_COMBINE_FUNCTION_NONE,
636 GR_COMBINE_FACTOR_NONE,
637 GR_COMBINE_FUNCTION_NONE,
638 GR_COMBINE_FACTOR_NONE,
639 FXFALSE,
640 FXFALSE );
641 grTexCombine( GR_TMU0,
642 GR_COMBINE_FUNCTION_LOCAL,
643 GR_COMBINE_FACTOR_NONE,
644 GR_COMBINE_FUNCTION_LOCAL,
645 GR_COMBINE_FACTOR_NONE,
646 FXFALSE,
647 FXFALSE );
649 else
651 grTexCombine( GR_TMU1,
652 GR_COMBINE_FUNCTION_LOCAL,
653 GR_COMBINE_FACTOR_NONE,
654 GR_COMBINE_FUNCTION_LOCAL,
655 GR_COMBINE_FACTOR_NONE,
656 FXFALSE,
657 FXFALSE );
658 grTexCombine( GR_TMU0,
659 GR_COMBINE_FUNCTION_SCALE_OTHER,
660 GR_COMBINE_FACTOR_ONE,
661 GR_COMBINE_FUNCTION_SCALE_OTHER,
662 GR_COMBINE_FACTOR_ONE,
663 FXFALSE,
664 FXFALSE );
666 grTexSource( hires_tex->tmu, hires_tex->tex_addr, GR_MIPMAPLEVELMASK_BOTH, &(hires_tex->info) );
668 if (d->imageW%2 == 1) d->imageW -= 1;
669 if (d->imageH%2 == 1) d->imageH -= 1;
670 if (d->imageY > d->imageH) d->imageY = (d->imageY%d->imageH);
672 if (!settings.PPL)
674 if ( (d->frameX > 0) && (d->frameW == rdp.ci_width) )
675 d->frameW -= (WORD)(2.0f*d->frameX);
676 if ( (d->frameY > 0) && (d->frameH == rdp.ci_height) )
677 d->frameH -= (WORD)(2.0f*d->frameY);
680 float ul_x, ul_y, ul_u, ul_v, lr_x, lr_y, lr_u, lr_v;
681 if (screensize)
683 ul_x = 0.0f;
684 ul_y = 0.0f;
685 ul_u = 0.0f;
686 ul_v = 0.0f;
687 lr_x = (float)rdp.hires_tex->scr_width;
688 lr_y = (float)rdp.hires_tex->scr_height;
689 lr_u = rdp.hires_tex->u_scale * (float)(rdp.hires_tex->width);//255.0f - (1024 - settings.res_x)*0.25f;
690 lr_v = rdp.hires_tex->v_scale * (float)(rdp.hires_tex->height);//255.0f - (1024 - settings.res_y)*0.25f;
692 else
694 ul_u = d->imageX;
695 ul_v = d->imageY;
696 lr_u = d->imageX + (d->frameW * d->scaleX) ;
697 lr_v = d->imageY + (d->frameH * d->scaleY) ;
699 ul_x = d->frameX;
700 ul_y = d->frameY;
702 lr_x = d->frameX + d->frameW;
703 lr_y = d->frameY + d->frameH;
704 ul_x *= rdp.scale_x;
705 lr_x *= rdp.scale_x;
706 ul_y *= rdp.scale_y;
707 lr_y *= rdp.scale_y;
708 ul_u *= rdp.hires_tex->u_scale;
709 lr_u *= rdp.hires_tex->u_scale;
710 ul_v *= rdp.hires_tex->v_scale;
711 lr_v *= rdp.hires_tex->v_scale;
712 if (lr_x > rdp.scissor.lr_x) lr_x = (float)rdp.scissor.lr_x;
713 if (lr_y > rdp.scissor.lr_y) lr_y = (float)rdp.scissor.lr_y;
715 // Make the vertices
716 VERTEX v[4] = {
717 { ul_x, ul_y, Z, 1.0f, ul_u, ul_v, ul_u, ul_v },
718 { lr_x, ul_y, Z, 1.0f, lr_u, ul_v, lr_u, ul_v },
719 { ul_x, lr_y, Z, 1.0f, ul_u, lr_v, ul_u, lr_v },
720 { lr_x, lr_y, Z, 1.0f, lr_u, lr_v, lr_u, lr_v } };
721 ConvertCoordsConvert (v, 4);
722 AllowShadeMods (v, 4);
723 for (int s = 0; s < 4; s++)
724 apply_shade_mods (&(v[s]));
725 grDrawTriangle (&v[0], &v[2], &v[1]);
726 grDrawTriangle (&v[2], &v[3], &v[1]);
727 rdp.update |= UPDATE_ZBUF_ENABLED | UPDATE_COMBINE | UPDATE_TEXTURE | UPDATE_ALPHA_COMPARE | UPDATE_VIEWPORT;
730 //****************************************************************
733 struct mat2d_t {
734 float A, B, C, D;
735 float X, Y;
736 float BaseScaleX;
737 float BaseScaleY;
738 } mat_2d;
740 static void uc6_bg_1cyc ()
742 if (render_depth_mode == 2) {
743 // ZIGGY
744 // Zelda LoT effect save/restore depth buffer
745 RDP("bg_1cyc: saving depth buffer\n");
746 //printf("bg_1cyc: saving depth buffer\n");
747 if (grFramebufferCopyExt)
748 grFramebufferCopyExt(0, 0, settings.scr_res_x, settings.scr_res_y,
749 GR_FBCOPY_BUFFER_BACK, GR_FBCOPY_BUFFER_FRONT,
750 GR_FBCOPY_MODE_DEPTH);
751 return;
754 if (rdp.skip_drawing)
756 RDP("bg_1cyc skipped\n");
757 return;
759 FRDP ("uc6:bg_1cyc #%d, #%d\n", rdp.tri_n, rdp.tri_n+1);
760 FRDP_E ("uc6:bg_1cyc #%d, #%d\n", rdp.tri_n, rdp.tri_n+1);
762 DWORD addr = segoffset(rdp.cmd1) >> 1;
764 DRAWIMAGE d;
766 d.imageX = (((WORD *)gfx.RDRAM)[(addr+0)^1] >> 5); // 0
767 d.imageW = (((WORD *)gfx.RDRAM)[(addr+1)^1] >> 2); // 1
768 d.frameX = ((short*)gfx.RDRAM)[(addr+2)^1] / 4.0f; // 2
769 d.frameW = ((WORD *)gfx.RDRAM)[(addr+3)^1] >> 2; // 3
771 d.imageY = (((WORD *)gfx.RDRAM)[(addr+4)^1] >> 5); // 4
772 d.imageH = (((WORD *)gfx.RDRAM)[(addr+5)^1] >> 2); // 5
773 d.frameY = ((short*)gfx.RDRAM)[(addr+6)^1] / 4.0f; // 6
774 d.frameH = ((WORD *)gfx.RDRAM)[(addr+7)^1] >> 2; // 7
776 d.imagePtr = segoffset(((DWORD*)gfx.RDRAM)[(addr+8)>>1]); // 8,9
777 // WORD imageLoad = ((WORD *)gfx.RDRAM)[(addr+10)^1]; // 10
778 d.imageFmt = ((BYTE *)gfx.RDRAM)[(((addr+11)<<1)+0)^3]; // 11
779 d.imageSiz = ((BYTE *)gfx.RDRAM)[(((addr+11)<<1)+1)^3]; // |
780 d.imagePal = ((WORD *)gfx.RDRAM)[(addr+12)^1]; // 12
781 WORD imageFlip = ((WORD *)gfx.RDRAM)[(addr+13)^1]; // 13;
782 d.flipX = (BYTE)imageFlip&0x01;
784 d.scaleX = ((short *)gfx.RDRAM)[(addr+14)^1] / 1024.0f; // 14
785 d.scaleY = ((short *)gfx.RDRAM)[(addr+15)^1] / 1024.0f; // 15
786 if (settings.doraemon2) //Doraemon 2 scale fix
788 if (d.frameW == d.imageW)
789 d.scaleX = 1.0f;
790 if (d.frameH == d.imageH)
791 d.scaleY = 1.0f;
793 d.flipY = 0;
794 long imageYorig= ((long *)gfx.RDRAM)[(addr+16)>>1] >> 5;
795 rdp.last_bg = d.imagePtr;
797 FRDP ("imagePtr: %08lx\n", d.imagePtr);
798 FRDP ("frameX: %f, frameW: %d, frameY: %f, frameH: %d\n", d.frameX, d.frameW, d.frameY, d.frameH);
799 FRDP ("imageX: %d, imageW: %d, imageY: %d, imageH: %d\n", d.imageX, d.imageW, d.imageY, d.imageH);
800 FRDP ("imageYorig: %d, scaleX: %f, scaleY: %f\n", imageYorig, d.scaleX, d.scaleY);
801 FRDP ("imageFmt: %d, imageSiz: %d, imagePal: %d, imageFlip: %d\n", d.imageFmt, d.imageSiz, d.imagePal, d.flipX);
802 if (settings.fb_hires && FindTextureBuffer(d.imagePtr, d.imageW))
804 DrawHiresImage(&d);
805 return;
808 if (settings.ucode == 2 || settings.PPL)
810 if ( (d.imagePtr != rdp.cimg) && (d.imagePtr != rdp.ocimg) && d.imagePtr) //can't draw from framebuffer
811 DrawImage (&d);
812 else
814 RDP("uc6:bg_1cyc skipped\n");
817 else
818 DrawImage (&d);
821 static void uc6_bg_copy ()
823 if (render_depth_mode == 1) {
824 // ZIGGY
825 // Zelda LoT effect save/restore depth buffer
826 RDP("bg_copy: restoring depth buffer\n");
827 //printf("bg_copy: restoring depth buffer\n");
828 if (grFramebufferCopyExt)
829 grFramebufferCopyExt(0, 0, settings.scr_res_x, settings.scr_res_y,
830 GR_FBCOPY_BUFFER_FRONT, GR_FBCOPY_BUFFER_BACK,
831 GR_FBCOPY_MODE_DEPTH);
832 return;
835 if (rdp.skip_drawing)
837 RDP("bg_copy skipped\n");
838 return;
840 FRDP ("uc6:bg_copy #%d, #%d\n", rdp.tri_n, rdp.tri_n+1);
842 DWORD addr = segoffset(rdp.cmd1) >> 1;
844 DRAWIMAGE d;
846 d.imageX = (((WORD *)gfx.RDRAM)[(addr+0)^1] >> 5); // 0
847 d.imageW = (((WORD *)gfx.RDRAM)[(addr+1)^1] >> 2); // 1
848 d.frameX = ((short*)gfx.RDRAM)[(addr+2)^1] / 4.0f; // 2
849 d.frameW = ((WORD *)gfx.RDRAM)[(addr+3)^1] >> 2; // 3
851 d.imageY = (((WORD *)gfx.RDRAM)[(addr+4)^1] >> 5); // 4
852 d.imageH = (((WORD *)gfx.RDRAM)[(addr+5)^1] >> 2); // 5
853 d.frameY = ((short*)gfx.RDRAM)[(addr+6)^1] / 4.0f; // 6
854 d.frameH = ((WORD *)gfx.RDRAM)[(addr+7)^1] >> 2; // 7
856 d.imagePtr = segoffset(((DWORD*)gfx.RDRAM)[(addr+8)>>1]); // 8,9
857 d.imageFmt = ((BYTE *)gfx.RDRAM)[(((addr+11)<<1)+0)^3]; // 11
858 d.imageSiz = ((BYTE *)gfx.RDRAM)[(((addr+11)<<1)+1)^3]; // |
859 d.imagePal = ((WORD *)gfx.RDRAM)[(addr+12)^1]; // 12
860 WORD imageFlip = ((WORD *)gfx.RDRAM)[(addr+13)^1]; // 13;
861 d.flipX = (BYTE)imageFlip&0x01;
863 d.scaleX = 1.0f; // 14
864 d.scaleY = 1.0f; // 15
865 d.flipY = 0;
866 rdp.last_bg = d.imagePtr;
868 FRDP ("imagePtr: %08lx\n", d.imagePtr);
869 FRDP ("frameX: %f, frameW: %d, frameY: %f, frameH: %d\n", d.frameX, d.frameW, d.frameY, d.frameH);
870 FRDP ("imageX: %d, imageW: %d, imageY: %d, imageH: %d\n", d.imageX, d.imageW, d.imageY, d.imageH);
871 FRDP ("imageFmt: %d, imageSiz: %d, imagePal: %d\n", d.imageFmt, d.imageSiz, d.imagePal);
873 if (settings.fb_hires && FindTextureBuffer(d.imagePtr, d.imageW))
875 DrawHiresImage(&d);
876 return;
879 if (settings.ucode == 2 || settings.PPL)
881 if ( (d.imagePtr != rdp.cimg) && (d.imagePtr != rdp.ocimg) && d.imagePtr) //can't draw from framebuffer
882 DrawImage (&d);
883 else
885 RDP("uc6:bg_copy skipped\n");
888 else
889 DrawImage (&d);
893 static void draw_splitted_triangle(VERTEX **vtx)
895 vtx[0]->not_zclipped = vtx[1]->not_zclipped = vtx[2]->not_zclipped = 1;
897 int index,i,j, min_256,max_256, cur_256,left_256,right_256;
898 float percent;
900 min_256 = min((int)vtx[0]->u0,(int)vtx[1]->u0); // bah, don't put two mins on one line
901 min_256 = min(min_256,(int)vtx[2]->u0) >> 8; // or it will be calculated twice
903 max_256 = max((int)vtx[0]->u0,(int)vtx[1]->u0); // not like it makes much difference
904 max_256 = max(max_256,(int)vtx[2]->u0) >> 8; // anyway :P
906 for (cur_256=min_256; cur_256<=max_256; cur_256++)
908 left_256 = cur_256 << 8;
909 right_256 = (cur_256+1) << 8;
911 // Set vertex buffers
912 rdp.vtxbuf = rdp.vtx1; // copy from v to rdp.vtx1
913 rdp.vtxbuf2 = rdp.vtx2;
914 rdp.vtx_buffer = 0;
915 rdp.n_global = 3;
916 index = 0;
918 // ** Left plane **
919 for (i=0; i<3; i++)
921 j = i+1;
922 if (j == 3) j = 0;
924 VERTEX *v1 = vtx[i];
925 VERTEX *v2 = vtx[j];
927 if (v1->u0 >= left_256)
929 if (v2->u0 >= left_256) // Both are in, save the last one
931 rdp.vtxbuf[index] = *v2;
932 rdp.vtxbuf[index].u0 -= left_256;
933 rdp.vtxbuf[index++].v0 += rdp.cur_cache[0]->c_scl_y * (cur_256 * rdp.cur_cache[0]->splitheight);
935 else // First is in, second is out, save intersection
937 percent = (left_256 - v1->u0) / (v2->u0 - v1->u0);
938 rdp.vtxbuf[index].x = v1->x + (v2->x - v1->x) * percent;
939 rdp.vtxbuf[index].y = v1->y + (v2->y - v1->y) * percent;
940 rdp.vtxbuf[index].z = 1;
941 rdp.vtxbuf[index].q = 1;
942 rdp.vtxbuf[index].u0 = 0.5f;
943 rdp.vtxbuf[index].v0 = v1->v0 + (v2->v0 - v1->v0) * percent +
944 rdp.cur_cache[0]->c_scl_y * cur_256 * rdp.cur_cache[0]->splitheight;
945 rdp.vtxbuf[index].b = (BYTE)(v1->b + (v2->b - v1->b) * percent);
946 rdp.vtxbuf[index].g = (BYTE)(v1->g + (v2->g - v1->g) * percent);
947 rdp.vtxbuf[index].r = (BYTE)(v1->r + (v2->r - v1->r) * percent);
948 rdp.vtxbuf[index++].a = (BYTE)(v1->a + (v2->a - v1->a) * percent);
951 else
953 //if (v2->u0 < left_256) // Both are out, save nothing
954 if (v2->u0 >= left_256) // First is out, second is in, save intersection & in point
956 percent = (left_256 - v2->u0) / (v1->u0 - v2->u0);
957 rdp.vtxbuf[index].x = v2->x + (v1->x - v2->x) * percent;
958 rdp.vtxbuf[index].y = v2->y + (v1->y - v2->y) * percent;
959 rdp.vtxbuf[index].z = 1;
960 rdp.vtxbuf[index].q = 1;
961 rdp.vtxbuf[index].u0 = 0.5f;
962 rdp.vtxbuf[index].v0 = v2->v0 + (v1->v0 - v2->v0) * percent +
963 rdp.cur_cache[0]->c_scl_y * cur_256 * rdp.cur_cache[0]->splitheight;
964 rdp.vtxbuf[index].b = (BYTE)(v2->b + (v1->b - v2->b) * percent);
965 rdp.vtxbuf[index].g = (BYTE)(v2->g + (v1->g - v2->g) * percent);
966 rdp.vtxbuf[index].r = (BYTE)(v2->r + (v1->r - v2->r) * percent);
967 rdp.vtxbuf[index++].a = (BYTE)(v2->a + (v1->a - v2->a) * percent);
969 // Save the in point
970 rdp.vtxbuf[index] = *v2;
971 rdp.vtxbuf[index].u0 -= left_256;
972 rdp.vtxbuf[index++].v0 += rdp.cur_cache[0]->c_scl_y * (cur_256 * rdp.cur_cache[0]->splitheight);
976 rdp.n_global = index;
978 rdp.vtxbuf = rdp.vtx2; // now vtx1 holds the value, & vtx2 is the destination
979 rdp.vtxbuf2 = rdp.vtx1;
980 rdp.vtx_buffer ^= 1;
981 index = 0;
983 for (i=0; i<rdp.n_global; i++)
985 j = i+1;
986 if (j == rdp.n_global) j = 0;
988 VERTEX *v1 = &rdp.vtxbuf2[i];
989 VERTEX *v2 = &rdp.vtxbuf2[j];
991 // ** Right plane **
992 if (v1->u0 <= 256.0f)
994 if (v2->u0 <= 256.0f) // Both are in, save the last one
996 rdp.vtxbuf[index++] = *v2;
998 else // First is in, second is out, save intersection
1000 percent = (right_256 - v1->u0) / (v2->u0 - v1->u0);
1001 rdp.vtxbuf[index].x = v1->x + (v2->x - v1->x) * percent;
1002 rdp.vtxbuf[index].y = v1->y + (v2->y - v1->y) * percent;
1003 rdp.vtxbuf[index].z = 1;
1004 rdp.vtxbuf[index].q = 1;
1005 rdp.vtxbuf[index].u0 = 255.5f;
1006 rdp.vtxbuf[index].v0 = v1->v0 + (v2->v0 - v1->v0) * percent;
1007 rdp.vtxbuf[index].b = (BYTE)(v1->b + (v2->b - v1->b) * percent);
1008 rdp.vtxbuf[index].g = (BYTE)(v1->g + (v2->g - v1->g) * percent);
1009 rdp.vtxbuf[index].r = (BYTE)(v1->r + (v2->r - v1->r) * percent);
1010 rdp.vtxbuf[index++].a = (BYTE)(v1->a + (v2->a - v1->a) * percent);
1013 else
1015 //if (v2->u0 > 256.0f) // Both are out, save nothing
1016 if (v2->u0 <= 256.0f) // First is out, second is in, save intersection & in point
1018 percent = (right_256 - v2->u0) / (v1->u0 - v2->u0);
1019 rdp.vtxbuf[index].x = v2->x + (v1->x - v2->x) * percent;
1020 rdp.vtxbuf[index].y = v2->y + (v1->y - v2->y) * percent;
1021 rdp.vtxbuf[index].z = 1;
1022 rdp.vtxbuf[index].q = 1;
1023 rdp.vtxbuf[index].u0 = 255.5f;
1024 rdp.vtxbuf[index].v0 = v2->v0 + (v1->v0 - v2->v0) * percent;
1025 rdp.vtxbuf[index].b = (BYTE)(v2->b + (v1->b - v2->b) * percent);
1026 rdp.vtxbuf[index].g = (BYTE)(v2->g + (v1->g - v2->g) * percent);
1027 rdp.vtxbuf[index].r = (BYTE)(v2->r + (v1->r - v2->r) * percent);
1028 rdp.vtxbuf[index++].a = (BYTE)(v2->a + (v1->a - v2->a) * percent);
1030 // Save the in point
1031 rdp.vtxbuf[index++] = *v2;
1035 rdp.n_global = index;
1037 do_triangle_stuff_2 ();
1041 static float set_sprite_combine_mode ()
1043 if (rdp.cycle_mode == 2)
1045 rdp.tex = 1;
1046 rdp.allow_combine = 0;
1048 cmb.tmu1_func = cmb.tmu0_func = GR_COMBINE_FUNCTION_LOCAL;
1049 cmb.tmu1_fac = cmb.tmu0_fac = GR_COMBINE_FACTOR_NONE;
1050 cmb.tmu1_a_func = cmb.tmu0_a_func = GR_COMBINE_FUNCTION_LOCAL;
1051 cmb.tmu1_a_fac = cmb.tmu0_a_fac = GR_COMBINE_FACTOR_NONE;
1052 cmb.tmu1_invert = cmb.tmu0_invert = FXFALSE;
1053 cmb.tmu1_a_invert = cmb.tmu0_a_invert = FXFALSE;
1054 rdp.update |= UPDATE_COMBINE;
1055 //*/
1057 rdp.update |= UPDATE_TEXTURE;
1058 update ();
1059 rdp.allow_combine = 1;
1061 float Z = 1.0f;
1062 if (fullscreen)
1064 grFogMode (GR_FOG_DISABLE);
1065 if (rdp.zsrc == 1 && (rdp.othermode_l & 0x00000030))
1067 RDP("Sprite uses depth compare\n");
1068 Z = rdp.prim_depth;
1069 grDepthBufferFunction (GR_CMP_LEQUAL);
1070 grDepthMask (FXTRUE);
1072 else
1074 RDP("Sprite not uses depth compare\n");
1075 grDepthBufferFunction (GR_CMP_ALWAYS);
1076 grDepthMask (FXFALSE);
1079 grClipWindow (0, 0, settings.res_x, settings.res_y);
1081 grCullMode (GR_CULL_DISABLE);
1083 if (rdp.cycle_mode == 2)
1085 grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
1086 GR_COMBINE_FACTOR_ONE,
1087 GR_COMBINE_LOCAL_NONE,
1088 GR_COMBINE_OTHER_TEXTURE,
1089 FXFALSE);
1090 grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
1091 GR_COMBINE_FACTOR_ONE,
1092 GR_COMBINE_LOCAL_NONE,
1093 GR_COMBINE_OTHER_TEXTURE,
1094 FXFALSE);
1095 grAlphaBlendFunction (GR_BLEND_ONE,
1096 GR_BLEND_ZERO,
1097 GR_BLEND_ZERO,
1098 GR_BLEND_ZERO);
1099 rdp.update |= UPDATE_ALPHA_COMPARE | UPDATE_COMBINE | UPDATE_ALPHA_COMPARE;
1102 return Z;
1105 static void uc6_draw_polygons (VERTEX v[4])
1107 AllowShadeMods (v, 4);
1108 for (int s = 0; s < 4; s++)
1109 apply_shade_mods (&(v[s]));
1111 // Set vertex buffers
1112 if (rdp.cur_cache[0]->splits > 1)
1114 VERTEX *vptr[3];
1115 int i;
1116 for (i = 0; i < 3; i++)
1117 vptr[i] = &v[i];
1118 draw_splitted_triangle(vptr);
1120 rdp.tri_n ++;
1121 for (i = 0; i < 3; i++)
1122 vptr[i] = &v[i+1];
1123 draw_splitted_triangle(vptr);
1124 rdp.tri_n ++;
1126 else
1128 rdp.vtxbuf = rdp.vtx1; // copy from v to rdp.vtx1
1129 rdp.vtxbuf2 = rdp.vtx2;
1130 rdp.vtx_buffer = 0;
1131 rdp.n_global = 3;
1132 memcpy (rdp.vtxbuf, v, sizeof(VERTEX)*3);
1133 do_triangle_stuff_2 ();
1134 rdp.tri_n ++;
1136 rdp.vtxbuf = rdp.vtx1; // copy from v to rdp.vtx1
1137 rdp.vtxbuf2 = rdp.vtx2;
1138 rdp.vtx_buffer = 0;
1139 rdp.n_global = 3;
1140 memcpy (rdp.vtxbuf, v+1, sizeof(VERTEX)*3);
1141 do_triangle_stuff_2 ();
1142 rdp.tri_n ++;
1144 rdp.update |= UPDATE_ZBUF_ENABLED | UPDATE_VIEWPORT;
1146 if (fullscreen && settings.fog && (rdp.flags & FOG_ENABLED))
1148 grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
1152 static void uc6_obj_rectangle ()
1154 // RDP ("uc6:obj_rectangle\n");
1156 DWORD addr = segoffset(rdp.cmd1) >> 1;
1158 float objX = ((short*)gfx.RDRAM)[(addr+0)^1] / 4.0f; // 0
1159 float scaleW = ((WORD *)gfx.RDRAM)[(addr+1)^1] / 1024.0f; // 1
1160 short imageW = ((short*)gfx.RDRAM)[(addr+2)^1] >> 5; // 2, 3 is padding
1161 float objY = ((short*)gfx.RDRAM)[(addr+4)^1] / 4.0f; // 4
1162 float scaleH = ((WORD *)gfx.RDRAM)[(addr+5)^1] / 1024.0f; // 5
1163 short imageH = ((short*)gfx.RDRAM)[(addr+6)^1] >> 5; // 6, 7 is padding
1165 WORD imageStride = ((WORD *)gfx.RDRAM)[(addr+8)^1]; // 8
1166 WORD imageAdrs = ((WORD *)gfx.RDRAM)[(addr+9)^1]; // 9
1167 BYTE imageFmt = ((BYTE *)gfx.RDRAM)[(((addr+10)<<1)+0)^3]; // 10
1168 BYTE imageSiz = ((BYTE *)gfx.RDRAM)[(((addr+10)<<1)+1)^3]; // |
1169 BYTE imagePal = ((BYTE *)gfx.RDRAM)[(((addr+10)<<1)+2)^3]; // 11
1170 BYTE imageFlags = ((BYTE *)gfx.RDRAM)[(((addr+10)<<1)+3)^3]; // |
1172 if (imageW < 0)
1173 imageW = (short)rdp.scissor_o.lr_x - (short)objX - imageW;
1174 if (imageH < 0)
1175 imageH = (short)rdp.scissor_o.lr_y - (short)objY - imageH;
1177 FRDP ("uc6:obj_rectangle #%d, #%d\n"
1178 "objX: %f, scaleW: %f, imageW: %d\n"
1179 "objY: %f, scaleH: %f, imageH: %d\n"
1180 "size: %d, format: %d\n", rdp.tri_n, rdp.tri_n+1,
1181 objX, scaleW, imageW, objY, scaleH, imageH, imageSiz, imageFmt);
1182 if (imageAdrs > 4096)
1184 FRDP("tmem: %08lx is out of bounds! return\n", imageAdrs);
1185 return;
1187 if (!rdp.s2dex_tex_loaded)
1189 RDP("Texture was not loaded! return\n");
1190 return;
1193 // SetTile ()
1194 TILE *tile = &rdp.tiles[0];
1195 tile->format = imageFmt; // RGBA
1196 tile->size = imageSiz; // 16-bit
1197 tile->line = imageStride;
1198 tile->t_mem = imageAdrs;
1199 tile->palette = imagePal;
1200 tile->clamp_t = 1;
1201 tile->mirror_t = 0;
1202 tile->mask_t = 0;
1203 tile->shift_t = 0;
1204 tile->clamp_s = 1;
1205 tile->mirror_s = 0;
1206 tile->mask_s = 0;
1207 tile->shift_s = 0;
1209 // SetTileSize ()
1210 rdp.tiles[0].ul_s = 0;
1211 rdp.tiles[0].ul_t = 0;
1212 rdp.tiles[0].lr_s = (imageW>0)?imageW-1:0;
1213 rdp.tiles[0].lr_t = (imageH>0)?imageH-1:0;
1215 float Z = set_sprite_combine_mode ();
1217 float ul_x = objX;
1218 float lr_x = objX + imageW/scaleW;
1219 float ul_y = objY;
1220 float lr_y = objY + imageH/scaleH;
1221 float ul_u, lr_u, ul_v, lr_v;
1222 if (rdp.cur_cache[0]->splits > 1)
1224 lr_u = (float)(imageW-1);
1225 lr_v = (float)(imageH-1);
1227 else
1229 lr_u = 255.0f*rdp.cur_cache[0]->scale_x;
1230 lr_v = 255.0f*rdp.cur_cache[0]->scale_y;
1233 if (imageFlags&0x01) //flipS
1235 ul_u = lr_u;
1236 lr_u = 0.5f;
1238 else
1239 ul_u = 0.5f;
1240 if (imageFlags&0x10) //flipT
1242 ul_v = lr_v;
1243 lr_v = 0.5f;
1245 else
1246 ul_v = 0.5f;
1248 // Make the vertices
1249 VERTEX v[4] = {
1250 { ul_x, ul_y, Z, 1, ul_u, ul_v },
1251 { lr_x, ul_y, Z, 1, lr_u, ul_v },
1252 { ul_x, lr_y, Z, 1, ul_u, lr_v },
1253 { lr_x, lr_y, Z, 1, lr_u, lr_v }
1256 int i;
1257 for (i=0; i<4; i++)
1259 v[i].x *= rdp.scale_x;
1260 v[i].y *= rdp.scale_y;
1263 uc6_draw_polygons (v);
1266 void uc6_obj_sprite ()
1268 DWORD addr = segoffset(rdp.cmd1) >> 1;
1270 float objX = ((short*)gfx.RDRAM)[(addr+0)^1] / 4.0f; // 0
1271 float scaleW = ((WORD *)gfx.RDRAM)[(addr+1)^1] / 1024.0f; // 1
1272 short imageW = ((short*)gfx.RDRAM)[(addr+2)^1] >> 5; // 2, 3 is padding
1273 float objY = ((short*)gfx.RDRAM)[(addr+4)^1] / 4.0f; // 4
1274 float scaleH = ((WORD *)gfx.RDRAM)[(addr+5)^1] / 1024.0f; // 5
1275 short imageH = ((short*)gfx.RDRAM)[(addr+6)^1] >> 5; // 6, 7 is padding
1277 WORD imageStride = ((WORD *)gfx.RDRAM)[(addr+8)^1]; // 8
1278 WORD imageAdrs = ((WORD *)gfx.RDRAM)[(addr+9)^1]; // 9
1279 BYTE imageFmt = ((BYTE *)gfx.RDRAM)[(((addr+10)<<1)+0)^3]; // 10
1280 BYTE imageSiz = ((BYTE *)gfx.RDRAM)[(((addr+10)<<1)+1)^3]; // |
1281 BYTE imagePal = ((BYTE *)gfx.RDRAM)[(((addr+10)<<1)+2)^3]; // 11
1282 BYTE imageFlags = ((BYTE *)gfx.RDRAM)[(((addr+10)<<1)+3)^3]; // |
1284 FRDP ("uc6:obj_sprite #%d, #%d\n"
1285 "objX: %f, scaleW: %f, imageW: %d\n"
1286 "objY: %f, scaleH: %f, imageH: %d\n"
1287 "size: %d, format: %d\n", rdp.tri_n, rdp.tri_n+1,
1288 objX, scaleW, imageW, objY, scaleH, imageH, imageSiz, imageFmt);
1290 // SetTile ()
1291 TILE *tile = &rdp.tiles[0];
1292 tile->format = imageFmt; // RGBA
1293 tile->size = imageSiz; // 16-bit
1294 tile->line = imageStride;
1295 tile->t_mem = imageAdrs;
1296 tile->palette = imagePal;
1297 tile->clamp_t = 1;
1298 tile->mirror_t = 0;
1299 tile->mask_t = 0;
1300 tile->shift_t = 0;
1301 tile->clamp_s = 1;
1302 tile->mirror_s = 0;
1303 tile->mask_s = 0;
1304 tile->shift_s = 0;
1306 // SetTileSize ()
1307 rdp.tiles[0].ul_s = 0;
1308 rdp.tiles[0].ul_t = 0;
1309 rdp.tiles[0].lr_s = (imageW>0)?imageW-1:0;
1310 rdp.tiles[0].lr_t = (imageH>0)?imageH-1:0;
1312 float Z = set_sprite_combine_mode ();
1314 float ul_x = objX;
1315 float lr_x = objX + imageW/scaleW;
1316 float ul_y = objY;
1317 float lr_y = objY + imageH/scaleH;
1318 float ul_u, lr_u, ul_v, lr_v;
1319 if (rdp.cur_cache[0]->splits > 1)
1321 lr_u = (float)(imageW-1);
1322 lr_v = (float)(imageH-1);
1324 else
1326 lr_u = 255.0f*rdp.cur_cache[0]->scale_x;
1327 lr_v = 255.0f*rdp.cur_cache[0]->scale_y;
1330 if (imageFlags&0x01) //flipS
1332 ul_u = lr_u;
1333 lr_u = 0.5f;
1335 else
1336 ul_u = 0.5f;
1337 if (imageFlags&0x10) //flipT
1339 ul_v = lr_v;
1340 lr_v = 0.5f;
1342 else
1343 ul_v = 0.5f;
1345 // Make the vertices
1346 // FRDP("scale_x: %f, scale_y: %f\n", rdp.cur_cache[0]->scale_x, rdp.cur_cache[0]->scale_y);
1348 VERTEX v[4] = {
1349 { ul_x, ul_y, Z, 1, ul_u, ul_v },
1350 { lr_x, ul_y, Z, 1, lr_u, ul_v },
1351 { ul_x, lr_y, Z, 1, ul_u, lr_v },
1352 { lr_x, lr_y, Z, 1, lr_u, lr_v }
1355 int i;
1356 for (i=0; i<4; i++)
1358 float x = v[i].x;
1359 float y = v[i].y;
1360 v[i].x = (x * mat_2d.A + y * mat_2d.B + mat_2d.X) * rdp.scale_x;
1361 v[i].y = (x * mat_2d.C + y * mat_2d.D + mat_2d.Y) * rdp.scale_y;
1364 uc6_draw_polygons (v);
1367 void uc6_obj_movemem ()
1369 RDP ("uc6:obj_movemem\n");
1371 int index = rdp.cmd0 & 0xFFFF;
1372 DWORD addr = segoffset(rdp.cmd1) >> 1;
1374 if (index == 0) { // movemem matrix
1375 mat_2d.A = ((long*)gfx.RDRAM)[(addr+0)>>1] / 65536.0f;
1376 mat_2d.B = ((long*)gfx.RDRAM)[(addr+2)>>1] / 65536.0f;
1377 mat_2d.C = ((long*)gfx.RDRAM)[(addr+4)>>1] / 65536.0f;
1378 mat_2d.D = ((long*)gfx.RDRAM)[(addr+6)>>1] / 65536.0f;
1379 mat_2d.X = ((short*)gfx.RDRAM)[(addr+8)^1] / 4.0f;
1380 mat_2d.Y = ((short*)gfx.RDRAM)[(addr+9)^1] / 4.0f;
1381 mat_2d.BaseScaleX = ((WORD*)gfx.RDRAM)[(addr+10)^1] / 1024.0f;
1382 mat_2d.BaseScaleY = ((WORD*)gfx.RDRAM)[(addr+11)^1] / 1024.0f;
1384 FRDP ("mat_2d\nA: %f, B: %f, c: %f, D: %f\nX: %f, Y: %f\nBaseScaleX: %f, BaseScaleY: %f\n",
1385 mat_2d.A, mat_2d.B, mat_2d.C, mat_2d.D, mat_2d.X, mat_2d.Y, mat_2d.BaseScaleX, mat_2d.BaseScaleY);
1387 else if (index == 2) { // movemem submatrix
1388 mat_2d.X = ((short*)gfx.RDRAM)[(addr+0)^1] / 4.0f;
1389 mat_2d.Y = ((short*)gfx.RDRAM)[(addr+1)^1] / 4.0f;
1390 mat_2d.BaseScaleX = ((WORD*)gfx.RDRAM)[(addr+2)^1] / 1024.0f;
1391 mat_2d.BaseScaleY = ((WORD*)gfx.RDRAM)[(addr+3)^1] / 1024.0f;
1393 FRDP ("submatrix\nX: %f, Y: %f\nBaseScaleX: %f, BaseScaleY: %f\n",
1394 mat_2d.X, mat_2d.Y, mat_2d.BaseScaleX, mat_2d.BaseScaleY);
1398 static void uc6_select_dl ()
1400 RDP ("uc6:select_dl\n");
1401 RDP_E ("uc6:select_dl\n");
1404 static void uc6_obj_rendermode ()
1406 RDP ("uc6:obj_rendermode\n");
1407 RDP_E ("uc6:obj_rendermode\n");
1410 void uc6_obj_rectangle_r ()
1412 // RDP ("uc6:obj_rectangle_r\n");
1414 DWORD addr = segoffset(rdp.cmd1) >> 1;
1416 float objX = ((short*)gfx.RDRAM)[(addr+0)^1] / 4.0f; // 0
1417 float scaleW = ((WORD *)gfx.RDRAM)[(addr+1)^1] / 1024.0f; // 1
1418 short imageW = ((short*)gfx.RDRAM)[(addr+2)^1] >> 5; // 2, 3 is padding
1419 float objY = ((short*)gfx.RDRAM)[(addr+4)^1] / 4.0f; // 4
1420 float scaleH = ((WORD *)gfx.RDRAM)[(addr+5)^1] / 1024.0f; // 5
1421 short imageH = ((short*)gfx.RDRAM)[(addr+6)^1] >> 5; // 6, 7 is padding
1423 WORD imageStride = ((WORD *)gfx.RDRAM)[(addr+8)^1]; // 8
1424 WORD imageAdrs = ((WORD *)gfx.RDRAM)[(addr+9)^1]; // 9
1425 BYTE imageFmt = ((BYTE *)gfx.RDRAM)[(((addr+10)<<1)+0)^3]; // 10
1426 BYTE imageSiz = ((BYTE *)gfx.RDRAM)[(((addr+10)<<1)+1)^3]; // |
1427 BYTE imagePal = ((BYTE *)gfx.RDRAM)[(((addr+10)<<1)+2)^3]; // 11
1428 BYTE imageFlags = ((BYTE *)gfx.RDRAM)[(((addr+10)<<1)+3)^3]; // |
1430 if (imageW < 0)
1431 imageW = (short)rdp.scissor_o.lr_x - (short)objX - imageW;
1432 if (imageH < 0)
1433 imageH = (short)rdp.scissor_o.lr_y - (short)objY - imageH;
1435 FRDP ("uc6:obj_rectangle_r #%d, #%d\n"
1436 "objX: %f, scaleW: %f, imageW: %d\n"
1437 "objY: %f, scaleH: %f, imageH: %d\n"
1438 "size: %d, format: %d\n", rdp.tri_n, rdp.tri_n+1,
1439 objX, scaleW, imageW, objY, scaleH, imageH, imageSiz, imageFmt);
1441 if (imageFmt == 1) //YUV
1443 float ul_x = objX/mat_2d.BaseScaleX + mat_2d.X;
1444 float lr_x = (objX + imageW/scaleW)/mat_2d.BaseScaleX + mat_2d.X;
1445 float ul_y = objY/mat_2d.BaseScaleY + mat_2d.Y;
1446 float lr_y = (objY + imageH/scaleH)/mat_2d.BaseScaleY + mat_2d.Y;
1447 if (ul_x < rdp.yuv_ul_x) rdp.yuv_ul_x = ul_x;
1448 if (lr_x > rdp.yuv_lr_x) rdp.yuv_lr_x = lr_x;
1449 if (ul_y < rdp.yuv_ul_y) rdp.yuv_ul_y = ul_y;
1450 if (lr_y > rdp.yuv_lr_y) rdp.yuv_lr_y = lr_y;
1451 rdp.tri_n += 2;
1452 return;
1454 // SetTile ()
1455 TILE *tile = &rdp.tiles[0];
1456 tile->format = imageFmt; // RGBA
1457 tile->size = imageSiz; // 16-bit
1458 tile->line = imageStride;
1459 tile->t_mem = imageAdrs;
1460 tile->palette = imagePal;
1461 tile->clamp_t = 1;
1462 tile->mirror_t = 0;
1463 tile->mask_t = 0;
1464 tile->shift_t = 0;
1465 tile->clamp_s = 1;
1466 tile->mirror_s = 0;
1467 tile->mask_s = 0;
1468 tile->shift_s = 0;
1470 // SetTileSize ()
1471 rdp.tiles[0].ul_s = 0;
1472 rdp.tiles[0].ul_t = 0;
1473 rdp.tiles[0].lr_s = (imageW>0)?imageW-1:0;
1474 rdp.tiles[0].lr_t = (imageH>0)?imageH-1:0;
1476 float Z = set_sprite_combine_mode ();
1478 float ul_x = objX/mat_2d.BaseScaleX;
1479 float lr_x = (objX + imageW/scaleW)/mat_2d.BaseScaleX;
1480 float ul_y = objY/mat_2d.BaseScaleY;
1481 float lr_y = (objY + imageH/scaleH)/mat_2d.BaseScaleY;
1482 float ul_u, lr_u, ul_v, lr_v;
1483 if (rdp.cur_cache[0]->splits > 1)
1485 lr_u = (float)(imageW-1);
1486 lr_v = (float)(imageH-1);
1488 else
1490 lr_u = 255.0f*rdp.cur_cache[0]->scale_x;
1491 lr_v = 255.0f*rdp.cur_cache[0]->scale_y;
1494 if (imageFlags&0x01) //flipS
1496 ul_u = lr_u;
1497 lr_u = 0.5f;
1499 else
1500 ul_u = 0.5f;
1501 if (imageFlags&0x10) //flipT
1503 ul_v = lr_v;
1504 lr_v = 0.5f;
1506 else
1507 ul_v = 0.5f;
1509 // Make the vertices
1510 VERTEX v[4] = {
1511 { ul_x, ul_y, Z, 1, ul_u, ul_v },
1512 { lr_x, ul_y, Z, 1, lr_u, ul_v },
1513 { ul_x, lr_y, Z, 1, ul_u, lr_v },
1514 { lr_x, lr_y, Z, 1, lr_u, lr_v }
1517 int i;
1518 for (i=0; i<4; i++)
1520 float x = v[i].x;
1521 float y = v[i].y;
1522 v[i].x = (x + mat_2d.X) * rdp.scale_x;
1523 v[i].y = (y + mat_2d.Y) * rdp.scale_y;
1526 uc6_draw_polygons (v);
1529 void uc6_obj_loadtxtr ()
1531 RDP ("uc6:obj_loadtxtr ");
1532 rdp.s2dex_tex_loaded = TRUE;
1533 rdp.update |= UPDATE_TEXTURE;
1535 DWORD addr = segoffset(rdp.cmd1) >> 1;
1536 DWORD type = ((DWORD*)gfx.RDRAM)[(addr + 0) >> 1]; // 0, 1
1538 if (type == 0x00000030) { // TLUT
1539 DWORD image = segoffset(((DWORD*)gfx.RDRAM)[(addr + 2) >> 1]); // 2, 3
1540 WORD phead = ((WORD *)gfx.RDRAM)[(addr + 4) ^ 1] - 256; // 4
1541 WORD pnum = ((WORD *)gfx.RDRAM)[(addr + 5) ^ 1] + 1; // 5
1543 FRDP ("palette addr: %08lx, start: %d, num: %d\n", image, phead, pnum);
1544 load_palette (image, phead, pnum);
1546 else if (type == 0x00001033) { // TxtrBlock
1547 DWORD image = segoffset(((DWORD*)gfx.RDRAM)[(addr + 2) >> 1]); // 2, 3
1548 WORD tmem = ((WORD *)gfx.RDRAM)[(addr + 4) ^ 1]; // 4
1549 WORD tsize = ((WORD *)gfx.RDRAM)[(addr + 5) ^ 1]; // 5
1550 WORD tline = ((WORD *)gfx.RDRAM)[(addr + 6) ^ 1]; // 6
1552 FRDP ("addr: %08lx, tmem: %08lx, size: %d\n", image, tmem, tsize);
1553 rdp.timg.addr = image;
1555 rdp.tiles[7].t_mem = tmem;
1556 rdp.tiles[7].size = 1;
1557 rdp.cmd0 = 0;
1558 rdp.cmd1 = 0x07000000 | (tsize << 14) | tline;
1559 rdp_loadblock ();
1561 else if (type == 0x00fc1034)
1563 DWORD image = segoffset(((DWORD*)gfx.RDRAM)[(addr + 2) >> 1]); // 2, 3
1564 WORD tmem = ((WORD *)gfx.RDRAM)[(addr + 4) ^ 1]; // 4
1565 WORD twidth = ((WORD *)gfx.RDRAM)[(addr + 5) ^ 1]; // 5
1566 WORD theight = ((WORD *)gfx.RDRAM)[(addr + 6) ^ 1]; // 6
1568 FRDP ("tile addr: %08lx, tmem: %08lx, twidth: %d, theight: %d\n", image, tmem, twidth, theight);
1570 int line = (twidth + 1) >> 2;
1572 rdp.timg.addr = image;
1573 rdp.timg.width = line << 3;
1575 rdp.tiles[7].t_mem = tmem;
1576 rdp.tiles[7].line = line;
1577 rdp.tiles[7].size = 1;
1579 rdp.cmd0 = 0;
1580 rdp.cmd1 = 0x07000000 | (twidth << 14) | (theight << 2);
1582 rdp_loadtile ();
1584 else
1586 FRDP ("UNKNOWN (0x%08lx)\n", type);
1587 FRDP_E ("uc6:obj_loadtxtr UNKNOWN (0x%08lx)\n", type);
1591 void uc6_obj_ldtx_sprite ()
1593 RDP ("uc6:obj_ldtx_sprite\n");
1595 DWORD addr = rdp.cmd1;
1596 uc6_obj_loadtxtr ();
1597 rdp.cmd1 = addr + 24;
1598 uc6_obj_sprite ();
1601 void uc6_obj_ldtx_rect ()
1603 RDP ("uc6:obj_ldtx_rect\n");
1605 DWORD addr = rdp.cmd1;
1606 uc6_obj_loadtxtr ();
1607 rdp.cmd1 = addr + 24;
1608 uc6_obj_rectangle ();
1611 static void uc6_ldtx_rect_r ()
1613 RDP ("uc6:ldtx_rect_r\n");
1615 DWORD addr = rdp.cmd1;
1616 uc6_obj_loadtxtr ();
1617 rdp.cmd1 = addr + 24;
1618 uc6_obj_rectangle_r ();
1620 #ifdef _WIN32
1621 static void uc6_rdphalf_0 ()
1623 RDP ("uc6:rdphalf_0\n");
1624 RDP_E ("uc6:rdphalf_0\n");
1626 #endif // _WIN32
1627 static void uc6_rdphalf_1 ()
1629 RDP ("uc6:rdphalf_1\n");
1630 RDP_E ("uc6:rdphalf_1\n");
1633 static void uc6_loaducode ()
1635 RDP ("uc6:load_ucode\n");
1636 RDP_E ("uc6:load_ucode\n");
1638 // copy the microcode data
1639 DWORD addr = segoffset(rdp.cmd1);
1640 DWORD size = (rdp.cmd0 & 0xFFFF) + 1;
1641 memcpy (microcode, gfx.RDRAM+addr, size);
1643 microcheck ();
1646 void drawViRegBG()
1648 DWORD VIwidth = *gfx.VI_WIDTH_REG;
1650 DRAWIMAGE d;
1652 d.imageX = 0;
1653 d.imageW = (WORD)VIwidth;
1654 if (d.imageW%4) d.imageW -= 2;
1655 d.frameX = 0;
1656 d.frameW = (WORD)rdp.vi_width;
1658 d.imageY = 0;
1659 d.imageH = (WORD)rdp.vi_height;
1660 d.frameY = 0;
1661 d.frameH = (WORD)(rdp.vi_height);
1662 RDP ("drawViRegBG\n");
1663 FRDP ("frameX: %f, frameW: %d, frameY: %f, frameH: %d\n", d.frameX, d.frameW, d.frameY, d.frameH);
1664 FRDP ("imageX: %d, imageW: %d, imageY: %d, imageH: %d\n", d.imageX, d.imageW, d.imageY, d.imageH);
1665 if (!settings.RE2)
1667 d.imagePtr = (*gfx.VI_ORIGIN_REG) - (VIwidth<<1);
1668 rdp.last_bg = d.imagePtr;
1669 rdp.cycle_mode = 2;
1670 d.imageSiz = 2;
1671 d.imageFmt = 0;
1672 d.imagePal = 0;
1674 d.scaleX = 1.0f;
1675 d.scaleY = 1.0f;
1676 d.flipX = 0;
1677 d.flipY = 0;
1679 // FRDP ("drawViRegBG imageW :%d, imageH: %d\n", d.imageW, d.imageH);
1680 if (!d.imageW || !d.imageH)
1682 RDP("skipped\n");
1683 return;
1685 DrawImage (&d);
1686 if (settings.lego)
1688 rdp.updatescreen = 1;
1689 newSwapBuffers ();
1690 DrawImage (&d);
1692 return;
1694 //Draw RE2 video
1695 d.imagePtr = (*gfx.VI_ORIGIN_REG) - (VIwidth<<2);
1696 rdp.last_bg = d.imagePtr;
1697 if (d.imageH > 256) d.imageH = 256;
1698 update_screen_count = 0;
1700 if (settings.RE2_native_video) //draw video in native resolution and without conversion.
1702 DWORD * image = new DWORD[d.imageW*d.imageH];
1703 DWORD * src = (DWORD*)(gfx.RDRAM+d.imagePtr);
1704 DWORD * dst = image;
1705 DWORD col;
1706 for (int h = 0; h < d.imageH; h++)
1708 for (int w = 0; w < d.imageW; w++)
1710 col = *(src++);
1711 *(dst++) = col >> 8;
1715 int x = (settings.scr_res_x - d.imageW) / 2;
1716 int y = (settings.scr_res_y - d.imageH) / 2;
1718 grLfbWriteRegion(GR_BUFFER_BACKBUFFER,
1721 GR_LFB_SRC_FMT_888,
1722 d.imageW,
1723 d.imageH,
1724 FXFALSE,
1725 d.imageW<<2,
1726 image);
1727 delete[] image;
1729 else
1732 DWORD * src = (DWORD*)(gfx.RDRAM+d.imagePtr);
1733 GrTexInfo t_info;
1734 t_info.smallLodLog2 = GR_LOD_LOG2_256;
1735 t_info.largeLodLog2 = GR_LOD_LOG2_256;
1736 t_info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
1737 if (sup_32bit_tex) //use 32bit textures
1739 DWORD image[256*256];
1740 DWORD * dst = image;
1741 DWORD col;
1742 for (int h = 0; h < d.imageH; h++)
1744 for (int w = 0; w < 256; w++)
1746 col = *(src++);
1747 *(dst++) = (col >> 8) | 0xFF000000;
1749 src += (d.imageW - 256);
1751 t_info.format = GR_TEXFMT_ARGB_8888;
1752 t_info.data = image;
1753 grTexDownloadMipMap (GR_TMU0,
1754 grTexMinAddress(GR_TMU0)+offset_textures,
1755 GR_MIPMAPLEVELMASK_BOTH,
1756 &t_info);
1758 else
1760 WORD image[256*256];
1761 WORD * dst = image;
1762 DWORD col;
1763 BYTE r, g, b;
1764 for (int h = 0; h < d.imageH; h++)
1766 for (int w = 0; w < 256; w++)
1768 col = *(src++);
1769 r = (BYTE)((col >> 24)&0xFF);
1770 r = (BYTE)((float)r / 255.0f * 31.0f);
1771 g = (BYTE)((col >> 16)&0xFF);
1772 g = (BYTE)((float)g / 255.0f * 63.0f);
1773 b = (BYTE)((col >> 8)&0xFF);
1774 b = (BYTE)((float)b / 255.0f * 31.0f);
1775 *(dst++) = (r << 11) | (g << 5) | b;
1777 src += (d.imageW - 256);
1779 t_info.format = GR_TEXFMT_RGB_565;
1780 t_info.data = image;
1781 grTexDownloadMipMap (GR_TMU0,
1782 grTexMinAddress(GR_TMU0)+offset_textures,
1783 GR_MIPMAPLEVELMASK_BOTH,
1784 &t_info);
1786 grTexSource (GR_TMU0,
1787 grTexMinAddress(GR_TMU0)+offset_textures,
1788 GR_MIPMAPLEVELMASK_BOTH,
1789 &t_info);
1790 grTexCombine( GR_TMU1,
1791 GR_COMBINE_FUNCTION_NONE,
1792 GR_COMBINE_FACTOR_NONE,
1793 GR_COMBINE_FUNCTION_NONE,
1794 GR_COMBINE_FACTOR_NONE,
1795 FXFALSE,
1796 FXFALSE );
1797 grTexCombine( GR_TMU0,
1798 GR_COMBINE_FUNCTION_LOCAL,
1799 GR_COMBINE_FACTOR_NONE,
1800 GR_COMBINE_FUNCTION_LOCAL,
1801 GR_COMBINE_FACTOR_NONE,
1802 FXFALSE,
1803 FXFALSE );
1804 grTexClampMode (GR_TMU0,
1805 GR_TEXTURECLAMP_WRAP,
1806 GR_TEXTURECLAMP_CLAMP);
1807 grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
1808 GR_COMBINE_FACTOR_ONE,
1809 GR_COMBINE_LOCAL_NONE,
1810 GR_COMBINE_OTHER_TEXTURE,
1811 FXFALSE);
1812 grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL,
1813 GR_COMBINE_FACTOR_NONE,
1814 GR_COMBINE_LOCAL_CONSTANT,
1815 GR_COMBINE_OTHER_NONE,
1816 FXFALSE);
1817 grAlphaBlendFunction (GR_BLEND_ONE,
1818 GR_BLEND_ZERO,
1819 GR_BLEND_ONE,
1820 GR_BLEND_ZERO);
1821 grConstantColorValue (0xFFFFFFFF);
1822 grDepthBufferFunction (GR_CMP_ALWAYS);
1823 grDepthMask (FXFALSE);
1825 float scale_y = (float)d.imageW/rdp.vi_height;
1826 float height = settings.scr_res_x/scale_y;
1827 float ul_y = (settings.scr_res_y - height)/2.0f;
1828 float lr_y = settings.scr_res_y - ul_y - 1.0f;
1829 float lr_x = settings.scr_res_x-1.0f;
1830 float lr_u = d.imageW - 1.0f;
1831 float lr_v = d.imageH - 1.0f;
1832 VERTEX v[4] = {
1833 { 0, ul_y, 1.0f, 1.0f, 0, 0, 0, 0 },
1834 { lr_x, ul_y, 1.0f, 1.0f, lr_u, 0, lr_u, 0 },
1835 { 0, lr_y, 1.0f, 1.0f, 0, lr_v, 0, lr_v },
1836 { lr_x, lr_y, 1.0f, 1.0f, lr_u, lr_v, lr_u, lr_v }
1838 for (int i=0; i<4; i++)
1840 v[i].uc(0) = v[i].u0;
1841 v[i].vc(0) = v[i].v0;
1843 grDrawTriangle (&v[0], &v[2], &v[1]);
1844 grDrawTriangle (&v[2], &v[3], &v[1]);
1847 void uc6_sprite2d ()
1849 DWORD a = rdp.pc[rdp.pc_i] & BMASK;
1850 DWORD cmd0 = ((DWORD*)gfx.RDRAM)[a>>2]; //check next command
1851 if ( (cmd0>>24) != 0xBE )
1852 return;
1854 FRDP ("uc6:uc6_sprite2d #%d, #%d\n", rdp.tri_n, rdp.tri_n+1);
1855 DWORD addr = segoffset(rdp.cmd1) >> 1;
1856 DRAWIMAGE d;
1858 d.imagePtr = segoffset(((DWORD*)gfx.RDRAM)[(addr+0)>>1]); // 0,1
1859 DWORD tlut = ((DWORD*)gfx.RDRAM)[(addr + 2) >> 1]; // 2, 3
1860 if (tlut)
1862 rdp.tlut_mode = 2;
1863 load_palette (segoffset(tlut), 0, 256);
1865 WORD stride = (((WORD *)gfx.RDRAM)[(addr+4)^1]); // 4
1866 d.imageW = (((WORD *)gfx.RDRAM)[(addr+5)^1]); // 5
1867 d.imageH = (((WORD *)gfx.RDRAM)[(addr+6)^1]); // 6
1868 d.imageFmt = ((BYTE *)gfx.RDRAM)[(((addr+7)<<1)+0)^3]; // 7
1869 d.imageSiz = ((BYTE *)gfx.RDRAM)[(((addr+7)<<1)+1)^3]; // |
1870 d.imagePal = 0;
1871 d.imageX = (((WORD *)gfx.RDRAM)[(addr+8)^1]); // 8
1872 d.imageY = (((WORD *)gfx.RDRAM)[(addr+9)^1]); // 9
1874 if (d.imageW == 0)
1875 return;// d.imageW = stride;
1877 cmd0 = ((DWORD*)gfx.RDRAM)[a>>2]; //check next command
1878 while (1)
1880 if ( (cmd0>>24) == 0xBE )
1882 DWORD cmd1 = ((DWORD*)gfx.RDRAM)[(a>>2)+1];
1883 rdp.pc[rdp.pc_i] = (a+8) & BMASK;
1885 d.scaleX = ((cmd1>>16)&0xFFFF)/1024.0f;
1886 d.scaleY = (cmd1&0xFFFF)/1024.0f;
1887 if( (cmd1&0xFFFF) < 0x100 )
1888 d.scaleY = d.scaleX;
1889 d.flipX = (BYTE)((cmd0>>8)&0xFF);
1890 d.flipY = (BYTE)(cmd0&0xFF);
1893 a = rdp.pc[rdp.pc_i] & BMASK;
1894 rdp.pc[rdp.pc_i] = (a+8) & BMASK;
1895 cmd0 = ((DWORD*)gfx.RDRAM)[a>>2]; //check next command
1897 if ( (cmd0>>24) == 0xBD )
1899 DWORD cmd1 = ((DWORD*)gfx.RDRAM)[(a>>2)+1];
1901 d.frameX = ((short)((cmd1>>16)&0xFFFF)) / 4.0f;
1902 d.frameY = ((short)(cmd1&0xFFFF)) / 4.0f;
1903 d.frameW = (WORD) (d.imageW / d.scaleX);
1904 d.frameH = (WORD) (d.imageH / d.scaleY);
1905 if (settings.nitro)
1907 int scaleY = (int)d.scaleY;
1908 d.imageH /= scaleY;
1909 d.imageY /= scaleY;
1910 stride *= scaleY;
1911 d.scaleY = 1.0f;
1913 FRDP ("imagePtr: %08lx\n", d.imagePtr);
1914 FRDP ("frameX: %f, frameW: %d, frameY: %f, frameH: %d\n", d.frameX, d.frameW, d.frameY, d.frameH);
1915 FRDP ("imageX: %d, imageW: %d, imageY: %d, imageH: %d\n", d.imageX, d.imageW, d.imageY, d.imageH);
1916 FRDP ("imageFmt: %d, imageSiz: %d, imagePal: %d, imageStride: %d\n", d.imageFmt, d.imageSiz, d.imagePal, stride);
1917 FRDP ("scaleX: %f, scaleY: %f\n", d.scaleX, d.scaleY);
1919 else
1921 return;
1924 DWORD texsize = d.imageW * d.imageH;
1925 if (d.imageSiz == 0)
1926 texsize >>= 1;
1927 else
1928 texsize <<= (d.imageSiz-1);
1930 if (texsize > 4096)
1932 d.imageW = stride;
1933 d.imageH += d.imageY;
1934 DrawImage (&d);
1936 else
1938 WORD line = d.imageW;
1939 if (line & 7) line += 8; // round up
1940 line >>= 3;
1941 if (d.imageSiz == 0)
1943 if (line%2)
1944 line++;
1945 line >>= 1;
1947 else
1949 line <<= (d.imageSiz-1);
1951 if (line == 0)
1952 line = 1;
1954 rdp.timg.addr = d.imagePtr;
1955 rdp.timg.width = stride;
1956 rdp.tiles[7].t_mem = 0;
1957 rdp.tiles[7].line = line;//(d.imageW>>3);
1958 rdp.tiles[7].size = d.imageSiz;
1959 rdp.cmd0 = (d.imageX << 14) | (d.imageY << 2);
1960 rdp.cmd1 = 0x07000000 | ((d.imageX+d.imageW-1) << 14) | ((d.imageY+d.imageH-1) << 2);
1961 rdp_loadtile ();
1963 // SetTile ()
1964 TILE *tile = &rdp.tiles[0];
1965 tile->format = d.imageFmt;
1966 tile->size = d.imageSiz;
1967 tile->line = line;//(d.imageW>>3);
1968 tile->t_mem = 0;
1969 tile->palette = 0;
1970 tile->clamp_t = 1;
1971 tile->mirror_t = 0;
1972 tile->mask_t = 0;
1973 tile->shift_t = 0;
1974 tile->clamp_s = 1;
1975 tile->mirror_s = 0;
1976 tile->mask_s = 0;
1977 tile->shift_s = 0;
1979 // SetTileSize ()
1980 rdp.tiles[0].ul_s = d.imageX;
1981 rdp.tiles[0].ul_t = d.imageY;
1982 rdp.tiles[0].lr_s = d.imageX+d.imageW-1;
1983 rdp.tiles[0].lr_t = d.imageY+d.imageH-1;
1985 float Z = set_sprite_combine_mode ();
1987 float ul_x, ul_y, lr_x, lr_y;
1988 if (d.flipX)
1990 ul_x = d.frameX + d.frameW;
1991 lr_x = d.frameX;
1993 else
1995 ul_x = d.frameX;
1996 lr_x = d.frameX + d.frameW;
1998 if (d.flipY)
2000 ul_y = d.frameY + d.frameH;
2001 lr_y = d.frameY;
2003 else
2005 ul_y = d.frameY;
2006 lr_y = d.frameY + d.frameH;
2009 float lr_u, lr_v;
2010 if (rdp.cur_cache[0]->splits > 1)
2012 lr_u = (float)(d.imageW-1);
2013 lr_v = (float)(d.imageH-1);
2015 else
2017 lr_u = 255.0f*rdp.cur_cache[0]->scale_x;
2018 lr_v = 255.0f*rdp.cur_cache[0]->scale_y;
2021 // Make the vertices
2022 VERTEX v[4] = {
2023 { ul_x, ul_y, Z, 1, 0.5f, 0.5f },
2024 { lr_x, ul_y, Z, 1, lr_u, 0.5f },
2025 { ul_x, lr_y, Z, 1, 0.5f, lr_v },
2026 { lr_x, lr_y, Z, 1, lr_u, lr_v } };
2028 int i;
2029 for (i=0; i<4; i++)
2031 v[i].x *= rdp.scale_x;
2032 v[i].y *= rdp.scale_y;
2035 // ConvertCoordsConvert (v, 4);
2036 AllowShadeMods (v, 4);
2037 for (int s = 0; s < 4; s++)
2038 apply_shade_mods (&(v[s]));
2040 // Set vertex buffers
2041 if (rdp.cur_cache[0]->splits > 1)
2043 VERTEX *vptr[3];
2044 for (i = 0; i < 3; i++)
2045 vptr[i] = &v[i];
2046 draw_splitted_triangle(vptr);
2048 rdp.tri_n ++;
2049 for (i = 0; i < 3; i++)
2050 vptr[i] = &v[i+1];
2051 draw_splitted_triangle(vptr);
2052 rdp.tri_n ++;
2054 else
2056 rdp.vtxbuf = rdp.vtx1; // copy from v to rdp.vtx1
2057 rdp.vtxbuf2 = rdp.vtx2;
2058 rdp.vtx_buffer = 0;
2059 rdp.n_global = 3;
2060 memcpy (rdp.vtxbuf, v, sizeof(VERTEX)*3);
2061 do_triangle_stuff_2 ();
2062 rdp.tri_n ++;
2064 rdp.vtxbuf = rdp.vtx1; // copy from v to rdp.vtx1
2065 rdp.vtxbuf2 = rdp.vtx2;
2066 rdp.vtx_buffer = 0;
2067 rdp.n_global = 3;
2068 memcpy (rdp.vtxbuf, v+1, sizeof(VERTEX)*3);
2069 do_triangle_stuff_2 ();
2070 rdp.tri_n ++;
2072 rdp.update |= UPDATE_ZBUF_ENABLED | UPDATE_VIEWPORT;
2074 if (fullscreen && settings.fog && (rdp.flags & FOG_ENABLED))
2076 grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
2080 a = rdp.pc[rdp.pc_i] & BMASK;
2081 cmd0 = ((DWORD*)gfx.RDRAM)[a>>2]; //check next command
2082 if (( (cmd0>>24) == 0xBD ) || ( (cmd0>>24) == 0xBE ))
2083 rdp.pc[rdp.pc_i] = (a+8) & BMASK;
2084 else
2085 return;