Path: blob/master/libmupen64plus/mupen64plus-video-glide64mk2/src/Glide64/TexBuffer.cpp
2 views
/*1* Glide64 - Glide video plugin for Nintendo 64 emulators.2* Copyright (c) 2002 Dave20013* Copyright (c) 2003-2009 Sergey 'Gonetz' Lipski4*5* This program is free software; you can redistribute it and/or modify6* it under the terms of the GNU General Public License as published by7* the Free Software Foundation; either version 2 of the License, or8* any later version.9*10* This program is distributed in the hope that it will be useful,11* but WITHOUT ANY WARRANTY; without even the implied warranty of12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13* GNU General Public License for more details.14*15* You should have received a copy of the GNU General Public License16* along with this program; if not, write to the Free Software17* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA18*/1920//****************************************************************21//22// Glide64 - Glide Plugin for Nintendo 64 emulators23// Project started on December 29th, 200124//25// Authors:26// Dave2001, original author, founded the project in 2001, left it in 200227// Gugaman, joined the project in 2002, left it in 200228// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 200229// Hiroshi 'KoolSmoky' Morii, joined the project in 200730//31//****************************************************************32//33// To modify Glide64:34// * 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.35// * 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.36//37//****************************************************************38//39// Hardware frame buffer emulation40// Dec 2003 created by Gonetz41//42//****************************************************************4344#include "Gfx_1.3.h"45#include "TexBuffer.h"46#include "CRC.h"4748static TBUFF_COLOR_IMAGE * AllocateTextureBuffer(COLOR_IMAGE & cimage)49{50TBUFF_COLOR_IMAGE texbuf;51texbuf.addr = cimage.addr;52texbuf.end_addr = cimage.addr + ((cimage.width*cimage.height)<<cimage.size>>1);53texbuf.width = cimage.width;54texbuf.height = cimage.height;55texbuf.format = cimage.format;56texbuf.size = cimage.size;57texbuf.scr_width = min(cimage.width * rdp.scale_x, settings.scr_res_x);58float height = min(rdp.vi_height,cimage.height);59if (cimage.status == ci_copy_self || (cimage.status == ci_copy && cimage.width == rdp.frame_buffers[rdp.main_ci_index].width))60height = rdp.vi_height;61texbuf.scr_height = height * rdp.scale_y;62// texbuf.scr_height = texbuf.height * rdp.scale_y;6364wxUint16 max_size = max((wxUint16)texbuf.scr_width, (wxUint16)texbuf.scr_height);65if (max_size > voodoo.max_tex_size) //texture size is too large66return 0;67wxUint32 tex_size;68//calculate LOD69switch ((max_size-1) >> 6)70{71case 0:72texbuf.info.smallLodLog2 = texbuf.info.largeLodLog2 = GR_LOD_LOG2_64;73tex_size = 64;74break;75case 1:76texbuf.info.smallLodLog2 = texbuf.info.largeLodLog2 = GR_LOD_LOG2_128;77tex_size = 128;78break;79case 2:80case 3:81texbuf.info.smallLodLog2 = texbuf.info.largeLodLog2 = GR_LOD_LOG2_256;82tex_size = 256;83break;84case 4:85case 5:86case 6:87case 7:88texbuf.info.smallLodLog2 = texbuf.info.largeLodLog2 = GR_LOD_LOG2_512;89tex_size = 512;90break;91case 8:92case 9:93case 10:94case 11:95case 12:96case 13:97case 14:98case 15:99texbuf.info.smallLodLog2 = texbuf.info.largeLodLog2 = GR_LOD_LOG2_1024;100tex_size = 1024;101break;102default:103texbuf.info.smallLodLog2 = texbuf.info.largeLodLog2 = GR_LOD_LOG2_2048;104tex_size = 2048;105}106//calculate aspect107if (texbuf.scr_width >= texbuf.scr_height)108{109if ((texbuf.scr_width/texbuf.scr_height) >= 2)110{111texbuf.info.aspectRatioLog2 = GR_ASPECT_LOG2_2x1;112texbuf.tex_width = tex_size;113texbuf.tex_height = tex_size >> 1;114}115else116{117texbuf.info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;118texbuf.tex_width = texbuf.tex_height = tex_size;119}120}121else122{123if ((texbuf.scr_height/texbuf.scr_width) >= 2)124{125texbuf.info.aspectRatioLog2 = GR_ASPECT_LOG2_1x2;126texbuf.tex_width = tex_size >> 1;127texbuf.tex_height = tex_size;128}129else130{131texbuf.info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;132texbuf.tex_width = texbuf.tex_height = tex_size;133}134}135if ((cimage.format != 0))// && (cimage.width <= 64))136texbuf.info.format = GR_TEXFMT_ALPHA_INTENSITY_88;137else138texbuf.info.format = GR_TEXFMT_RGB_565;139140texbuf.lr_u = 256.0f * texbuf.scr_width / (float)tex_size;// + 1.0f;141texbuf.lr_v = 256.0f * texbuf.scr_height / (float)tex_size;// + 1.0f;142texbuf.tile = 0;143texbuf.tile_uls = 0;144texbuf.tile_ult = 0;145texbuf.u_shift = 0;146texbuf.v_shift = 0;147texbuf.drawn = FALSE;148texbuf.u_scale = texbuf.lr_u / (float)(texbuf.width);149texbuf.v_scale = texbuf.lr_v / (float)(texbuf.height);150texbuf.cache = 0;151texbuf.crc = 0;152texbuf.t_mem = 0;153154FRDP("\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);155156wxUint32 required = grTexCalcMemRequired(texbuf.info.smallLodLog2, texbuf.info.largeLodLog2,157texbuf.info.aspectRatioLog2, texbuf.info.format);158//find free space159for (int i = 0; i < voodoo.num_tmu; i++)160{161wxUint32 available = 0;162wxUint32 top = 0;163if (rdp.texbufs[i].count)164{165TBUFF_COLOR_IMAGE & t = rdp.texbufs[i].images[rdp.texbufs[i].count - 1];166if (rdp.read_whole_frame || rdp.motionblur)167{168if ((cimage.status == ci_aux) && (rdp.cur_tex_buf == i))169{170top = t.tex_addr + t.tex_width * (int)(t.scr_height+1) * 2;171if (rdp.texbufs[i].end - top < required)172return 0;173}174else175top = rdp.texbufs[i].end;176}177else178top = t.tex_addr + t.tex_width * t.tex_height * 2;179available = rdp.texbufs[i].end - top;180}181else182{183available = rdp.texbufs[i].end - rdp.texbufs[i].begin;184top = rdp.texbufs[i].begin;185}186if (available >= required)187{188rdp.texbufs[i].count++;189rdp.texbufs[i].clear_allowed = FALSE;190texbuf.tex_addr = top;191rdp.cur_tex_buf = i;192texbuf.tmu = rdp.texbufs[i].tmu;193rdp.texbufs[i].images[rdp.texbufs[i].count - 1] = texbuf;194return &(rdp.texbufs[i].images[rdp.texbufs[i].count - 1]);195}196}197//not found. keep recently accessed bank, clear second one198if (!rdp.texbufs[rdp.cur_tex_buf^1].clear_allowed) //can't clear => can't allocate199return 0;200rdp.cur_tex_buf ^= 1;201rdp.texbufs[rdp.cur_tex_buf].count = 1;202rdp.texbufs[rdp.cur_tex_buf].clear_allowed = FALSE;203texbuf.tmu = rdp.texbufs[rdp.cur_tex_buf].tmu;204texbuf.tex_addr = rdp.texbufs[rdp.cur_tex_buf].begin;205rdp.texbufs[rdp.cur_tex_buf].images[0] = texbuf;206return &(rdp.texbufs[rdp.cur_tex_buf].images[0]);207}208209int OpenTextureBuffer(COLOR_IMAGE & cimage)210{211FRDP("OpenTextureBuffer. cur_tex_buf: %d, addr: %08lx, width: %d, height: %d", rdp.cur_tex_buf, cimage.addr, cimage.width, cimage.height);212if (!fullscreen) return FALSE;213214int found = FALSE, search = TRUE;215TBUFF_COLOR_IMAGE *texbuf = 0;216wxUint32 addr = cimage.addr;217if ((settings.hacks&hack_Banjo2) && cimage.status == ci_copy_self)218addr = rdp.frame_buffers[rdp.copy_ci_index].addr;219wxUint32 end_addr = addr + ((cimage.width*cimage.height)<<cimage.size>>1);220if (rdp.motionblur)221{222// if (cimage.format != 0)223// return FALSE;224search = FALSE;225}226if (rdp.read_whole_frame)227{228if (settings.hacks&hack_PMario) //motion blur effects in Paper Mario229{230rdp.cur_tex_buf = rdp.acc_tex_buf;231FRDP("\nread_whole_frame. last allocated bank: %d\n", rdp.acc_tex_buf);232}233else234{235if (!rdp.texbufs[0].clear_allowed || !rdp.texbufs[1].clear_allowed)236{237if (cimage.status == ci_main)238{239texbuf = &(rdp.texbufs[rdp.cur_tex_buf].images[0]);240found = TRUE;241}242else243{244for (int t = 0; (t < rdp.texbufs[rdp.cur_tex_buf].count) && !found; t++)245{246texbuf = &(rdp.texbufs[rdp.cur_tex_buf].images[t]);247if (addr == texbuf->addr && cimage.width == texbuf->width)248{249texbuf->drawn = FALSE;250found = TRUE;251}252}253}254}255search = FALSE;256}257}258if (search)259{260for (int i = 0; (i < voodoo.num_tmu) && !found; i++)261{262for (int j = 0; (j < rdp.texbufs[i].count) && !found; j++)263{264texbuf = &(rdp.texbufs[i].images[j]);265if (addr == texbuf->addr && cimage.width == texbuf->width)266{267//texbuf->height = cimage.height;268//texbuf->end_addr = end_addr;269texbuf->drawn = FALSE;270texbuf->format = (wxUint16)cimage.format;271if ((cimage.format != 0))272texbuf->info.format = GR_TEXFMT_ALPHA_INTENSITY_88;273else274texbuf->info.format = GR_TEXFMT_RGB_565;275texbuf->crc = 0;276texbuf->t_mem = 0;277texbuf->tile = 0;278found = TRUE;279rdp.cur_tex_buf = i;280rdp.texbufs[i].clear_allowed = FALSE;281}282else //check intersection283{284if (!((end_addr <= texbuf->addr) || (addr >= texbuf->end_addr))) //intersected, remove285{286grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT );287grTextureBufferExt( texbuf->tmu, texbuf->tex_addr, texbuf->info.smallLodLog2, texbuf->info.largeLodLog2,288texbuf->info.aspectRatioLog2, texbuf->info.format, GR_MIPMAPLEVELMASK_BOTH );289grDepthMask (FXFALSE);290grBufferClear (0, 0, 0xFFFF);291grDepthMask (FXTRUE);292grRenderBuffer( GR_BUFFER_BACKBUFFER );293rdp.texbufs[i].count--;294if (j < rdp.texbufs[i].count)295memcpy(&(rdp.texbufs[i].images[j]), &(rdp.texbufs[i].images[j+1]), sizeof(TBUFF_COLOR_IMAGE)*(rdp.texbufs[i].count-j));296}297}298}299}300}301else302{303LRDP(" not searched");304}305306if (!found)307{308LRDP(" not found");309texbuf = AllocateTextureBuffer(cimage);310}311else312{313LRDP(" found");314}315316if (!texbuf)317{318LRDP(" KO\n");319return FALSE;320}321322rdp.acc_tex_buf = rdp.cur_tex_buf;323rdp.cur_image = texbuf;324grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT );325grTextureBufferExt( rdp.cur_image->tmu, rdp.cur_image->tex_addr, rdp.cur_image->info.smallLodLog2, rdp.cur_image->info.largeLodLog2,326rdp.cur_image->info.aspectRatioLog2, rdp.cur_image->info.format, GR_MIPMAPLEVELMASK_BOTH );327///*328if (rdp.cur_image->clear && (settings.frame_buffer&fb_hwfbe_buf_clear) && cimage.changed)329{330rdp.cur_image->clear = FALSE;331grDepthMask (FXFALSE);332grBufferClear (0, 0, 0xFFFF);333grDepthMask (FXTRUE);334}335//*/336// memset(gfx.RDRAM+cimage.addr, 0, cimage.width*cimage.height*cimage.size);337FRDP(" 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);338if (!rdp.offset_x_bak)339{340rdp.offset_x_bak = rdp.offset_x;341rdp.offset_x = 0;342}343if (!rdp.offset_y_bak)344{345rdp.offset_y_bak = rdp.offset_y;346rdp.offset_y = 0;347}348rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR;349return TRUE;350}351352static GrTextureFormat_t TexBufSetupCombiner(int force_rgb = FALSE)353{354grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER,355GR_COMBINE_FACTOR_ONE,356GR_COMBINE_LOCAL_NONE,357GR_COMBINE_OTHER_TEXTURE,358// GR_COMBINE_OTHER_CONSTANT,359FXFALSE);360grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,361GR_COMBINE_FACTOR_ONE,362GR_COMBINE_LOCAL_NONE,363GR_COMBINE_OTHER_TEXTURE,364FXFALSE);365// grConstantColorValue (0xFFFFFFFF);366grAlphaBlendFunction (GR_BLEND_ONE, // use alpha compare, but not T0 alpha367GR_BLEND_ZERO,368GR_BLEND_ONE,369GR_BLEND_ZERO);370grClipWindow (0, 0, settings.scr_res_x, settings.scr_res_y);371grDepthBufferFunction (GR_CMP_ALWAYS);372grDepthMask (FXFALSE);373grCullMode (GR_CULL_DISABLE);374grFogMode (GR_FOG_DISABLE);375GrTextureFormat_t buf_format = (rdp.tbuff_tex) ? rdp.tbuff_tex->info.format : GR_TEXFMT_RGB_565;376GrCombineFunction_t color_source = GR_COMBINE_FUNCTION_LOCAL;377if (!force_rgb && rdp.black_ci_index > 0 && rdp.black_ci_index <= rdp.copy_ci_index)378{379color_source = GR_COMBINE_FUNCTION_LOCAL_ALPHA;380buf_format = GR_TEXFMT_ALPHA_INTENSITY_88;381}382if (rdp.tbuff_tex->tmu == GR_TMU0)383{384grTexCombine( GR_TMU1,385GR_COMBINE_FUNCTION_NONE,386GR_COMBINE_FACTOR_NONE,387GR_COMBINE_FUNCTION_NONE,388GR_COMBINE_FACTOR_NONE,389FXFALSE,390FXFALSE );391grTexCombine( GR_TMU0,392color_source,393GR_COMBINE_FACTOR_NONE,394GR_COMBINE_FUNCTION_ZERO,395GR_COMBINE_FACTOR_NONE,396FXFALSE,397FXTRUE );398}399else400{401grTexCombine( GR_TMU1,402color_source,403GR_COMBINE_FACTOR_NONE,404GR_COMBINE_FUNCTION_ZERO,405GR_COMBINE_FACTOR_NONE,406FXFALSE,407FXTRUE );408grTexCombine( GR_TMU0,409GR_COMBINE_FUNCTION_SCALE_OTHER,410GR_COMBINE_FACTOR_ONE,411GR_COMBINE_FUNCTION_SCALE_OTHER,412GR_COMBINE_FACTOR_ONE,413FXFALSE,414FXFALSE );415}416return buf_format;417}418419int CloseTextureBuffer(int draw)420{421if (!fullscreen || !rdp.cur_image)422{423LRDP("CloseTextureBuffer KO\n");424return FALSE;425}426grRenderBuffer( GR_BUFFER_BACKBUFFER );427rdp.offset_x = rdp.offset_x_bak;428rdp.offset_y = rdp.offset_y_bak;429rdp.offset_x_bak = rdp.offset_y_bak = 0;430rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR;431if (!draw)432{433LRDP("CloseTextureBuffer no draw, OK\n");434rdp.cur_image = 0;435return TRUE;436}437rdp.tbuff_tex = rdp.cur_image;438rdp.cur_image = 0;439rdp.tbuff_tex->info.format = TexBufSetupCombiner();440float zero = 0.0f;441float ul_x = rdp.offset_x;442float ul_y = rdp.offset_y;443float lr_x = rdp.tbuff_tex->scr_width + rdp.offset_x;444float lr_y = rdp.tbuff_tex->scr_height + rdp.offset_y;445float lr_u = rdp.tbuff_tex->lr_u;446float lr_v = rdp.tbuff_tex->lr_v;447FRDP("lr_x: %f, lr_y: %f, lr_u: %f, lr_v: %f\n", lr_x, lr_y, lr_u, lr_v);448449450// Make the vertices451VERTEX v[4] = {452{ ul_x, ul_y, 1, 1, zero, zero, zero, zero, {zero, zero, zero, zero} },453{ lr_x, ul_y, 1, 1, lr_u, zero, lr_u, zero, {lr_u, zero, lr_u, zero} },454{ ul_x, lr_y, 1, 1, zero, lr_v, zero, lr_v, {zero, lr_v, zero, lr_v} },455{ lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }456};457458grTexSource( rdp.tbuff_tex->tmu, rdp.tbuff_tex->tex_addr, GR_MIPMAPLEVELMASK_BOTH, &(rdp.tbuff_tex->info) );459grClipWindow (0, 0, settings.res_x, settings.res_y);460grDrawTriangle (&v[0], &v[2], &v[1]);461grDrawTriangle (&v[2], &v[3], &v[1]);462rdp.update |= UPDATE_ZBUF_ENABLED | UPDATE_COMBINE | UPDATE_TEXTURE | UPDATE_ALPHA_COMPARE;463if (settings.fog && (rdp.flags & FOG_ENABLED))464{465grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);466}467LRDP("CloseTextureBuffer draw, OK\n");468rdp.tbuff_tex = 0;469return TRUE;470}471472int CopyTextureBuffer(COLOR_IMAGE & fb_from, COLOR_IMAGE & fb_to)473{474if (!fullscreen)475return FALSE;476FRDP("CopyTextureBuffer from %08x to %08x\n", fb_from.addr, fb_to.addr);477if (rdp.cur_image)478{479rdp.cur_image->crc = 0;480if (rdp.cur_image->addr == fb_to.addr)481return CloseTextureBuffer(TRUE);482rdp.tbuff_tex = rdp.cur_image;483}484else if (!FindTextureBuffer(fb_from.addr, (wxUint16)fb_from.width))485{486LRDP("Can't find 'from' buffer.\n");487return FALSE;488}489if (!OpenTextureBuffer(fb_to))490{491LRDP("Can't open new buffer.\n");492return CloseTextureBuffer(TRUE);493}494rdp.tbuff_tex->crc = 0;495GrTextureFormat_t buf_format = rdp.tbuff_tex->info.format;496rdp.tbuff_tex->info.format = GR_TEXFMT_RGB_565;497TexBufSetupCombiner(TRUE);498float ul_x = 0.0f;499float ul_y = 0.0f;500float lr_x = rdp.tbuff_tex->scr_width;501float lr_y = rdp.tbuff_tex->scr_height;502float zero = 0.0f;503float lr_u = rdp.tbuff_tex->lr_u;504float lr_v = rdp.tbuff_tex->lr_v;505FRDP("lr_x: %f, lr_y: %f\n", lr_x, lr_y);506507508// Make the vertices509VERTEX v[4] = {510{ ul_x, ul_y, 1, 1, zero, zero, zero, zero, {zero, zero, zero, zero} },511{ lr_x, ul_y, 1, 1, lr_u, zero, lr_u, zero, {lr_u, zero, lr_u, zero} },512{ ul_x, lr_y, 1, 1, zero, lr_v, zero, lr_v, {zero, lr_v, zero, lr_v} },513{ lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }514};515516grTexSource( rdp.tbuff_tex->tmu, rdp.tbuff_tex->tex_addr, GR_MIPMAPLEVELMASK_BOTH, &(rdp.tbuff_tex->info) );517grDrawTriangle (&v[0], &v[2], &v[1]);518grDrawTriangle (&v[2], &v[3], &v[1]);519grRenderBuffer( GR_BUFFER_BACKBUFFER );520rdp.offset_x = rdp.offset_x_bak;521rdp.offset_y = rdp.offset_y_bak;522rdp.offset_x_bak = rdp.offset_y_bak = 0;523AddOffset(v, 4);524grClipWindow (0, 0, settings.res_x, settings.res_y);525grDrawTriangle (&v[0], &v[2], &v[1]);526grDrawTriangle (&v[2], &v[3], &v[1]);527rdp.tbuff_tex->info.format = buf_format;528529rdp.update |= UPDATE_ZBUF_ENABLED | UPDATE_COMBINE | UPDATE_TEXTURE | UPDATE_ALPHA_COMPARE;530rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR;531if (settings.fog && (rdp.flags & FOG_ENABLED))532grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);533LRDP("CopyTextureBuffer draw, OK\n");534rdp.tbuff_tex = 0;535rdp.cur_image = 0;536return TRUE;537}538539int CopyDepthBuffer()540{541if (!fullscreen)542return FALSE;543LRDP("CopyDepthBuffer. ");544float bound = 1024.0f;545GrLOD_t LOD = GR_LOD_LOG2_1024;546if (settings.scr_res_x > 1024)547{548bound = 2048.0f;549LOD = GR_LOD_LOG2_2048;550}551rdp.tbuff_tex = &(rdp.texbufs[0].images[0]);552rdp.tbuff_tex->tmu = rdp.texbufs[0].tmu;553rdp.tbuff_tex->info.format = GR_TEXFMT_RGB_565;554rdp.tbuff_tex->info.smallLodLog2 = rdp.tbuff_tex->info.largeLodLog2 = LOD;555rdp.tbuff_tex->info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;556TexBufSetupCombiner(TRUE);557float ul_x = 0.0f;558float ul_y = 0.0f;559float lr_x = bound;560float lr_y = bound;561float zero = 0.0f;562float lr_u = 255.5f;563float lr_v = 255.5f;564FRDP("lr_x: %f, lr_y: %f\n", lr_x, lr_y);565566567// Make the vertices568VERTEX v[4] = {569{ ul_x, ul_y, 1, 1, zero, zero, zero, zero, {zero, zero, zero, zero} },570{ lr_x, ul_y, 1, 1, lr_u, zero, lr_u, zero, {lr_u, zero, lr_u, zero} },571{ ul_x, lr_y, 1, 1, zero, lr_v, zero, lr_v, {zero, lr_v, zero, lr_v} },572{ lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }573};574575grAuxBufferExt( GR_BUFFER_AUXBUFFER );576grTexSource( rdp.texbufs[0].tmu, rdp.texbufs[0].begin, GR_MIPMAPLEVELMASK_BOTH, &(rdp.tbuff_tex->info) );577grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT );578grTextureBufferExt( rdp.texbufs[1].tmu, rdp.texbufs[1].begin, LOD, LOD,579GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH );580grDrawTriangle (&v[0], &v[2], &v[1]);581grDrawTriangle (&v[2], &v[3], &v[1]);582grRenderBuffer( GR_BUFFER_BACKBUFFER );583grTextureAuxBufferExt( rdp.texbufs[1].tmu, rdp.texbufs[1].begin, LOD, LOD,584GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH );585grAuxBufferExt( GR_BUFFER_TEXTUREAUXBUFFER_EXT );586587rdp.update |= UPDATE_ZBUF_ENABLED | UPDATE_COMBINE | UPDATE_TEXTURE | UPDATE_ALPHA_COMPARE;588if (settings.fog && (rdp.flags & FOG_ENABLED))589grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);590LRDP("CopyDepthBuffer draw, OK\n");591rdp.tbuff_tex = 0;592return TRUE;593}594595int SwapTextureBuffer()596{597if (!fullscreen || !rdp.tbuff_tex)598return FALSE;599LRDP("SwapTextureBuffer.");600COLOR_IMAGE ci;601ci.addr = rdp.tbuff_tex->addr;602ci.format = rdp.tbuff_tex->format;603ci.width = rdp.tbuff_tex->width;604ci.height = rdp.tbuff_tex->height;605ci.size = 2;606ci.status = ci_main;607ci.changed = FALSE;608TBUFF_COLOR_IMAGE * texbuf = AllocateTextureBuffer(ci);609if (!texbuf)610{611LRDP("Failed!\n");612return FALSE;613}614TexBufSetupCombiner();615616float ul_x = 0.0f;617float ul_y = 0.0f;618float lr_x = rdp.tbuff_tex->scr_width;619float lr_y = rdp.tbuff_tex->scr_height;620float zero = 0.0f;621float lr_u = rdp.tbuff_tex->lr_u;622float lr_v = rdp.tbuff_tex->lr_v;623624// Make the vertices625VERTEX v[4] = {626{ ul_x, ul_y, 1, 1, zero, zero, zero, zero, {zero, zero, zero, zero} },627{ lr_x, ul_y, 1, 1, lr_u, zero, lr_u, zero, {lr_u, zero, lr_u, zero} },628{ ul_x, lr_y, 1, 1, zero, lr_v, zero, lr_v, {zero, lr_v, zero, lr_v} },629{ lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }630};631632grTexSource( rdp.tbuff_tex->tmu, rdp.tbuff_tex->tex_addr, GR_MIPMAPLEVELMASK_BOTH, &(rdp.tbuff_tex->info) );633texbuf->tile_uls = rdp.tbuff_tex->tile_uls;634texbuf->tile_ult = rdp.tbuff_tex->tile_ult;635texbuf->v_shift = rdp.tbuff_tex->v_shift;636grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT );637grTextureBufferExt( texbuf->tmu, texbuf->tex_addr, texbuf->info.smallLodLog2, texbuf->info.largeLodLog2,638texbuf->info.aspectRatioLog2, texbuf->info.format, GR_MIPMAPLEVELMASK_BOTH );639grDrawTriangle (&v[0], &v[2], &v[1]);640grDrawTriangle (&v[2], &v[3], &v[1]);641rdp.texbufs[rdp.tbuff_tex->tmu].clear_allowed = TRUE;642rdp.texbufs[rdp.tbuff_tex->tmu].count = 0;643texbuf->tile_uls = rdp.tbuff_tex->tile_uls;644texbuf->tile_ult = rdp.tbuff_tex->tile_ult;645texbuf->u_shift = rdp.tbuff_tex->u_shift;646texbuf->v_shift = rdp.tbuff_tex->v_shift;647rdp.tbuff_tex = texbuf;648if (rdp.cur_image)649{650grTextureBufferExt( rdp.cur_image->tmu, rdp.cur_image->tex_addr, rdp.cur_image->info.smallLodLog2, rdp.cur_image->info.largeLodLog2,651rdp.cur_image->info.aspectRatioLog2, rdp.cur_image->info.format, GR_MIPMAPLEVELMASK_BOTH );652}653else654{655grRenderBuffer( GR_BUFFER_BACKBUFFER );656rdp.offset_x = rdp.offset_x_bak;657rdp.offset_y = rdp.offset_y_bak;658rdp.offset_x_bak = rdp.offset_y_bak = 0;659rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR;660}661rdp.update |= UPDATE_ZBUF_ENABLED | UPDATE_COMBINE | UPDATE_TEXTURE | UPDATE_ALPHA_COMPARE;662if (settings.fog && (rdp.flags & FOG_ENABLED))663{664grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);665}666LRDP("SwapTextureBuffer draw, OK\n");667return TRUE;668}669670static wxUint32 CalcCRC(TBUFF_COLOR_IMAGE * pTCI)671{672wxUint32 result = 0;673if ((settings.frame_buffer&fb_ref) > 0)674pTCI->crc = 0; //Since fb content changes each frame, crc check is meaningless.675else if (settings.fb_crc_mode == SETTINGS::fbcrcFast)676result = *((wxUint32*)(gfx.RDRAM + pTCI->addr + (pTCI->end_addr-pTCI->addr)/2));677else if (settings.fb_crc_mode == SETTINGS::fbcrcSafe)678{679wxUint8 * pSrc = gfx.RDRAM + pTCI->addr;680const wxUint32 nSize = pTCI->end_addr-pTCI->addr;681result = CRC32(0xFFFFFFFF, pSrc, 32);682result = CRC32(result, pSrc + (nSize>>1), 32);683result = CRC32(result, pSrc + nSize - 32, 32);684}685return result;686}687688int FindTextureBuffer(wxUint32 addr, wxUint16 width)689{690if (rdp.skip_drawing)691return FALSE;692FRDP("FindTextureBuffer. addr: %08lx, width: %d, scale_x: %f\n", addr, width, rdp.scale_x);693int found = FALSE;694wxUint32 shift = 0;695for (int i = 0; i < voodoo.num_tmu && !found; i++)696{697wxUint8 index = rdp.cur_tex_buf^i;698for (int j = 0; j < rdp.texbufs[index].count && !found; j++)699{700rdp.tbuff_tex = &(rdp.texbufs[index].images[j]);701if(addr >= rdp.tbuff_tex->addr && addr < rdp.tbuff_tex->end_addr)// && rdp.timg.format == 0)702{703bool bCorrect;704if (rdp.tbuff_tex->crc == 0)705{706rdp.tbuff_tex->crc = CalcCRC(rdp.tbuff_tex);707bCorrect = width == 1 || rdp.tbuff_tex->width == width || (rdp.tbuff_tex->width > 320 && rdp.tbuff_tex->width == width*2);708}709else710bCorrect = rdp.tbuff_tex->crc == CalcCRC(rdp.tbuff_tex);711if (bCorrect)712{713shift = addr - rdp.tbuff_tex->addr;714// if (!rdp.motionblur)715if (!rdp.cur_image)716rdp.cur_tex_buf = index;717found = TRUE;718// FRDP("FindTextureBuffer, found in TMU%d buffer: %d\n", rdp.tbuff_tex->tmu, j);719}720else //new texture is loaded into this place, texture buffer is not valid anymore721{722rdp.texbufs[index].count--;723if (j < rdp.texbufs[index].count)724memcpy(&(rdp.texbufs[index].images[j]), &(rdp.texbufs[index].images[j+1]), sizeof(TBUFF_COLOR_IMAGE)*(rdp.texbufs[index].count-j));725}726}727}728}729if (found)730{731rdp.tbuff_tex->tile_uls = 0;732rdp.tbuff_tex->tile_ult = 0;733if (shift > 0)734{735shift >>= 1;736rdp.tbuff_tex->v_shift = shift / rdp.tbuff_tex->width;737rdp.tbuff_tex->u_shift = shift % rdp.tbuff_tex->width;738}739else740{741rdp.tbuff_tex->v_shift = 0;742rdp.tbuff_tex->u_shift = 0;743}744FRDP("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]);745//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);746return TRUE;747}748rdp.tbuff_tex = 0;749LRDP("FindTextureBuffer, not found\n");750return FALSE;751}752753754