2 * Glide64 - Glide video plugin for Nintendo 64 emulators.
3 * Copyright (c) 2002 Dave2001
4 * Copyright (c) 2003-2009 Sergey 'Gonetz' Lipski
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 //****************************************************************
23 // Glide64 - Glide Plugin for Nintendo 64 emulators
24 // Project started on December 29th, 2001
27 // Dave2001, original author, founded the project in 2001, left it in 2002
28 // Gugaman, joined the project in 2002, left it in 2002
29 // Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
30 // Hiroshi 'KoolSmoky' Morii, joined the project in 2007
32 //****************************************************************
35 // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
36 // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
38 //****************************************************************
40 // Hardware frame buffer emulation
41 // Dec 2003 created by Gonetz
43 //****************************************************************
46 #include "TexBuffer.h"
51 static TBUFF_COLOR_IMAGE * AllocateTextureBuffer(COLOR_IMAGE & cimage)
53 TBUFF_COLOR_IMAGE texbuf;
54 texbuf.addr = cimage.addr;
55 texbuf.end_addr = cimage.addr + ((cimage.width*cimage.height)<<cimage.size>>1);
56 texbuf.width = cimage.width;
57 texbuf.height = cimage.height;
58 texbuf.format = cimage.format;
59 texbuf.size = cimage.size;
60 texbuf.scr_width = min(cimage.width * rdp.scale_x, settings.scr_res_x);
61 float height = min(rdp.vi_height,cimage.height);
62 if (cimage.status == ci_copy_self || (cimage.status == ci_copy && cimage.width == rdp.frame_buffers[rdp.main_ci_index].width))
63 height = rdp.vi_height;
64 texbuf.scr_height = height * rdp.scale_y;
65 // texbuf.scr_height = texbuf.height * rdp.scale_y;
67 wxUint16 max_size = max((wxUint16)texbuf.scr_width, (wxUint16)texbuf.scr_height);
68 if (max_size > voodoo.max_tex_size) //texture size is too large
72 switch ((max_size-1) >> 6)
75 texbuf.info.smallLodLog2 = texbuf.info.largeLodLog2 = GR_LOD_LOG2_64;
79 texbuf.info.smallLodLog2 = texbuf.info.largeLodLog2 = GR_LOD_LOG2_128;
84 texbuf.info.smallLodLog2 = texbuf.info.largeLodLog2 = GR_LOD_LOG2_256;
91 texbuf.info.smallLodLog2 = texbuf.info.largeLodLog2 = GR_LOD_LOG2_512;
102 texbuf.info.smallLodLog2 = texbuf.info.largeLodLog2 = GR_LOD_LOG2_1024;
106 texbuf.info.smallLodLog2 = texbuf.info.largeLodLog2 = GR_LOD_LOG2_2048;
110 if (texbuf.scr_width >= texbuf.scr_height)
112 if ((texbuf.scr_width/texbuf.scr_height) >= 2)
114 texbuf.info.aspectRatioLog2 = GR_ASPECT_LOG2_2x1;
115 texbuf.tex_width = tex_size;
116 texbuf.tex_height = tex_size >> 1;
120 texbuf.info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
121 texbuf.tex_width = texbuf.tex_height = tex_size;
126 if ((texbuf.scr_height/texbuf.scr_width) >= 2)
128 texbuf.info.aspectRatioLog2 = GR_ASPECT_LOG2_1x2;
129 texbuf.tex_width = tex_size >> 1;
130 texbuf.tex_height = tex_size;
134 texbuf.info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
135 texbuf.tex_width = texbuf.tex_height = tex_size;
138 if ((cimage.format != 0))// && (cimage.width <= 64))
139 texbuf.info.format = GR_TEXFMT_ALPHA_INTENSITY_88;
141 texbuf.info.format = GR_TEXFMT_RGB_565;
143 texbuf.lr_u = 256.0f * texbuf.scr_width / (float)tex_size;// + 1.0f;
144 texbuf.lr_v = 256.0f * texbuf.scr_height / (float)tex_size;// + 1.0f;
150 texbuf.drawn = FALSE;
151 texbuf.u_scale = texbuf.lr_u / (float)(texbuf.width);
152 texbuf.v_scale = texbuf.lr_v / (float)(texbuf.height);
157 FRDP("\nAllocateTextureBuffer. width: %d, height: %d, scr_width: %f, scr_height: %f, vi_width: %f, vi_height:%f, scale_x: %f, scale_y: %f, lr_u: %f, lr_v: %f, u_scale: %f, v_scale: %f\n", texbuf.width, texbuf.height, texbuf.scr_width, texbuf.scr_height, rdp.vi_width, rdp.vi_height, rdp.scale_x, rdp.scale_y, texbuf.lr_u, texbuf.lr_v, texbuf.u_scale, texbuf.v_scale);
159 wxUint32 required = grTexCalcMemRequired(texbuf.info.smallLodLog2, texbuf.info.largeLodLog2,
160 texbuf.info.aspectRatioLog2, texbuf.info.format);
162 for (int i = 0; i < voodoo.num_tmu; i++)
164 wxUint32 available = 0;
166 if (rdp.texbufs[i].count)
168 TBUFF_COLOR_IMAGE & t = rdp.texbufs[i].images[rdp.texbufs[i].count - 1];
169 if (rdp.read_whole_frame || rdp.motionblur)
171 if ((cimage.status == ci_aux) && (rdp.cur_tex_buf == i))
173 top = t.tex_addr + t.tex_width * (int)(t.scr_height+1) * 2;
174 if (rdp.texbufs[i].end - top < required)
178 top = rdp.texbufs[i].end;
181 top = t.tex_addr + t.tex_width * t.tex_height * 2;
182 available = rdp.texbufs[i].end - top;
186 available = rdp.texbufs[i].end - rdp.texbufs[i].begin;
187 top = rdp.texbufs[i].begin;
189 if (available >= required)
191 rdp.texbufs[i].count++;
192 rdp.texbufs[i].clear_allowed = FALSE;
193 texbuf.tex_addr = top;
195 texbuf.tmu = rdp.texbufs[i].tmu;
196 rdp.texbufs[i].images[rdp.texbufs[i].count - 1] = texbuf;
197 return &(rdp.texbufs[i].images[rdp.texbufs[i].count - 1]);
200 //not found. keep recently accessed bank, clear second one
201 if (!rdp.texbufs[rdp.cur_tex_buf^1].clear_allowed) //can't clear => can't allocate
203 rdp.cur_tex_buf ^= 1;
204 rdp.texbufs[rdp.cur_tex_buf].count = 1;
205 rdp.texbufs[rdp.cur_tex_buf].clear_allowed = FALSE;
206 texbuf.tmu = rdp.texbufs[rdp.cur_tex_buf].tmu;
207 texbuf.tex_addr = rdp.texbufs[rdp.cur_tex_buf].begin;
208 rdp.texbufs[rdp.cur_tex_buf].images[0] = texbuf;
209 return &(rdp.texbufs[rdp.cur_tex_buf].images[0]);
212 int OpenTextureBuffer(COLOR_IMAGE & cimage)
214 //printf("OpenTextureBuffer. cur_tex_buf: %d, addr: %08lx, width: %d, height: %d\n", rdp.cur_tex_buf, cimage.addr, cimage.width, cimage.height);
215 //unsigned int ticks = ticksGetTicks();
216 FRDP("OpenTextureBuffer. cur_tex_buf: %d, addr: %08lx, width: %d, height: %d", rdp.cur_tex_buf, cimage.addr, cimage.width, cimage.height);
217 if (!fullscreen) return FALSE;
219 int found = FALSE, search = TRUE;
220 TBUFF_COLOR_IMAGE *texbuf = 0;
221 wxUint32 addr = cimage.addr;
222 if ((settings.hacks&hack_Banjo2) && cimage.status == ci_copy_self)
223 addr = rdp.frame_buffers[rdp.copy_ci_index].addr;
224 wxUint32 end_addr = addr + ((cimage.width*cimage.height)<<cimage.size>>1);
227 // if (cimage.format != 0)
231 if (rdp.read_whole_frame)
233 if (settings.hacks&hack_PMario) //motion blur effects in Paper Mario
235 rdp.cur_tex_buf = rdp.acc_tex_buf;
236 FRDP("\nread_whole_frame. last allocated bank: %d\n", rdp.acc_tex_buf);
240 if (!rdp.texbufs[0].clear_allowed || !rdp.texbufs[1].clear_allowed)
242 if (cimage.status == ci_main)
244 texbuf = &(rdp.texbufs[rdp.cur_tex_buf].images[0]);
249 for (int t = 0; (t < rdp.texbufs[rdp.cur_tex_buf].count) && !found; t++)
251 texbuf = &(rdp.texbufs[rdp.cur_tex_buf].images[t]);
252 if (addr == texbuf->addr && cimage.width == texbuf->width)
254 texbuf->drawn = FALSE;
265 //printf("search ! (%i) : ", voodoo.num_tmu);
266 for (int i = 0; (i < voodoo.num_tmu) && !found; i++)
268 //printf("[%i] ", rdp.texbufs[i].count);
269 for (int j = 0; (j < rdp.texbufs[i].count) && !found; j++)
271 texbuf = &(rdp.texbufs[i].images[j]);
272 if (addr == texbuf->addr && cimage.width == texbuf->width)
274 //texbuf->height = cimage.height;
275 //texbuf->end_addr = end_addr;
276 texbuf->drawn = FALSE;
277 texbuf->format = (wxUint16)cimage.format;
278 if ((cimage.format != 0))
279 texbuf->info.format = GR_TEXFMT_ALPHA_INTENSITY_88;
281 texbuf->info.format = GR_TEXFMT_RGB_565;
287 rdp.texbufs[i].clear_allowed = FALSE;
289 else //check intersection
291 if (!((end_addr <= texbuf->addr) || (addr >= texbuf->end_addr))) //intersected, remove
293 grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT );
294 grTextureBufferExt( texbuf->tmu, texbuf->tex_addr, texbuf->info.smallLodLog2, texbuf->info.largeLodLog2,
295 texbuf->info.aspectRatioLog2, texbuf->info.format, GR_MIPMAPLEVELMASK_BOTH );
296 grDepthMask (FXFALSE);
297 grBufferClear (0, 0, 0xFFFF);
298 grDepthMask (FXTRUE);
299 grRenderBuffer( GR_BUFFER_BACKBUFFER );
300 rdp.texbufs[i].count--;
301 if (j < rdp.texbufs[i].count)
302 memcpy(&(rdp.texbufs[i].images[j]), &(rdp.texbufs[i].images[j+1]), sizeof(TBUFF_COLOR_IMAGE)*(rdp.texbufs[i].count-j));
310 LRDP(" not searched");
316 texbuf = AllocateTextureBuffer(cimage);
317 //printf(" not found\n");
322 //printf(" found\n");
331 //unsigned int tticks=ticksGetTicks();
332 rdp.acc_tex_buf = rdp.cur_tex_buf;
333 rdp.cur_image = texbuf;
334 grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT );
335 grTextureBufferExt( rdp.cur_image->tmu, rdp.cur_image->tex_addr, rdp.cur_image->info.smallLodLog2, rdp.cur_image->info.largeLodLog2,
336 rdp.cur_image->info.aspectRatioLog2, rdp.cur_image->info.format, GR_MIPMAPLEVELMASK_BOTH );
338 //printf("mesured %u ms\n", ticksGetTicks()-tticks);
339 if (rdp.cur_image->clear && (settings.frame_buffer&fb_hwfbe_buf_clear) && cimage.changed)
341 rdp.cur_image->clear = FALSE;
342 grDepthMask (FXFALSE);
343 grBufferClear (0, 0, 0xFFFF);
344 grDepthMask (FXTRUE);
348 // memset(gfx.RDRAM+cimage.addr, 0, cimage.width*cimage.height*cimage.size);
349 FRDP(" texaddr: %08lx, tex_width: %d, tex_height: %d, cur_tex_buf: %d, texformat: %d, motionblur: %d\n", rdp.cur_image->tex_addr, rdp.cur_image->tex_width, rdp.cur_image->tex_height, rdp.cur_tex_buf, rdp.cur_image->info.format, rdp.motionblur);
350 //printf(" time = %u ms, texaddr: %08x, tex_width: %d, tex_height: %d, cur_tex_buf: %d, texformat: %d, motionblur: %d\n", ticksGetTicks()-ticks, rdp.cur_image->tex_addr, rdp.cur_image->tex_width, rdp.cur_image->tex_height, rdp.cur_tex_buf, rdp.cur_image->info.format, rdp.motionblur);
351 if (!rdp.offset_x_bak)
353 rdp.offset_x_bak = rdp.offset_x;
356 if (!rdp.offset_y_bak)
358 rdp.offset_y_bak = rdp.offset_y;
361 rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR;
366 static GrTextureFormat_t TexBufSetupCombiner(int force_rgb = FALSE)
368 grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER,
369 GR_COMBINE_FACTOR_ONE,
370 GR_COMBINE_LOCAL_NONE,
371 GR_COMBINE_OTHER_TEXTURE,
372 // GR_COMBINE_OTHER_CONSTANT,
374 grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
375 GR_COMBINE_FACTOR_ONE,
376 GR_COMBINE_LOCAL_NONE,
377 GR_COMBINE_OTHER_TEXTURE,
379 // grConstantColorValue (0xFFFFFFFF);
380 grAlphaBlendFunction (GR_BLEND_ONE, // use alpha compare, but not T0 alpha
384 grClipWindow (0, 0, settings.scr_res_x, settings.scr_res_y);
385 grDepthBufferFunction (GR_CMP_ALWAYS);
386 grDepthMask (FXFALSE);
387 grCullMode (GR_CULL_DISABLE);
388 grFogMode (GR_FOG_DISABLE);
389 GrTextureFormat_t buf_format = (rdp.tbuff_tex) ? rdp.tbuff_tex->info.format : GR_TEXFMT_RGB_565;
390 GrCombineFunction_t color_source = GR_COMBINE_FUNCTION_LOCAL;
391 if (!force_rgb && rdp.black_ci_index > 0 && rdp.black_ci_index <= rdp.copy_ci_index)
393 color_source = GR_COMBINE_FUNCTION_LOCAL_ALPHA;
394 buf_format = GR_TEXFMT_ALPHA_INTENSITY_88;
396 if (rdp.tbuff_tex->tmu == GR_TMU0)
398 grTexCombine( GR_TMU1,
399 GR_COMBINE_FUNCTION_NONE,
400 GR_COMBINE_FACTOR_NONE,
401 GR_COMBINE_FUNCTION_NONE,
402 GR_COMBINE_FACTOR_NONE,
405 grTexCombine( GR_TMU0,
407 GR_COMBINE_FACTOR_NONE,
408 GR_COMBINE_FUNCTION_ZERO,
409 GR_COMBINE_FACTOR_NONE,
415 grTexCombine( GR_TMU1,
417 GR_COMBINE_FACTOR_NONE,
418 GR_COMBINE_FUNCTION_ZERO,
419 GR_COMBINE_FACTOR_NONE,
422 grTexCombine( GR_TMU0,
423 GR_COMBINE_FUNCTION_SCALE_OTHER,
424 GR_COMBINE_FACTOR_ONE,
425 GR_COMBINE_FUNCTION_SCALE_OTHER,
426 GR_COMBINE_FACTOR_ONE,
433 int CloseTextureBuffer(int draw)
435 if (!fullscreen || !rdp.cur_image)
437 LRDP("CloseTextureBuffer KO\n");
440 grRenderBuffer( GR_BUFFER_BACKBUFFER );
441 rdp.offset_x = rdp.offset_x_bak;
442 rdp.offset_y = rdp.offset_y_bak;
443 rdp.offset_x_bak = rdp.offset_y_bak = 0;
444 rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR;
447 LRDP("CloseTextureBuffer no draw, OK\n");
451 rdp.tbuff_tex = rdp.cur_image;
453 rdp.tbuff_tex->info.format = TexBufSetupCombiner();
455 float ul_x = rdp.offset_x;
456 float ul_y = rdp.offset_y;
457 float lr_x = rdp.tbuff_tex->scr_width + rdp.offset_x;
458 float lr_y = rdp.tbuff_tex->scr_height + rdp.offset_y;
459 float lr_u = rdp.tbuff_tex->lr_u;
460 float lr_v = rdp.tbuff_tex->lr_v;
461 FRDP("lr_x: %f, lr_y: %f, lr_u: %f, lr_v: %f\n", lr_x, lr_y, lr_u, lr_v);
466 { ul_x, ul_y, 1, 1, zero, zero, zero, zero, {zero, zero, zero, zero} },
467 { lr_x, ul_y, 1, 1, lr_u, zero, lr_u, zero, {lr_u, zero, lr_u, zero} },
468 { ul_x, lr_y, 1, 1, zero, lr_v, zero, lr_v, {zero, lr_v, zero, lr_v} },
469 { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }
472 grTexSource( rdp.tbuff_tex->tmu, rdp.tbuff_tex->tex_addr, GR_MIPMAPLEVELMASK_BOTH, &(rdp.tbuff_tex->info) );
473 grClipWindow (0, 0, settings.res_x, settings.res_y);
474 grDrawTriangle (&v[0], &v[2], &v[1]);
475 grDrawTriangle (&v[2], &v[3], &v[1]);
476 rdp.update |= UPDATE_ZBUF_ENABLED | UPDATE_COMBINE | UPDATE_TEXTURE | UPDATE_ALPHA_COMPARE;
477 if (settings.fog && (rdp.flags & FOG_ENABLED))
479 grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
481 LRDP("CloseTextureBuffer draw, OK\n");
486 int CopyTextureBuffer(COLOR_IMAGE & fb_from, COLOR_IMAGE & fb_to)
490 FRDP("CopyTextureBuffer from %08x to %08x\n", fb_from.addr, fb_to.addr);
493 rdp.cur_image->crc = 0;
494 if (rdp.cur_image->addr == fb_to.addr)
495 return CloseTextureBuffer(TRUE);
496 rdp.tbuff_tex = rdp.cur_image;
498 else if (!FindTextureBuffer(fb_from.addr, (wxUint16)fb_from.width))
500 LRDP("Can't find 'from' buffer.\n");
503 if (!OpenTextureBuffer(fb_to))
505 LRDP("Can't open new buffer.\n");
506 return CloseTextureBuffer(TRUE);
508 rdp.tbuff_tex->crc = 0;
509 GrTextureFormat_t buf_format = rdp.tbuff_tex->info.format;
510 rdp.tbuff_tex->info.format = GR_TEXFMT_RGB_565;
511 TexBufSetupCombiner(TRUE);
514 float lr_x = rdp.tbuff_tex->scr_width;
515 float lr_y = rdp.tbuff_tex->scr_height;
517 float lr_u = rdp.tbuff_tex->lr_u;
518 float lr_v = rdp.tbuff_tex->lr_v;
519 FRDP("lr_x: %f, lr_y: %f\n", lr_x, lr_y);
524 { ul_x, ul_y, 1, 1, zero, zero, zero, zero, {zero, zero, zero, zero} },
525 { lr_x, ul_y, 1, 1, lr_u, zero, lr_u, zero, {lr_u, zero, lr_u, zero} },
526 { ul_x, lr_y, 1, 1, zero, lr_v, zero, lr_v, {zero, lr_v, zero, lr_v} },
527 { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }
530 grTexSource( rdp.tbuff_tex->tmu, rdp.tbuff_tex->tex_addr, GR_MIPMAPLEVELMASK_BOTH, &(rdp.tbuff_tex->info) );
531 grDrawTriangle (&v[0], &v[2], &v[1]);
532 grDrawTriangle (&v[2], &v[3], &v[1]);
533 grRenderBuffer( GR_BUFFER_BACKBUFFER );
534 rdp.offset_x = rdp.offset_x_bak;
535 rdp.offset_y = rdp.offset_y_bak;
536 rdp.offset_x_bak = rdp.offset_y_bak = 0;
538 grClipWindow (0, 0, settings.res_x, settings.res_y);
539 grDrawTriangle (&v[0], &v[2], &v[1]);
540 grDrawTriangle (&v[2], &v[3], &v[1]);
541 rdp.tbuff_tex->info.format = buf_format;
543 rdp.update |= UPDATE_ZBUF_ENABLED | UPDATE_COMBINE | UPDATE_TEXTURE | UPDATE_ALPHA_COMPARE;
544 rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR;
545 if (settings.fog && (rdp.flags & FOG_ENABLED))
546 grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
547 LRDP("CopyTextureBuffer draw, OK\n");
553 int CopyDepthBuffer()
557 LRDP("CopyDepthBuffer. ");
558 float bound = 1024.0f;
559 GrLOD_t LOD = GR_LOD_LOG2_1024;
560 if (settings.scr_res_x > 1024)
563 LOD = GR_LOD_LOG2_2048;
565 rdp.tbuff_tex = &(rdp.texbufs[0].images[0]);
566 rdp.tbuff_tex->tmu = rdp.texbufs[0].tmu;
567 rdp.tbuff_tex->info.format = GR_TEXFMT_RGB_565;
568 rdp.tbuff_tex->info.smallLodLog2 = rdp.tbuff_tex->info.largeLodLog2 = LOD;
569 rdp.tbuff_tex->info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
570 TexBufSetupCombiner(TRUE);
578 FRDP("lr_x: %f, lr_y: %f\n", lr_x, lr_y);
583 { ul_x, ul_y, 1, 1, zero, zero, zero, zero, {zero, zero, zero, zero} },
584 { lr_x, ul_y, 1, 1, lr_u, zero, lr_u, zero, {lr_u, zero, lr_u, zero} },
585 { ul_x, lr_y, 1, 1, zero, lr_v, zero, lr_v, {zero, lr_v, zero, lr_v} },
586 { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }
589 grAuxBufferExt( GR_BUFFER_AUXBUFFER );
590 grTexSource( rdp.texbufs[0].tmu, rdp.texbufs[0].begin, GR_MIPMAPLEVELMASK_BOTH, &(rdp.tbuff_tex->info) );
591 grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT );
592 grTextureBufferExt( rdp.texbufs[1].tmu, rdp.texbufs[1].begin, LOD, LOD,
593 GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH );
594 grDrawTriangle (&v[0], &v[2], &v[1]);
595 grDrawTriangle (&v[2], &v[3], &v[1]);
596 grRenderBuffer( GR_BUFFER_BACKBUFFER );
597 grTextureAuxBufferExt( rdp.texbufs[1].tmu, rdp.texbufs[1].begin, LOD, LOD,
598 GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH );
599 grAuxBufferExt( GR_BUFFER_TEXTUREAUXBUFFER_EXT );
601 rdp.update |= UPDATE_ZBUF_ENABLED | UPDATE_COMBINE | UPDATE_TEXTURE | UPDATE_ALPHA_COMPARE;
602 if (settings.fog && (rdp.flags & FOG_ENABLED))
603 grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
604 LRDP("CopyDepthBuffer draw, OK\n");
609 int SwapTextureBuffer()
611 if (!fullscreen || !rdp.tbuff_tex)
613 LRDP("SwapTextureBuffer.");
615 ci.addr = rdp.tbuff_tex->addr;
616 ci.format = rdp.tbuff_tex->format;
617 ci.width = rdp.tbuff_tex->width;
618 ci.height = rdp.tbuff_tex->height;
622 TBUFF_COLOR_IMAGE * texbuf = AllocateTextureBuffer(ci);
628 TexBufSetupCombiner();
632 float lr_x = rdp.tbuff_tex->scr_width;
633 float lr_y = rdp.tbuff_tex->scr_height;
635 float lr_u = rdp.tbuff_tex->lr_u;
636 float lr_v = rdp.tbuff_tex->lr_v;
640 { ul_x, ul_y, 1, 1, zero, zero, zero, zero, {zero, zero, zero, zero} },
641 { lr_x, ul_y, 1, 1, lr_u, zero, lr_u, zero, {lr_u, zero, lr_u, zero} },
642 { ul_x, lr_y, 1, 1, zero, lr_v, zero, lr_v, {zero, lr_v, zero, lr_v} },
643 { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }
646 grTexSource( rdp.tbuff_tex->tmu, rdp.tbuff_tex->tex_addr, GR_MIPMAPLEVELMASK_BOTH, &(rdp.tbuff_tex->info) );
647 texbuf->tile_uls = rdp.tbuff_tex->tile_uls;
648 texbuf->tile_ult = rdp.tbuff_tex->tile_ult;
649 texbuf->v_shift = rdp.tbuff_tex->v_shift;
650 grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT );
651 grTextureBufferExt( texbuf->tmu, texbuf->tex_addr, texbuf->info.smallLodLog2, texbuf->info.largeLodLog2,
652 texbuf->info.aspectRatioLog2, texbuf->info.format, GR_MIPMAPLEVELMASK_BOTH );
653 grDrawTriangle (&v[0], &v[2], &v[1]);
654 grDrawTriangle (&v[2], &v[3], &v[1]);
655 rdp.texbufs[rdp.tbuff_tex->tmu].clear_allowed = TRUE;
656 rdp.texbufs[rdp.tbuff_tex->tmu].count = 0;
657 texbuf->tile_uls = rdp.tbuff_tex->tile_uls;
658 texbuf->tile_ult = rdp.tbuff_tex->tile_ult;
659 texbuf->u_shift = rdp.tbuff_tex->u_shift;
660 texbuf->v_shift = rdp.tbuff_tex->v_shift;
661 rdp.tbuff_tex = texbuf;
664 grTextureBufferExt( rdp.cur_image->tmu, rdp.cur_image->tex_addr, rdp.cur_image->info.smallLodLog2, rdp.cur_image->info.largeLodLog2,
665 rdp.cur_image->info.aspectRatioLog2, rdp.cur_image->info.format, GR_MIPMAPLEVELMASK_BOTH );
669 grRenderBuffer( GR_BUFFER_BACKBUFFER );
670 rdp.offset_x = rdp.offset_x_bak;
671 rdp.offset_y = rdp.offset_y_bak;
672 rdp.offset_x_bak = rdp.offset_y_bak = 0;
673 rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR;
675 rdp.update |= UPDATE_ZBUF_ENABLED | UPDATE_COMBINE | UPDATE_TEXTURE | UPDATE_ALPHA_COMPARE;
676 if (settings.fog && (rdp.flags & FOG_ENABLED))
678 grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
680 LRDP("SwapTextureBuffer draw, OK\n");
684 static wxUint32 CalcCRC(TBUFF_COLOR_IMAGE * pTCI)
687 if ((settings.frame_buffer&fb_ref) > 0)
688 pTCI->crc = 0; //Since fb content changes each frame, crc check is meaningless.
689 else if (settings.fb_crc_mode == SETTINGS::fbcrcFast)
690 result = *((wxUint32*)(gfx.RDRAM + pTCI->addr + (pTCI->end_addr-pTCI->addr)/2));
691 else if (settings.fb_crc_mode == SETTINGS::fbcrcSafe)
693 wxUint8 * pSrc = gfx.RDRAM + pTCI->addr;
694 const wxUint32 nSize = pTCI->end_addr-pTCI->addr;
695 result = CRC32(0xFFFFFFFF, pSrc, 32);
696 result = CRC32(result, pSrc + (nSize>>1), 32);
697 result = CRC32(result, pSrc + nSize - 32, 32);
702 int FindTextureBuffer(wxUint32 addr, wxUint16 width)
704 if (rdp.skip_drawing)
706 FRDP("FindTextureBuffer. addr: %08lx, width: %d, scale_x: %f\n", addr, width, rdp.scale_x);
709 for (int i = 0; i < voodoo.num_tmu && !found; i++)
711 wxUint8 index = rdp.cur_tex_buf^i;
712 for (int j = 0; j < rdp.texbufs[index].count && !found; j++)
714 rdp.tbuff_tex = &(rdp.texbufs[index].images[j]);
715 if(addr >= rdp.tbuff_tex->addr && addr < rdp.tbuff_tex->end_addr)// && rdp.timg.format == 0)
718 if (rdp.tbuff_tex->crc == 0)
720 rdp.tbuff_tex->crc = CalcCRC(rdp.tbuff_tex);
721 bCorrect = width == 1 || rdp.tbuff_tex->width == width || (rdp.tbuff_tex->width > 320 && rdp.tbuff_tex->width == width*2);
724 bCorrect = rdp.tbuff_tex->crc == CalcCRC(rdp.tbuff_tex);
727 shift = addr - rdp.tbuff_tex->addr;
728 // if (!rdp.motionblur)
730 rdp.cur_tex_buf = index;
732 // FRDP("FindTextureBuffer, found in TMU%d buffer: %d\n", rdp.tbuff_tex->tmu, j);
734 else //new texture is loaded into this place, texture buffer is not valid anymore
736 rdp.texbufs[index].count--;
737 if (j < rdp.texbufs[index].count)
738 memcpy(&(rdp.texbufs[index].images[j]), &(rdp.texbufs[index].images[j+1]), sizeof(TBUFF_COLOR_IMAGE)*(rdp.texbufs[index].count-j));
745 rdp.tbuff_tex->tile_uls = 0;
746 rdp.tbuff_tex->tile_ult = 0;
750 rdp.tbuff_tex->v_shift = shift / rdp.tbuff_tex->width;
751 rdp.tbuff_tex->u_shift = shift % rdp.tbuff_tex->width;
755 rdp.tbuff_tex->v_shift = 0;
756 rdp.tbuff_tex->u_shift = 0;
758 FRDP("FindTextureBuffer, found, u_shift: %d, v_shift: %d, format: %s\n", rdp.tbuff_tex->u_shift, rdp.tbuff_tex->v_shift, str_format[rdp.tbuff_tex->format]);
759 //FRDP("Buffer, addr=%08lx, end_addr=%08lx, width: %d, height: %d\n", rdp.tbuff_tex->addr, rdp.tbuff_tex->end_addr, rdp.tbuff_tex->width, rdp.tbuff_tex->height);
763 LRDP("FindTextureBuffer, not found\n");