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
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
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
42 typedef struct DRAWIMAGE_t
{
61 void DrawHiresDepthImage (DRAWIMAGE
*d
)
63 WORD
* src
= (WORD
*)(gfx
.RDRAM
+d
->imagePtr
);
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
);
75 t_info
.format
= GR_TEXFMT_RGB_565
;
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
,
83 GR_MIPMAPLEVELMASK_BOTH
,
85 grTexSource (rdp
.texbufs
[1].tmu
,
87 GR_MIPMAPLEVELMASK_BOTH
,
89 grTexCombine( GR_TMU1
,
90 GR_COMBINE_FUNCTION_LOCAL
,
91 GR_COMBINE_FACTOR_NONE
,
92 GR_COMBINE_FUNCTION_LOCAL
,
93 GR_COMBINE_FACTOR_NONE
,
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
,
103 grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER
,
104 GR_COMBINE_FACTOR_ONE
,
105 GR_COMBINE_LOCAL_NONE
,
106 GR_COMBINE_OTHER_TEXTURE
,
108 grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER
,
109 GR_COMBINE_FACTOR_ONE
,
110 GR_COMBINE_LOCAL_NONE
,
111 GR_COMBINE_OTHER_TEXTURE
,
113 grAlphaBlendFunction (GR_BLEND_ONE
,
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;
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
)
160 if (d
->imageH
> d
->imageW
)
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
);
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
);
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)
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
;
191 depthbuffersave
= TRUE
;
194 if (settings
.fb_hires
)
196 DrawHiresDepthImage(d
);
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
,
224 void DrawImage (DRAWIMAGE
*d
)
226 if (d
->imageW
== 0 || d
->imageH
== 0 || d
->frameH
== 0) return;
234 // choose optimum size for the format/size
235 if (d
->imageSiz
== 0)
243 if (d
->imageSiz
== 1)
251 if (d
->imageSiz
== 2)
259 if (d
->imageSiz
== 3)
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
)
275 rdp
.update
|= UPDATE_ZBUF_ENABLED
| UPDATE_COMBINE
|
276 UPDATE_ALPHA_COMPARE
| UPDATE_VIEWPORT
;
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);
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
;
301 ul_x
= d
->frameX
+ d
->frameW
;
307 lr_x
= d
->frameX
+ d
->frameW
;
311 ul_y
= d
->frameY
+ d
->frameH
;
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
;
338 TILE
*tile
= &rdp
.tiles
[0];
339 tile
->format
= d
->imageFmt
; // RGBA
340 tile
->size
= d
->imageSiz
; // 16-bit
343 tile
->palette
= (BYTE
)d
->imagePal
;
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
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
377 RDP("Background uses depth compare\n");
378 Z
= ScaleZ(rdp
.prim_depth
);
379 grDepthBufferFunction (GR_CMP_LEQUAL
);
380 grDepthMask (FXTRUE
);
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
);
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
,
409 grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER
,
410 GR_COMBINE_FACTOR_ONE
,
411 GR_COMBINE_LOCAL_NONE
,
412 GR_COMBINE_OTHER_TEXTURE
,
414 grConstantColorValue (0xFFFFFFFF);
415 grAlphaBlendFunction (GR_BLEND_ONE
, // use alpha compare, but not T0 alpha
419 rdp
.update
|= UPDATE_COMBINE
;
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
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
;
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
;
464 cb_u
= ((cur_u
-1)<<x_shift
);
465 while (cb_u
>= d
->imageW
) cb_u
-= d
->imageW
;
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
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;
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);
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
;
506 if ((flr_x
<= rdp
.scissor
.lr_x
) || (ful_x
< rdp
.scissor
.lr_x
))
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
));
529 add_tri (vl
, 3, TRI_BACKGROUND
);
534 add_tri (vl
, 3, TRI_BACKGROUND
);
546 // increment whatever caused this split
547 tb_u
+= x_size
- (x_size
-(nlr_u
-cb_u
));
549 if (nlr_u
== cur_wrap_u
*d
->imageW
) {
553 if (nlr_u
== (cur_u
<<x_shift
)) cur_u
++;
554 if (nlr_u
== lr_u
) break;
559 tb_v
+= y_size
- (y_size
-(nlr_v
-cb_v
));
561 if (nlr_v
== cur_wrap_v
*d
->imageH
) {
565 if (nlr_v
== (cur_v
<<y_shift
)) cur_v
++;
566 if (nlr_v
== lr_v
) break;
571 rdp
.allow_combine
= 1;
573 rdp
.update
|= UPDATE_ZBUF_ENABLED
| UPDATE_COMBINE
| UPDATE_TEXTURE
| UPDATE_ALPHA_COMPARE
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
);
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
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
);
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
,
619 grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER
,
620 GR_COMBINE_FACTOR_ONE
,
621 GR_COMBINE_LOCAL_NONE
,
622 GR_COMBINE_OTHER_TEXTURE
,
624 grConstantColorValue (0xFFFFFFFF);
625 grAlphaBlendFunction (GR_BLEND_ONE
, // use alpha compare, but not T0 alpha
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
,
641 grTexCombine( GR_TMU0
,
642 GR_COMBINE_FUNCTION_LOCAL
,
643 GR_COMBINE_FACTOR_NONE
,
644 GR_COMBINE_FUNCTION_LOCAL
,
645 GR_COMBINE_FACTOR_NONE
,
651 grTexCombine( GR_TMU1
,
652 GR_COMBINE_FUNCTION_LOCAL
,
653 GR_COMBINE_FACTOR_NONE
,
654 GR_COMBINE_FUNCTION_LOCAL
,
655 GR_COMBINE_FACTOR_NONE
,
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
,
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
);
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
;
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;
696 lr_u
= d
->imageX
+ (d
->frameW
* d
->scaleX
) ;
697 lr_v
= d
->imageY
+ (d
->frameH
* d
->scaleY
) ;
702 lr_x
= d
->frameX
+ d
->frameW
;
703 lr_y
= d
->frameY
+ d
->frameH
;
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
;
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 //****************************************************************
740 static void uc6_bg_1cyc ()
742 if (render_depth_mode
== 2) {
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
);
754 if (rdp
.skip_drawing
)
756 RDP("bg_1cyc skipped\n");
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;
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
)
790 if (d
.frameH
== d
.imageH
)
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
))
808 if (settings
.ucode
== 2 || settings
.PPL
)
810 if ( (d
.imagePtr
!= rdp
.cimg
) && (d
.imagePtr
!= rdp
.ocimg
) && d
.imagePtr
) //can't draw from framebuffer
814 RDP("uc6:bg_1cyc skipped\n");
821 static void uc6_bg_copy ()
823 if (render_depth_mode
== 1) {
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
);
835 if (rdp
.skip_drawing
)
837 RDP("bg_copy skipped\n");
840 FRDP ("uc6:bg_copy #%d, #%d\n", rdp
.tri_n
, rdp
.tri_n
+1);
842 DWORD addr
= segoffset(rdp
.cmd1
) >> 1;
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
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
))
879 if (settings
.ucode
== 2 || settings
.PPL
)
881 if ( (d
.imagePtr
!= rdp
.cimg
) && (d
.imagePtr
!= rdp
.ocimg
) && d
.imagePtr
) //can't draw from framebuffer
885 RDP("uc6:bg_copy skipped\n");
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
;
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
;
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
);
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
);
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
;
983 for (i
=0; i
<rdp
.n_global
; i
++)
986 if (j
== rdp
.n_global
) j
= 0;
988 VERTEX
*v1
= &rdp
.vtxbuf2
[i
];
989 VERTEX
*v2
= &rdp
.vtxbuf2
[j
];
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
);
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)
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
;
1057 rdp
.update
|= UPDATE_TEXTURE
;
1059 rdp
.allow_combine
= 1;
1064 grFogMode (GR_FOG_DISABLE
);
1065 if (rdp
.zsrc
== 1 && (rdp
.othermode_l
& 0x00000030))
1067 RDP("Sprite uses depth compare\n");
1069 grDepthBufferFunction (GR_CMP_LEQUAL
);
1070 grDepthMask (FXTRUE
);
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
,
1090 grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER
,
1091 GR_COMBINE_FACTOR_ONE
,
1092 GR_COMBINE_LOCAL_NONE
,
1093 GR_COMBINE_OTHER_TEXTURE
,
1095 grAlphaBlendFunction (GR_BLEND_ONE
,
1099 rdp
.update
|= UPDATE_ALPHA_COMPARE
| UPDATE_COMBINE
| UPDATE_ALPHA_COMPARE
;
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)
1116 for (i
= 0; i
< 3; i
++)
1118 draw_splitted_triangle(vptr
);
1121 for (i
= 0; i
< 3; i
++)
1123 draw_splitted_triangle(vptr
);
1128 rdp
.vtxbuf
= rdp
.vtx1
; // copy from v to rdp.vtx1
1129 rdp
.vtxbuf2
= rdp
.vtx2
;
1132 memcpy (rdp
.vtxbuf
, v
, sizeof(VERTEX
)*3);
1133 do_triangle_stuff_2 ();
1136 rdp
.vtxbuf
= rdp
.vtx1
; // copy from v to rdp.vtx1
1137 rdp
.vtxbuf2
= rdp
.vtx2
;
1140 memcpy (rdp
.vtxbuf
, v
+1, sizeof(VERTEX
)*3);
1141 do_triangle_stuff_2 ();
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]; // |
1173 imageW
= (short)rdp
.scissor_o
.lr_x
- (short)objX
- imageW
;
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
);
1187 if (!rdp
.s2dex_tex_loaded
)
1189 RDP("Texture was not loaded! return\n");
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
;
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 ();
1218 float lr_x
= objX
+ imageW
/scaleW
;
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);
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
1240 if (imageFlags
&0x10) //flipT
1248 // Make the vertices
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
}
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
);
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
;
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 ();
1315 float lr_x
= objX
+ imageW
/scaleW
;
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);
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
1337 if (imageFlags
&0x10) //flipT
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);
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
}
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]; // |
1431 imageW
= (short)rdp
.scissor_o
.lr_x
- (short)objX
- imageW
;
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
;
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
;
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);
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
1501 if (imageFlags
&0x10) //flipT
1509 // Make the vertices
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
}
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;
1558 rdp
.cmd1
= 0x07000000 | (tsize
<< 14) | tline
;
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;
1580 rdp
.cmd1
= 0x07000000 | (twidth
<< 14) | (theight
<< 2);
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;
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 ();
1621 static void uc6_rdphalf_0 ()
1623 RDP ("uc6:rdphalf_0\n");
1624 RDP_E ("uc6:rdphalf_0\n");
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
);
1648 DWORD VIwidth
= *gfx
.VI_WIDTH_REG
;
1653 d
.imageW
= (WORD
)VIwidth
;
1654 if (d
.imageW
%4) d
.imageW
-= 2;
1656 d
.frameW
= (WORD
)rdp
.vi_width
;
1659 d
.imageH
= (WORD
)rdp
.vi_height
;
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
);
1667 d
.imagePtr
= (*gfx
.VI_ORIGIN_REG
) - (VIwidth
<<1);
1668 rdp
.last_bg
= d
.imagePtr
;
1679 // FRDP ("drawViRegBG imageW :%d, imageH: %d\n", d.imageW, d.imageH);
1680 if (!d
.imageW
|| !d
.imageH
)
1688 rdp
.updatescreen
= 1;
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;
1706 for (int h = 0; h < d.imageH; h++)
1708 for (int w = 0; w < d.imageW; w++)
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,
1732 DWORD
* src
= (DWORD
*)(gfx
.RDRAM
+d
.imagePtr
);
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
;
1742 for (int h
= 0; h
< d
.imageH
; h
++)
1744 for (int w
= 0; w
< 256; w
++)
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
,
1760 WORD image
[256*256];
1764 for (int h
= 0; h
< d
.imageH
; h
++)
1766 for (int w
= 0; w
< 256; w
++)
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
,
1786 grTexSource (GR_TMU0
,
1787 grTexMinAddress(GR_TMU0
)+offset_textures
,
1788 GR_MIPMAPLEVELMASK_BOTH
,
1790 grTexCombine( GR_TMU1
,
1791 GR_COMBINE_FUNCTION_NONE
,
1792 GR_COMBINE_FACTOR_NONE
,
1793 GR_COMBINE_FUNCTION_NONE
,
1794 GR_COMBINE_FACTOR_NONE
,
1797 grTexCombine( GR_TMU0
,
1798 GR_COMBINE_FUNCTION_LOCAL
,
1799 GR_COMBINE_FACTOR_NONE
,
1800 GR_COMBINE_FUNCTION_LOCAL
,
1801 GR_COMBINE_FACTOR_NONE
,
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
,
1812 grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL
,
1813 GR_COMBINE_FACTOR_NONE
,
1814 GR_COMBINE_LOCAL_CONSTANT
,
1815 GR_COMBINE_OTHER_NONE
,
1817 grAlphaBlendFunction (GR_BLEND_ONE
,
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
;
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 )
1854 FRDP ("uc6:uc6_sprite2d #%d, #%d\n", rdp
.tri_n
, rdp
.tri_n
+1);
1855 DWORD addr
= segoffset(rdp
.cmd1
) >> 1;
1858 d
.imagePtr
= segoffset(((DWORD
*)gfx
.RDRAM
)[(addr
+0)>>1]); // 0,1
1859 DWORD tlut
= ((DWORD
*)gfx
.RDRAM
)[(addr
+ 2) >> 1]; // 2, 3
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]; // |
1871 d
.imageX
= (((WORD
*)gfx
.RDRAM
)[(addr
+8)^1]); // 8
1872 d
.imageY
= (((WORD
*)gfx
.RDRAM
)[(addr
+9)^1]); // 9
1875 return;// d.imageW = stride;
1877 cmd0
= ((DWORD
*)gfx
.RDRAM
)[a
>>2]; //check next command
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
);
1907 int scaleY
= (int)d
.scaleY
;
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
);
1924 DWORD texsize
= d
.imageW
* d
.imageH
;
1925 if (d
.imageSiz
== 0)
1928 texsize
<<= (d
.imageSiz
-1);
1933 d
.imageH
+= d
.imageY
;
1938 WORD line
= d
.imageW
;
1939 if (line
& 7) line
+= 8; // round up
1941 if (d
.imageSiz
== 0)
1949 line
<<= (d
.imageSiz
-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);
1964 TILE
*tile
= &rdp
.tiles
[0];
1965 tile
->format
= d
.imageFmt
;
1966 tile
->size
= d
.imageSiz
;
1967 tile
->line
= line
;//(d.imageW>>3);
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
;
1990 ul_x
= d
.frameX
+ d
.frameW
;
1996 lr_x
= d
.frameX
+ d
.frameW
;
2000 ul_y
= d
.frameY
+ d
.frameH
;
2006 lr_y
= d
.frameY
+ d
.frameH
;
2010 if (rdp
.cur_cache
[0]->splits
> 1)
2012 lr_u
= (float)(d
.imageW
-1);
2013 lr_v
= (float)(d
.imageH
-1);
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
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
} };
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)
2044 for (i
= 0; i
< 3; i
++)
2046 draw_splitted_triangle(vptr
);
2049 for (i
= 0; i
< 3; i
++)
2051 draw_splitted_triangle(vptr
);
2056 rdp
.vtxbuf
= rdp
.vtx1
; // copy from v to rdp.vtx1
2057 rdp
.vtxbuf2
= rdp
.vtx2
;
2060 memcpy (rdp
.vtxbuf
, v
, sizeof(VERTEX
)*3);
2061 do_triangle_stuff_2 ();
2064 rdp
.vtxbuf
= rdp
.vtx1
; // copy from v to rdp.vtx1
2065 rdp
.vtxbuf2
= rdp
.vtx2
;
2068 memcpy (rdp
.vtxbuf
, v
+1, sizeof(VERTEX
)*3);
2069 do_triangle_stuff_2 ();
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
;