2 Copyright (C) 2005 Rice1964
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 // ===========================================================================
24 #include "ConvertImage.h"
25 #include "DeviceBuilder.h"
26 #include "FrameBuffer.h"
27 #include "UcodeDefs.h"
28 #include "RSP_Parser.h"
31 extern TMEMLoadMapInfo g_tmemLoadAddrMap[0x200]; // Totally 4KB TMEM;
33 // 0 keeps the most recent CI info
34 // 1 keeps the frame buffer CI info which is being displayed now
35 // 2 keeps the older frame buffer CI info. This can be used if we are using triple buffer
36 /* Overview of framebuffer implementation
37 1) Check if backbuffer has changed, via different detection techniques
38 2) If changed, we copy the GFX card's backbuffer to main RAM
39 3) This is slow due to the reading process, not the writing
42 RecentCIInfo g_RecentCIInfo[5];
43 RecentCIInfo *g_uRecentCIInfoPtrs[5] =
52 int numOfRecentCIInfos = 5;
54 RecentViOriginInfo g_RecentVIOriginInfo[5];
55 uint32 dwBackBufferSavedAtFrame=0;
57 RenderTextureInfo gRenderTextureInfos[20];
58 int numOfTxtBufInfos = sizeof(gRenderTextureInfos)/sizeof(RenderTextureInfo);
59 RenderTextureInfo *g_pRenderTextureInfo = NULL;
61 FrameBufferManager* g_pFrameBufferManager = NULL;
63 bool LastCIIsNewCI=false;
65 FrameBufferManager::FrameBufferManager() :
66 m_isRenderingToTexture(false),
67 m_curRenderTextureIndex(-1),
68 m_lastTextureBufferIndex(-1)
72 FrameBufferManager::~FrameBufferManager()
76 void FrameBufferManager::CloseUp()
78 for( int i=0; i<numOfTxtBufInfos; i++ )
80 SAFE_DELETE(gRenderTextureInfos[i].pRenderTexture);
84 void FrameBufferManager::Initialize()
86 m_isRenderingToTexture = false;
87 m_lastTextureBufferIndex = -1;
88 m_curRenderTextureIndex = -1;
90 status.bCIBufferIsRendered = false;
91 status.bN64IsDrawingTextureBuffer = false;
92 status.bHandleN64RenderTexture = false;
93 status.bN64FrameBufferIsUsed = false;
95 memset(&gRenderTextureInfos[0], 0, sizeof(RenderTextureInfo)*numOfTxtBufInfos);
97 // ===========================================================================
99 uint16 ConvertRGBATo555(uint8 r, uint8 g, uint8 b, uint8 a)
101 uint8 ar = a>=0x20?1:0;
102 return ((r>>3)<<RGBA5551_RedShift) | ((g>>3)<<RGBA5551_GreenShift) | ((b>>3)<<RGBA5551_BlueShift) | ar;//(a>>7);
105 uint16 ConvertRGBATo555(uint32 color32)
107 return (uint16)((((color32>>19)&0x1F)<<RGBA5551_RedShift) | (((color32>>11)&0x1F)<<RGBA5551_GreenShift) | (((color32>>3)&0x1F)<<RGBA5551_BlueShift) | ((color32>>31)));;
110 void FrameBufferManager::UpdateRecentCIAddr(SetImgInfo &ciinfo)
112 if( ciinfo.dwAddr == g_uRecentCIInfoPtrs[0]->dwAddr )
118 for( i=1; i<numOfRecentCIInfos; i++ )
120 if( ciinfo.dwAddr == g_uRecentCIInfoPtrs[i]->dwAddr )
122 temp = g_uRecentCIInfoPtrs[i];
124 for( int j=i; j>0; j-- )
126 g_uRecentCIInfoPtrs[j] = g_uRecentCIInfoPtrs[j-1];
132 if( i >= numOfRecentCIInfos )
134 temp = g_uRecentCIInfoPtrs[4];
135 g_uRecentCIInfoPtrs[4] = g_uRecentCIInfoPtrs[3];
136 g_uRecentCIInfoPtrs[3] = g_uRecentCIInfoPtrs[2];
137 g_uRecentCIInfoPtrs[2] = g_uRecentCIInfoPtrs[1];
138 g_uRecentCIInfoPtrs[1] = g_uRecentCIInfoPtrs[0];
139 temp->dwCopiedAtFrame = 0;
140 temp->bCopied = false;
143 g_uRecentCIInfoPtrs[0] = temp;
145 // Fix me here for Mario Tennis
146 temp->dwLastWidth = windowSetting.uViWidth;
147 temp->dwLastHeight = windowSetting.uViHeight;
149 temp->dwFormat = ciinfo.dwFormat;
150 temp->dwAddr = ciinfo.dwAddr;
151 temp->dwSize = ciinfo.dwSize;
152 temp->dwWidth = ciinfo.dwWidth;
153 temp->dwHeight = gRDP.scissor.bottom;
154 temp->dwMemSize = (temp->dwWidth*temp->dwHeight/2)<<temp->dwSize;
155 temp->bCopied = false;
156 temp->lastUsedFrame = status.gDlistCount;
157 temp->lastSetAtUcode = status.gUcodeCount;
161 /************************************************************************/
162 /* Mark the ciinfo entry that the ciinfo is used by VI origin register */
163 /* in another word, this is a real frame buffer, not a fake frame buffer*/
164 /* Fake frame buffers are never really used by VI origin */
165 /************************************************************************/
166 void FrameBufferManager::SetAddrBeDisplayed(uint32 addr)
168 uint32 viwidth = *g_GraphicsInfo.VI_WIDTH_REG;
169 addr &= (g_dwRamSize-1);
172 for( i=0; i<numOfRecentCIInfos; i++ )
174 if( g_uRecentCIInfoPtrs[i]->dwAddr+2*viwidth == addr )
176 g_uRecentCIInfoPtrs[i]->bUsedByVIAtFrame = status.gDlistCount;
178 else if( addr >= g_uRecentCIInfoPtrs[i]->dwAddr && addr < g_uRecentCIInfoPtrs[i]->dwAddr+0x1000 )
180 g_uRecentCIInfoPtrs[i]->bUsedByVIAtFrame = status.gDlistCount;
184 for( i=0; i<numOfRecentCIInfos; i++ )
186 if( g_RecentVIOriginInfo[i].addr == addr )
188 g_RecentVIOriginInfo[i].FrameCount = status.gDlistCount;
193 for( i=0; i<numOfRecentCIInfos; i++ )
195 if( g_RecentVIOriginInfo[i].addr == 0 )
198 g_RecentVIOriginInfo[i].addr = addr;
199 g_RecentVIOriginInfo[i].FrameCount = status.gDlistCount;
205 uint32 minFrameCount = 0xffffffff;
207 for( i=0; i<numOfRecentCIInfos; i++ )
209 if( g_RecentVIOriginInfo[i].FrameCount < minFrameCount )
212 minFrameCount = g_RecentVIOriginInfo[i].FrameCount;
216 g_RecentVIOriginInfo[index].addr = addr;
217 g_RecentVIOriginInfo[index].FrameCount = status.gDlistCount;
220 bool FrameBufferManager::HasAddrBeenDisplayed(uint32 addr, uint32 width)
222 addr &= (g_dwRamSize-1);
225 for( i=0; i<numOfRecentCIInfos; i++ )
227 if( g_uRecentCIInfoPtrs[i]->dwAddr == 0 )
230 if( g_uRecentCIInfoPtrs[i]->dwAddr == addr )
232 if( status.gDlistCount-g_uRecentCIInfoPtrs[i]->bUsedByVIAtFrame < 20 )
233 //if( g_uRecentCIInfoPtrs[i]->bUsedByVIAtFrame != 0 )
239 TXTRBUF_DUMP(TRACE0("This is a new buffer address, the addr is never a displayed buffer"););
245 for( i=0; i<numOfRecentCIInfos; i++ )
247 if( g_RecentVIOriginInfo[i].addr != 0 )
249 if( g_RecentVIOriginInfo[i].addr > addr &&
250 (g_RecentVIOriginInfo[i].addr - addr)%width == 0 &&
251 (g_RecentVIOriginInfo[i].addr - addr)/width <= 4)
253 if( status.gDlistCount-g_RecentVIOriginInfo[i].FrameCount < 20 )
254 //if( g_RecentVIOriginInfo[i].FrameCount != 0 )
260 TXTRBUF_DUMP(DebuggerAppendMsg("This is a new buffer address, the addr is never a displayed buffer"););
267 if( status.gDlistCount > 20 )
271 TXTRBUF_DUMP({DebuggerAppendMsg("This is a new buffer address, the addr is never a displayed buffer");});
276 int FrameBufferManager::FindRecentCIInfoIndex(uint32 addr)
278 for( int i=0; i<numOfRecentCIInfos; i++ )
280 if( g_uRecentCIInfoPtrs[i]->dwAddr <= addr && addr < g_uRecentCIInfoPtrs[i]->dwAddr+g_uRecentCIInfoPtrs[i]->dwMemSize )
288 bool FrameBufferManager::IsDIaRenderTexture()
290 // Knowing g_CI and g_ZI
294 bool foundSetScissor=false;
295 bool foundFillRect=false;
296 bool foundSetFillColor=false;
297 bool foundSetCImg=false;
298 uint32 newFillColor = 0;
300 uint32 dwPC = gDlistStack[gDlistStackPointer].pc; // This points to the next instruction
302 for( int i=0; i<10; i++ )
304 uint32 w0 = *(uint32 *)(g_pRDRAMu8 + dwPC + i*8);
305 uint32 w1 = *(uint32 *)(g_pRDRAMu8 + dwPC + 4 + i*8);
307 if( (w0>>24) == RDP_SETSCISSOR )
309 foundSetScissor = true;
313 if( (w0>>24) == RDP_SETFILLCOLOR )
315 foundSetFillColor = true;
320 if( (w0>>24) == RDP_FILLRECT )
322 uint32 x0 = ((w1>>12)&0xFFF)/4;
323 uint32 y0 = ((w1>>0 )&0xFFF)/4;
324 uint32 x1 = ((w0>>12)&0xFFF)/4;
326 if( x0 == 0 && y0 == 0 )
328 if( x1 == g_CI.dwWidth )
330 foundFillRect = true;
334 if(x1 == (unsigned int)(g_CI.dwWidth-1))
336 foundFillRect = true;
342 if( (w0>>24) == RDP_TEXRECT )
347 if( (w0>>24) == RDP_SETCIMG )
355 bool foundSetScissor=false;
356 bool foundFillRect=false;
357 bool foundSetFillColor=false;
358 bool foundSetCImg=false;
359 bool foundTxtRect=false;
366 if( foundSetFillColor )
368 if( newFillColor != 0xFFFCFFFC )
369 return true; // this is a render_texture
374 if( gRDP.fillColor != 0x00FFFFF7 )
375 return true; // this is a render_texture
377 return false; // this is a normal ZImg
379 else if( foundSetFillColor && newFillColor == 0xFFFCFFFC && foundSetCImg )
392 if( foundSetScissor )
396 int FrameBufferManager::CheckAddrInBackBuffers(uint32 addr, uint32 memsize, bool copyToRDRAM)
398 int r = FindRecentCIInfoIndex(addr);
402 // Also check if the address is overwritten by a recent render_texture
403 //int t = CheckAddrInRenderTextures(addr,false);
405 for( int i=0; i<numOfTxtBufInfos; i++ )
407 uint32 bufHeight = gRenderTextureInfos[i].knownHeight ? gRenderTextureInfos[i].N64Height : gRenderTextureInfos[i].maxUsedHeight;
408 uint32 bufMemSize = gRenderTextureInfos[i].CI_Info.dwSize*gRenderTextureInfos[i].N64Width*bufHeight;
409 if( addr >=gRenderTextureInfos[i].CI_Info.dwAddr && addr < gRenderTextureInfos[i].CI_Info.dwAddr+bufMemSize)
411 if( g_uRecentCIInfoPtrs[r]->lastSetAtUcode < gRenderTextureInfos[i].updateAtUcodeCount )
423 if( r >= 0 && status.gDlistCount - g_uRecentCIInfoPtrs[r]->lastUsedFrame <= 3 && g_uRecentCIInfoPtrs[r]->bCopied == false )
425 DEBUGGER_IF_DUMP((logTextureBuffer&&r==1),TRACE2("Hit current front buffer at %08X, size=0x%X", addr, memsize));
426 DEBUGGER_IF_DUMP((logTextureBuffer&&r==0),TRACE2("Hit current back buffer at %08X, size=0x%X", addr, memsize));
427 DEBUGGER_IF_DUMP((logTextureBuffer&&r>1),TRACE2("Hit old back buffer at %08X, size=0x%X", addr, memsize));
429 SaveBackBuffer(r, NULL, true);
436 uint8 CIFindIndex(uint16 val)
438 for( int i=0; i<=0xFF; i++ )
440 if( val == g_wRDPTlut[i] )
449 void TexRectToFrameBuffer_8b(uint32 dwXL, uint32 dwYL, uint32 dwXH, uint32 dwYH, float t0u0, float t0v0, float t0u1, float t0v1, uint32 dwTile)
451 // Copy the framebuffer texture into the N64 framebuffer memory
455 uint32 maxW = g_pRenderTextureInfo->CI_Info.dwWidth;
456 uint32 maxH = maxW*3/4;
457 if( status.dwTvSystem == TV_SYSTEM_PAL )
463 uint32 maxW = g_pRenderTextureInfo->N64Width;
464 uint32 maxH = g_pRenderTextureInfo->N64Height;
466 uint32 maxOff = maxW*maxH;
468 TMEMLoadMapInfo &info = g_tmemLoadAddrMap[gRDP.tiles[dwTile].dwTMem];
469 uint32 dwWidth = dwXH-dwXL;
470 uint32 dwHeight = dwYH-dwYL;
472 float xScale = (t0u1-t0u0)/dwWidth;
473 float yScale = (t0v1-t0v0)/dwHeight;
475 uint8* dwSrc = g_pRDRAMu8 + info.dwLoadAddress;
476 uint8* dwDst = g_pRDRAMu8 + g_pRenderTextureInfo->CI_Info.dwAddr;
478 uint32 dwSrcPitch = gRDP.tiles[dwTile].dwPitch;
479 uint32 dwDstPitch = g_pRenderTextureInfo->CI_Info.dwWidth;
481 uint32 dwSrcOffX = gRDP.tiles[dwTile].hilite_sl;
482 uint32 dwSrcOffY = gRDP.tiles[dwTile].hilite_tl;
484 uint32 dwLeft = dwXL;
487 dwWidth = min(dwWidth, maxW-dwLeft);
488 dwHeight = min(dwHeight, maxH-dwTop);
493 for (uint32 y = 0; y < dwHeight; y++)
495 uint32 dwByteOffset = (uint32)(((y*yScale+dwSrcOffY) * dwSrcPitch) + dwSrcOffX);
497 for (uint32 x = 0; x < dwWidth; x++)
499 if( (((y+dwTop)*dwDstPitch+x+dwLeft)^0x3) > maxOff )
502 TRACE0("Warning: Offset exceeds limit");
506 dwDst[((y+dwTop)*dwDstPitch+x+dwLeft)^0x3] = dwSrc[(uint32)(dwByteOffset+x*xScale) ^ 0x3];
510 TXTRBUF_DUMP(DebuggerAppendMsg("TexRect To FrameBuffer: X0=%d, Y0=%d, X1=%d, Y1=%d,\n\t\tfS0=%f, fT0=%f, fS1=%f, fT1=%f ",
511 dwXL, dwYL, dwXH, dwYH, t0v0, t0v0, t0u1, t0v1););
514 void TexRectToN64FrameBuffer_16b(uint32 x0, uint32 y0, uint32 width, uint32 height, uint32 dwTile)
516 // Copy the framebuffer texture into the N64 RDRAM framebuffer memory structure
519 if( g_textures[dwTile].m_pCTexture->StartUpdate(&srcInfo) == false )
521 DebuggerAppendMsg("Fail to lock texture:TexRectToN64FrameBuffer_16b" );
525 uint32 n64CIaddr = g_CI.dwAddr;
526 uint32 n64CIwidth = g_CI.dwWidth;
528 for (uint32 y = 0; y < height; y++)
530 uint32* pSrc = (uint32*)((uint8*)srcInfo.lpSurface + y * srcInfo.lPitch);
531 uint16* pN64Buffer = (uint16*)(g_pRDRAMu8+(n64CIaddr&(g_dwRamSize-1)))+(y+y0)*n64CIwidth;
533 for (uint32 x = 0; x < width; x++)
535 pN64Buffer[x+x0] = ConvertRGBATo555(pSrc[x]);
539 g_textures[dwTile].m_pCTexture->EndUpdate(&srcInfo);
542 #define FAST_CRC_CHECKING_INC_X 13
543 #define FAST_CRC_CHECKING_INC_Y 11
544 #define FAST_CRC_MIN_Y_INC 2
545 #define FAST_CRC_MIN_X_INC 2
546 #define FAST_CRC_MAX_X_INC 7
547 #define FAST_CRC_MAX_Y_INC 3
548 extern uint32 dwAsmHeight;
549 extern uint32 dwAsmPitch;
550 extern uint32 dwAsmdwBytesPerLine;
551 extern uint32 dwAsmCRC;
552 extern uint8* pAsmStart;
554 uint32 CalculateRDRAMCRC(void *pPhysicalAddress, uint32 left, uint32 top, uint32 width, uint32 height, uint32 size, uint32 pitchInBytes )
557 dwAsmdwBytesPerLine = ((width<<size)+1)/2;
559 if( currentRomOptions.bFastTexCRC && !options.bLoadHiResTextures && (height>=32 || (dwAsmdwBytesPerLine>>2)>=16))
561 uint32 realWidthInDWORD = dwAsmdwBytesPerLine>>2;
562 uint32 xinc = realWidthInDWORD / FAST_CRC_CHECKING_INC_X;
563 if( xinc < FAST_CRC_MIN_X_INC )
565 xinc = min(FAST_CRC_MIN_X_INC, width);
567 if( xinc > FAST_CRC_MAX_X_INC )
569 xinc = FAST_CRC_MAX_X_INC;
572 uint32 yinc = height / FAST_CRC_CHECKING_INC_Y;
573 if( yinc < FAST_CRC_MIN_Y_INC )
575 yinc = min(FAST_CRC_MIN_Y_INC, height);
577 if( yinc > FAST_CRC_MAX_Y_INC )
579 yinc = FAST_CRC_MAX_Y_INC;
582 uint32 pitch = pitchInBytes>>2;
583 register uint32 *pStart = (uint32*)(pPhysicalAddress);
584 pStart += (top * pitch) + (((left<<size)+1)>>3);
586 // The original assembly code had a bug in it (it incremented pStart by 'pitch' in bytes, not in dwords)
587 // This C code implements the same algorithm as the ASM but without the bug
592 while (x < realWidthInDWORD)
594 dwAsmCRC = (dwAsmCRC << 4) + ((dwAsmCRC >> 28) & 15);
595 dwAsmCRC += pStart[x];
608 dwAsmdwBytesPerLine = ((width<<size)+1)/2;
610 pAsmStart = (uint8*)(pPhysicalAddress);
611 pAsmStart += (top * pitchInBytes) + (((left<<size)+1)>>1);
613 dwAsmHeight = height - 1;
614 dwAsmPitch = pitchInBytes;
617 uint32 pitch = pitchInBytes>>2;
618 uint32* pStart = (uint32*)pPhysicalAddress;
619 pStart += (top * pitch) + (((left<<size)+1)>>3);
626 int x = dwAsmdwBytesPerLine - 4;
629 esi = *(uint32*)(pAsmStart + x);
632 dwAsmCRC = (dwAsmCRC << 4) + ((dwAsmCRC >> 28) & 15);
638 pAsmStart += dwAsmPitch;
642 #elif !defined(__GNUC__) // !defined(NO_ASM)
651 mov ecx, pAsmStart; // = pStart
652 mov edx, 0 // The CRC
653 mov eax, dwAsmHeight // = y
654 l2: mov ebx, dwAsmdwBytesPerLine // = x
656 l1: mov esi, [ecx+ebx]
676 #elif defined(__x86_64__) // defined(__GNUC__) && !defined(NO_ASM)
677 asm volatile(" xorl %k2, %k2 \n"
678 " movslq %k4, %q4 \n"
680 " movslq %3, %%rbx \n"
683 " movl (%0,%%rbx,1), %%eax \n"
684 " xorl %%ebx, %%eax \n"
686 " addl %%eax, %k2 \n"
689 " xorl %k1, %%eax \n"
690 " addl %%eax, %k2 \n"
694 : "+r"(pAsmStart), "+r"(dwAsmHeight), "=&r"(dwAsmCRC)
695 : "m"(dwAsmdwBytesPerLine), "r"(dwAsmPitch)
696 : "%rbx", "%rax", "memory", "cc"
698 #elif !defined(__PIC__) // !defined(__x86_64__) && defined(__GNUC__) && !defined(NO_ASM)
699 asm volatile("pusha \n"
700 "mov %[pAsmStart], %%ecx \n" // = pStart
701 "mov $0, %%edx \n" // The CRC
702 "mov %[dwAsmHeight], %%eax \n" // = y
704 "mov %[dwAsmdwBytesPerLine], %%ebx \n" // = x
707 "mov (%%ecx,%%ebx), %%esi \n"
708 "xor %%ebx, %%esi \n"
710 "add %%esi, %%edx \n"
713 "xor %%eax, %%esi \n"
714 "add %%esi, %%edx \n"
715 "add %[dwAsmPitch], %%ecx \n"
719 "mov %%edx, %[dwAsmCRC] \n"
721 : [pAsmStart]"+m"(pAsmStart), [dwAsmHeight]"+m"(dwAsmHeight), [dwAsmCRC]"=m"(dwAsmCRC)
722 : [dwAsmdwBytesPerLine]"m"(dwAsmdwBytesPerLine), [dwAsmPitch]"m"(dwAsmPitch)
725 #else // defined(__PIC__) && !defined(__x86_64__) && defined(__GNUC__) && !defined(NO_ASM)
726 unsigned int saveEBX;
727 unsigned int saveEAX;
728 unsigned int saveECX;
729 unsigned int saveEDX;
730 unsigned int saveESI;
731 unsigned int asmdwBytesPerLine = dwAsmdwBytesPerLine;
732 unsigned int asmPitch = dwAsmPitch;
733 unsigned int asmHeight = dwAsmHeight;
735 asm volatile("mov %%ebx, %2 \n"
740 "mov %0, %%ecx \n" // = pStart
741 "mov $0, %%edx \n" // The CRC
742 "mov %1, %%eax \n" // = y
744 "mov %3, %%ebx \n" // = x
747 "mov (%%ecx,%%ebx), %%esi \n"
748 "xor %%ebx, %%esi \n"
750 "add %%esi, %%edx \n"
753 "xor %%eax, %%esi \n"
754 "add %%esi, %%edx \n"
766 : "m"(pAsmStart), "m"(asmHeight), "m"(saveEBX), "m"(asmdwBytesPerLine), "m"(asmPitch), "m"(saveEAX),
767 "m"(asmCRC), "m"(saveECX), "m"(saveEDX), "m"(saveESI)
775 TRACE0("Exception in texture CRC calculation");
780 unsigned char CalculateMaxCI(void *pPhysicalAddress, uint32 left, uint32 top, uint32 width, uint32 height, uint32 size, uint32 pitchInBytes )
784 unsigned char val = 0;
786 if( TXT_SIZE_8b == size )
788 for( y = 0; y<height; y++ )
790 buf = (unsigned char*)pPhysicalAddress + left + pitchInBytes * (y+top);
791 for( x=0; x<width; x++ )
793 if( buf[x] > val ) val = buf[x];
801 unsigned char val1,val2;
804 for( y = 0; y<height; y++ )
806 buf = (unsigned char*)pPhysicalAddress + left + pitchInBytes * (y+top);
807 for( x=0; x<width; x++ )
811 if( val1 > val ) val = val1;
812 if( val2 > val ) val = val2;
822 bool FrameBufferManager::FrameBufferInRDRAMCheckCRC()
824 RecentCIInfo &p = *(g_uRecentCIInfoPtrs[0]);
825 uint8 *pFrameBufferBase = (uint8*)(g_pRDRAMu8+p.dwAddr);
826 uint32 pitch = (p.dwWidth << p.dwSize ) >> 1;
827 uint32 crc = CalculateRDRAMCRC(pFrameBufferBase, 0, 0, p.dwWidth, p.dwHeight, p.dwSize, pitch);
831 TRACE0("Frame Buffer CRC mismitch, it is modified by CPU");
840 extern std::vector<uint32> frameWriteRecord;
841 void FrameBufferManager::FrameBufferWriteByCPU(uint32 addr, uint32 size)
843 if( !frameBufferOptions.bProcessCPUWrite ) return;
844 //WARNING(TRACE2("Frame Buffer Write, addr=%08X, CI Addr=%08X", addr, g_CI.dwAddr));
845 status.frameWriteByCPU = TRUE;
846 frameWriteRecord.push_back(addr&(g_dwRamSize-1));
849 extern RECT frameWriteByCPURect;
850 extern std::vector<RECT> frameWriteByCPURects;
851 extern RECT frameWriteByCPURectArray[20][20];
852 extern bool frameWriteByCPURectFlag[20][20];
853 #define FRAMEBUFFER_IN_BLOCK
854 bool FrameBufferManager::ProcessFrameWriteRecord()
856 int size = frameWriteRecord.size();
857 if( size == 0 ) return false;
859 int index = FindRecentCIInfoIndex(frameWriteRecord[0]);
862 LOG_TEXTURE(TRACE1("Frame Buffer Write to non-record addr = %08X", frameWriteRecord[0]));
863 frameWriteRecord.clear();
868 uint32 base = g_uRecentCIInfoPtrs[index]->dwAddr;
869 uint32 uwidth = g_uRecentCIInfoPtrs[index]->dwWidth;
870 uint32 uheight = g_uRecentCIInfoPtrs[index]->dwHeight;
871 uint32 upitch = uwidth<<1;
873 frameWriteByCPURect.left=uwidth-1;
874 frameWriteByCPURect.top = uheight-1;
876 frameWriteByCPURect.right=0;
877 frameWriteByCPURect.bottom = 0;
881 for( int i=0; i<size; i++ )
883 off = frameWriteRecord[i]-base;
884 if( off < (int)g_uRecentCIInfoPtrs[index]->dwMemSize )
887 x = (off - y*upitch)>>1;
889 #ifdef FRAMEBUFFER_IN_BLOCK
893 RECT &rect = frameWriteByCPURectArray[xidx][yidx];
895 if( !frameWriteByCPURectFlag[xidx][yidx] )
897 rect.left=rect.right=x;
898 rect.top=rect.bottom=y;
899 frameWriteByCPURectFlag[xidx][yidx]=true;
903 if( x < rect.left ) rect.left = x;
904 if( x > rect.right ) rect.right = x;
905 if( y < rect.top ) rect.top = y;
906 if( y > rect.bottom ) rect.bottom = y;
909 if( x < frameWriteByCPURect.left ) frameWriteByCPURect.left = x;
910 if( x > frameWriteByCPURect.right ) frameWriteByCPURect.right = x;
911 if( y < frameWriteByCPURect.top ) frameWriteByCPURect.top = y;
912 if( y > frameWriteByCPURect.bottom ) frameWriteByCPURect.bottom = y;
917 frameWriteRecord.clear();
918 LOG_TEXTURE(TRACE4("Frame Buffer Write: Left=%d, Top=%d, Right=%d, Bottom=%d", frameWriteByCPURect.left,
919 frameWriteByCPURect.top, frameWriteByCPURect.right, frameWriteByCPURect.bottom));
924 void FrameBufferManager::FrameBufferReadByCPU( uint32 addr )
926 ///return; // it does not work very well anyway
929 if( !frameBufferOptions.bProcessCPURead ) return;
931 addr &= (g_dwRamSize-1);
932 int index = FindRecentCIInfoIndex(addr);
935 // Check if this is the depth buffer
936 uint32 size = 2*g_RecentCIInfo[0].dwWidth*g_RecentCIInfo[0].dwHeight;
939 if( addr >= g_ZI.dwAddr && addr < g_ZI.dwAddr + size )
941 TXTRBUF_OR_CI_DUMP(TRACE1("Depth Buffer read, reported by emulator, addr=%08X", addr));
949 if( status.gDlistCount - g_uRecentCIInfoPtrs[index]->lastUsedFrame > 3 )
951 // Ok, we don't have this frame anymore
955 //TXTRBUF_OR_CI_DUMP(TRACE1("FB Read By CPU at %08X", addr));
956 if( g_uRecentCIInfoPtrs[index]->bCopied ) return;
957 //if( addr != g_uRecentCIInfoPtrs[index]->dwAddr ) return;
959 TXTRBUF_OR_CI_DUMP(TRACE1("Frame Buffer read, reported by emulator, addr=%08X", addr));
960 uint32 size = 0x1000 - addr%0x1000;
961 CheckAddrInBackBuffers(addr, size, true);
963 DEBUGGER_IF_DUMP(pauseAtNext,{TRACE0("Frame Buffer read");});
964 DEBUGGER_PAUSE_AND_DUMP_NO_UPDATE(NEXT_RENDER_TEXTURE,
965 {DebuggerAppendMsg("Paused after setting Frame Buffer read:\n Cur CI Addr: 0x%08x, Fmt: %s Size: %s Width: %d",
966 g_CI.dwAddr, pszImgFormat[g_CI.dwFormat], pszImgSize[g_CI.dwSize], g_CI.dwWidth);});
971 extern RECT frameWriteByCPURect;
972 extern std::vector<RECT> frameWriteByCPURects;
973 extern RECT frameWriteByCPURectArray[20][20];
974 extern bool frameWriteByCPURectFlag[20][20];
975 #define FRAMEBUFFER_IN_BLOCK
977 void FrameBufferManager::UpdateFrameBufferBeforeUpdateFrame()
979 if( (frameBufferOptions.bProcessCPUWrite && status.frameWriteByCPU ) ||
980 (frameBufferOptions.bLoadBackBufFromRDRAM && !FrameBufferInRDRAMCheckCRC() ) )
981 // Checks if frame buffer has been modified by CPU
982 // Only happens to Dr. Mario
984 if( frameBufferOptions.bProcessCPUWrite )
986 if( ProcessFrameWriteRecord() )
988 #ifdef FRAMEBUFFER_IN_BLOCK
992 for( j=0; j<20; j++ )
994 if( frameWriteByCPURectFlag[i][j] )
996 CRender::GetRender()->DrawFrameBuffer(false, frameWriteByCPURectArray[i][j].left, frameWriteByCPURectArray[i][j].top,
997 frameWriteByCPURectArray[i][j].right-frameWriteByCPURectArray[i][j].left+1, frameWriteByCPURectArray[i][j].bottom-frameWriteByCPURectArray[i][j].top+1);
1001 for( i=0; i<20; i++)
1003 for( j=0; j<20; j++ )
1005 if( frameWriteByCPURectFlag[i][j] )
1007 ClearN64FrameBufferToBlack(frameWriteByCPURectArray[i][j].left, frameWriteByCPURectArray[i][j].top,
1008 frameWriteByCPURectArray[i][j].right-frameWriteByCPURectArray[i][j].left+1, frameWriteByCPURectArray[i][j].bottom-frameWriteByCPURectArray[i][j].top+1);
1009 frameWriteByCPURectFlag[i][j] = false;
1013 //memset(frameWriteByCPURectArray, 0, sizeof(frameWriteByCPURectArray));
1014 //memset(frameWriteByCPURectFlag, 0, sizeof(frameWriteByCPURectFlag));
1016 CRender::GetRender()->DrawFrameBuffer(false, frameWriteByCPURect.left, frameWriteByCPURect.top,
1017 frameWriteByCPURect.right-frameWriteByCPURect.left, frameWriteByCPURect.bottom-frameWriteByCPURect.top);
1018 ClearN64FrameBufferToBlack(frameWriteByCPURect.left, frameWriteByCPURect.top,
1019 frameWriteByCPURect.right-frameWriteByCPURect.left+1, frameWriteByCPURect.bottom-frameWriteByCPURect.top+1);
1022 int size = frameWriteByCPURects.size();
1023 for( int i=0; i<size; i++)
1025 CRender::GetRender()->DrawFrameBuffer(false, frameWriteByCPURects[i].left, frameWriteByCPURects[i].top,
1026 frameWriteByCPURects[i].right-frameWriteByCPURects[i].left, frameWriteByCPURects[i].bottom-frameWriteByCPURects[i].top);
1027 ClearN64FrameBufferToBlack(frameWriteByCPURects[i].left, frameWriteByCPURects[i].top,
1028 frameWriteByCPURects[i].right-frameWriteByCPURects[i].left+1, frameWriteByCPURects[i].bottom-frameWriteByCPURects[i].top+1);
1030 frameWriteByCPURects.clear();
1034 status.frameWriteByCPU = FALSE;
1038 if (CRender::IsAvailable())
1040 RecentCIInfo &p = *(g_uRecentCIInfoPtrs[0]);
1041 CRender::GetRender()->DrawFrameBuffer(false, 0,0,p.dwWidth,p.dwHeight);
1042 ClearN64FrameBufferToBlack();
1048 uint32 FrameBufferManager::ComputeCImgHeight(SetImgInfo &info, uint32 &height)
1050 uint32 dwPC = gDlistStack[gDlistStackPointer].pc; // This points to the next instruction
1052 for( int i=0; i<10; i++ )
1054 uint32 w0 = *(uint32 *)(g_pRDRAMu8 + dwPC + i*8);
1055 uint32 w1 = *(uint32 *)(g_pRDRAMu8 + dwPC + 4 + i*8);
1057 if( (w0>>24) == RDP_SETSCISSOR )
1059 height = ((w1>>0 )&0xFFF)/4;
1060 TXTRBUF_DETAIL_DUMP(TRACE1("buffer height = %d", height));
1061 return RDP_SETSCISSOR;
1064 if( (w0>>24) == RDP_FILLRECT )
1066 uint32 x0 = ((w1>>12)&0xFFF)/4;
1067 uint32 y0 = ((w1>>0 )&0xFFF)/4;
1068 uint32 x1 = ((w0>>12)&0xFFF)/4;
1069 uint32 y1 = ((w0>>0 )&0xFFF)/4;
1071 if( x0 == 0 && y0 == 0 )
1073 if( x1 == info.dwWidth )
1076 TXTRBUF_DETAIL_DUMP(TRACE1("buffer height = %d", height));
1077 return RDP_FILLRECT;
1080 if(x1 == (unsigned int)(info.dwWidth-1))
1083 TXTRBUF_DETAIL_DUMP(TRACE1("buffer height = %d", height));
1084 return RDP_FILLRECT;
1089 if( (w0>>24) == RDP_SETCIMG )
1094 if( (w0>>24) == RDP_SETCIMG )
1100 if( gRDP.scissor.left == 0 && gRDP.scissor.top == 0 && (unsigned int)gRDP.scissor.right == info.dwWidth )
1102 height = gRDP.scissor.bottom;
1103 TXTRBUF_DETAIL_DUMP(TRACE1("buffer height = %d", height));
1104 return RDP_SETSCISSOR+1;
1108 TXTRBUF_DETAIL_DUMP(TRACE0("Not sure about buffer height"));
1110 height = info.dwWidth*3/4;
1111 if( status.dwTvSystem == TV_SYSTEM_PAL )
1113 height = info.dwWidth*9/11;
1116 if( gRDP.scissor.bottom < (int)height && gRDP.scissor.bottom != 0 )
1118 height = gRDP.scissor.bottom;
1121 if( info.dwAddr + height*info.dwWidth*info.dwSize >= g_dwRamSize )
1123 height = info.dwWidth*3/4;
1124 if( status.dwTvSystem == TV_SYSTEM_PAL )
1126 height = info.dwWidth*9/11;
1129 if( gRDP.scissor.bottom < (int)height && gRDP.scissor.bottom != 0 )
1131 height = gRDP.scissor.bottom;
1134 if( info.dwAddr + height*info.dwWidth*info.dwSize >= g_dwRamSize )
1136 height = ( g_dwRamSize - info.dwAddr ) / info.dwWidth;
1140 TXTRBUF_DETAIL_DUMP(TRACE1("render_texture height = %d", height));
1144 int FrameBufferManager::CheckRenderTexturesWithNewCI(SetImgInfo &CIinfo, uint32 height, bool byNewTxtrBuf)
1147 uint32 memsize = ((height*CIinfo.dwWidth)>>1)<<CIinfo.dwSize;
1149 for( int i=0; i<numOfTxtBufInfos; i++ )
1151 RenderTextureInfo &info = gRenderTextureInfos[i];
1152 if( !info.isUsed ) continue;
1154 bool covered = false;
1156 if( info.CI_Info.dwAddr == CIinfo.dwAddr )
1158 if( info.CI_Info.dwSize == CIinfo.dwSize &&
1159 info.CI_Info.dwWidth == CIinfo.dwWidth &&
1160 info.CI_Info.dwFormat == CIinfo.dwFormat &&
1161 info.N64Height == height
1164 // This is the same texture at the same address
1172 // At the same address, but not the same size
1173 //SAFE_DELETE(info.psurf);
1179 uint32 memsize2 = ((info.N64Height*info.N64Width)>>1)<<info.CI_Info.dwSize;
1181 if( info.CI_Info.dwAddr > CIinfo.dwAddr && info.CI_Info.dwAddr < CIinfo.dwAddr + memsize)
1183 else if( info.CI_Info.dwAddr+memsize2 > CIinfo.dwAddr && info.CI_Info.dwAddr+memsize2 < CIinfo.dwAddr + memsize)
1185 else if( CIinfo.dwAddr > info.CI_Info.dwAddr && CIinfo.dwAddr < info.CI_Info.dwAddr + memsize2 )
1187 else if( CIinfo.dwAddr+ memsize > info.CI_Info.dwAddr && CIinfo.dwAddr+ memsize < info.CI_Info.dwAddr + memsize2 )
1193 //SAFE_DELETE(info.psurf);
1194 if( info.pRenderTexture->IsBeingRendered() )
1196 TRACE0("Error, covering a render_texture which is being rendered");
1197 TRACE3("New addrr=%08X, width=%d, height=%d", CIinfo.dwAddr, CIinfo.dwWidth, height );
1198 TRACE3("Old addrr=%08X, width=%d, height=%d", info.CI_Info.dwAddr, info.N64Width, info.N64Height );
1200 info.isUsed = false;
1201 TXTRBUF_DUMP(TRACE5("Delete txtr buf %d at %08X, covered by new CI at %08X, Width=%d, Height=%d",
1202 i, info.CI_Info.dwAddr, CIinfo.dwAddr, CIinfo.dwWidth, height ));
1203 SAFE_DELETE(info.pRenderTexture);
1204 info.txtEntry.pTexture = NULL;
1212 extern RecentCIInfo *g_uRecentCIInfoPtrs[5];
1213 RenderTextureInfo newRenderTextureInfo;
1215 int FrameBufferManager::FindASlot(void)
1219 // Find an empty slot
1221 for( int i=0; i<numOfTxtBufInfos; i++ )
1223 if( !gRenderTextureInfos[i].isUsed && gRenderTextureInfos[i].updateAtFrame < status.gDlistCount )
1231 // If cannot find an empty slot, find the oldest slot and reuse the slot
1234 uint32 oldestCount=0xFFFFFFFF;
1235 uint32 oldestIdx = 0;
1236 for( int i=0; i<numOfTxtBufInfos; i++ )
1238 if( gRenderTextureInfos[i].updateAtUcodeCount < oldestCount )
1240 oldestCount = gRenderTextureInfos[i].updateAtUcodeCount;
1248 DEBUGGER_IF_DUMP((logTextureBuffer && gRenderTextureInfos[idx].pRenderTexture ),TRACE2("Delete txtr buf %d at %08X, to reuse it.", idx, gRenderTextureInfos[idx].CI_Info.dwAddr ));
1249 SAFE_DELETE(gRenderTextureInfos[idx].pRenderTexture) ;
1255 void FrameBufferManager::SetRenderTexture(void)
1257 memcpy(&(newRenderTextureInfo.CI_Info), &g_CI, sizeof(SetImgInfo));
1259 newRenderTextureInfo.N64Width = newRenderTextureInfo.CI_Info.dwWidth;
1260 newRenderTextureInfo.knownHeight = ComputeCImgHeight(g_CI, newRenderTextureInfo.N64Height);
1262 status.bHandleN64RenderTexture = true;
1263 newRenderTextureInfo.maxUsedHeight = 0;
1265 if( defaultRomOptions.bInN64Resolution )
1267 newRenderTextureInfo.bufferWidth = newRenderTextureInfo.N64Width;
1268 newRenderTextureInfo.bufferHeight = newRenderTextureInfo.N64Height;
1270 else if( defaultRomOptions.bDoubleSizeForSmallTxtrBuf && newRenderTextureInfo.N64Width<=128 && newRenderTextureInfo.N64Height<=128)
1272 newRenderTextureInfo.bufferWidth = newRenderTextureInfo.N64Width*2;
1273 newRenderTextureInfo.bufferHeight = newRenderTextureInfo.N64Height*2;
1277 newRenderTextureInfo.bufferWidth = newRenderTextureInfo.N64Width;
1278 newRenderTextureInfo.bufferHeight = newRenderTextureInfo.N64Height;
1281 newRenderTextureInfo.scaleX = newRenderTextureInfo.bufferWidth / float(newRenderTextureInfo.N64Width);
1282 newRenderTextureInfo.scaleY = newRenderTextureInfo.bufferHeight / float(newRenderTextureInfo.N64Height);
1284 status.bFrameBufferIsDrawn = false;
1285 status.bFrameBufferDrawnByTriangles = false;
1287 newRenderTextureInfo.updateAtFrame = status.gDlistCount;
1288 newRenderTextureInfo.updateAtUcodeCount = status.gUcodeCount;
1290 // Delay activation of the render_texture until the 1st rendering
1292 TXTRBUF_DUMP(TRACE1("Set render_texture: addr=%08X", g_CI.dwAddr));
1293 DEBUGGER_PAUSE_AND_DUMP_NO_UPDATE(NEXT_RENDER_TEXTURE,
1294 {DebuggerAppendMsg("Paused after setting render_texture:\nAddr: 0x%08x, Fmt: %s Size: %s Width: %d, Height:%d",
1295 g_CI.dwAddr, pszImgFormat[g_CI.dwFormat], pszImgSize[g_CI.dwSize], g_CI.dwWidth, g_pRenderTextureInfo->N64Height);});
1298 int FrameBufferManager::SetBackBufferAsRenderTexture(SetImgInfo &CIinfo, int ciInfoIdx)
1301 // OK, heres the drill!
1303 // We set the graphics card's back buffer's contents as a render_texure
1304 // This is done due to how the current framebuffer implementation detects
1305 // changes to the backbuffer memory pointer and then we do a texture
1306 // copy. This might be slow since it doesnt use hardware auxillary buffers
1308 RenderTextureInfo tempRenderTextureInfo;
1310 memcpy(&(tempRenderTextureInfo.CI_Info), &CIinfo, sizeof(SetImgInfo));
1312 tempRenderTextureInfo.N64Width = g_uRecentCIInfoPtrs[ciInfoIdx]->dwLastWidth;
1313 tempRenderTextureInfo.N64Height = g_uRecentCIInfoPtrs[ciInfoIdx]->dwLastHeight;
1314 tempRenderTextureInfo.knownHeight = true;
1315 tempRenderTextureInfo.maxUsedHeight = 0;
1317 tempRenderTextureInfo.bufferWidth = windowSetting.uDisplayWidth;
1318 tempRenderTextureInfo.bufferHeight = windowSetting.uDisplayHeight;
1320 tempRenderTextureInfo.scaleX = tempRenderTextureInfo.bufferWidth / float(tempRenderTextureInfo.N64Width);
1321 tempRenderTextureInfo.scaleY = tempRenderTextureInfo.bufferHeight / float(tempRenderTextureInfo.N64Height);
1323 status.bFrameBufferIsDrawn = false;
1324 status.bFrameBufferDrawnByTriangles = false;
1326 tempRenderTextureInfo.updateAtFrame = status.gDlistCount;
1327 tempRenderTextureInfo.updateAtUcodeCount = status.gUcodeCount;
1329 // Checking against previous render_texture infos
1330 //uint32 memsize = ((tempRenderTextureInfo.N64Height*tempRenderTextureInfo.N64Width)>>1)<<tempRenderTextureInfo.CI_Info.dwSize;
1331 int matchidx = CheckRenderTexturesWithNewCI(CIinfo,tempRenderTextureInfo.N64Height,false);
1332 int idxToUse = (matchidx >= 0) ? matchidx : FindASlot();
1334 if( gRenderTextureInfos[idxToUse].pRenderTexture == NULL || matchidx < 0 )
1336 gRenderTextureInfos[idxToUse].pRenderTexture =
1337 new COGLRenderTexture(tempRenderTextureInfo.bufferWidth, tempRenderTextureInfo.bufferHeight, &gRenderTextureInfos[idxToUse], AS_BACK_BUFFER_SAVE);
1340 // Need to set all variables for gRenderTextureInfos[idxToUse]
1341 CRenderTexture *pRenderTexture = gRenderTextureInfos[idxToUse].pRenderTexture;
1342 memcpy(&gRenderTextureInfos[idxToUse], &tempRenderTextureInfo, sizeof(RenderTextureInfo) );
1343 gRenderTextureInfos[idxToUse].pRenderTexture = pRenderTexture;
1344 gRenderTextureInfos[idxToUse].isUsed = true;
1345 gRenderTextureInfos[idxToUse].txtEntry.pTexture = pRenderTexture->m_pTexture;
1346 gRenderTextureInfos[idxToUse].txtEntry.txtrBufIdx = idxToUse+1;
1348 TXTRBUF_DUMP(TRACE2("Set back buf as render_texture %d, addr=%08X", idxToUse, CIinfo.dwAddr));
1349 DEBUGGER_PAUSE_AND_DUMP_NO_UPDATE(NEXT_RENDER_TEXTURE,
1350 {DebuggerAppendMsg("Paused after setting render_texture:\nAddr: 0x%08x, Fmt: %s Size: %s Width: %d, Height:%d",
1351 CIinfo.dwAddr, pszImgFormat[CIinfo.dwFormat], pszImgSize[CIinfo.dwSize], CIinfo.dwWidth, g_pRenderTextureInfo->N64Height);});
1356 void FrameBufferManager::CloseRenderTexture(bool toSave)
1358 if( m_curRenderTextureIndex < 0 )
1361 status.bHandleN64RenderTexture = false;
1362 if( status.bDirectWriteIntoRDRAM )
1368 RestoreNormalBackBuffer();
1369 if( !toSave || !status.bFrameBufferIsDrawn || !status.bFrameBufferDrawnByTriangles )
1371 TXTRBUF_DUMP(TRACE0("Closing render_texture without save"););
1372 SAFE_DELETE(gRenderTextureInfos[m_curRenderTextureIndex].pRenderTexture);
1373 gRenderTextureInfos[m_curRenderTextureIndex].isUsed = false;
1374 TXTRBUF_DUMP(TRACE1("Delete render_texture %d",m_curRenderTextureIndex););
1378 TXTRBUF_DUMP(TRACE1("Closing render_texture %d", m_curRenderTextureIndex););
1379 StoreRenderTextureToRDRAM();
1381 if( frameBufferOptions.bRenderTextureWriteBack )
1383 SAFE_DELETE(gRenderTextureInfos[m_curRenderTextureIndex].pRenderTexture);
1384 gRenderTextureInfos[m_curRenderTextureIndex].isUsed = false;
1385 TXTRBUF_DUMP(TRACE1("Delete render_texture %d after writing back to RDRAM",m_curRenderTextureIndex););
1389 g_pRenderTextureInfo->crcInRDRAM = ComputeRenderTextureCRCInRDRAM(m_curRenderTextureIndex);
1390 g_pRenderTextureInfo->crcCheckedAtFrame = status.gDlistCount;
1395 SetScreenMult(windowSetting.uDisplayWidth/windowSetting.fViWidth, windowSetting.uDisplayHeight/windowSetting.fViHeight);
1396 CRender::g_pRender->UpdateClipRectangle();
1397 CRender::g_pRender->ApplyScissorWithClipRatio();
1399 DEBUGGER_PAUSE_AND_DUMP_NO_UPDATE(NEXT_RENDER_TEXTURE,
1401 DebuggerAppendMsg("Paused after saving render_texture %d:\nAddr: 0x%08x, Fmt: %s Size: %s Width: %d", m_curRenderTextureIndex,
1402 g_pRenderTextureInfo->CI_Info.dwAddr, pszImgFormat[g_pRenderTextureInfo->CI_Info.dwFormat], pszImgSize[g_pRenderTextureInfo->CI_Info.dwSize], g_pRenderTextureInfo->CI_Info.dwWidth);
1406 void FrameBufferManager::ClearN64FrameBufferToBlack(uint32 left, uint32 top, uint32 width, uint32 height)
1408 RecentCIInfo &p = *(g_uRecentCIInfoPtrs[0]);
1409 uint16 *frameBufferBase = (uint16*)(g_pRDRAMu8+p.dwAddr);
1410 uint32 pitch = p.dwWidth;
1412 if( width == 0 || height == 0 )
1414 uint32 len = p.dwHeight*p.dwWidth*p.dwSize;
1415 if( p.dwSize == TXT_SIZE_4b ) len = (p.dwHeight*p.dwWidth)>>1;
1416 memset(frameBufferBase, 0, len);
1420 for( uint32 y=0; y<height; y++)
1422 for( uint32 x=0; x<width; x++ )
1424 *(frameBufferBase+(y+top)*pitch+x+left) = 0;
1430 uint8 RevTlutTable[0x10000];
1431 bool RevTlutTableNeedUpdate = false;
1432 void InitTlutReverseLookup(void)
1434 if( RevTlutTableNeedUpdate )
1436 memset(RevTlutTable, 0, 0x10000);
1437 for( int i=0; i<=0xFF; i++ )
1439 RevTlutTable[g_wRDPTlut[i]] = uint8(i);
1442 RevTlutTableNeedUpdate = false;
1447 // Copies backbuffer to N64 framebuffer by notification by emu core
1449 void FrameBufferManager::CopyBackToFrameBufferIfReadByCPU(uint32 addr)
1451 int i = FindRecentCIInfoIndex(addr);
1454 //if( i == 0 ) CGraphicsContext::Get()->UpdateFrame();
1455 RecentCIInfo *info = g_uRecentCIInfoPtrs[i];
1456 StoreBackBufferToRDRAM( info->dwAddr, info->dwFormat, info->dwSize, info->dwWidth, info->dwHeight,
1457 windowSetting.uDisplayWidth, windowSetting.uDisplayHeight, addr, 0x1000-addr%0x1000);
1458 TRACE1("Copy back for CI Addr=%08X", info->dwAddr);
1462 // We do these checks to see if a render_texture operation is occurring...
1463 void FrameBufferManager::CheckRenderTextureCRCInRDRAM(void)
1465 for( int i=0; i<numOfTxtBufInfos; i++ )
1467 if( !gRenderTextureInfos[i].isUsed )
1470 if( gRenderTextureInfos[i].pRenderTexture->IsBeingRendered() )
1473 if( gRenderTextureInfos[i].crcCheckedAtFrame < status.gDlistCount )
1475 uint32 crc = ComputeRenderTextureCRCInRDRAM(i);
1476 if( gRenderTextureInfos[i].crcInRDRAM != crc )
1478 // RDRAM has been modified by CPU core
1479 TXTRBUF_DUMP(TRACE2("Delete txtr buf %d at %08X, CRC in RDRAM changed", i, gRenderTextureInfos[i].CI_Info.dwAddr ));
1480 SAFE_DELETE(gRenderTextureInfos[i].pRenderTexture);
1481 gRenderTextureInfos[i].isUsed = false;
1486 gRenderTextureInfos[i].crcCheckedAtFrame = status.gDlistCount;
1492 // Check render_texture memory addresses
1493 int FrameBufferManager::CheckAddrInRenderTextures(uint32 addr, bool checkcrc)
1495 for( int i=0; i<numOfTxtBufInfos; i++ )
1497 if( !gRenderTextureInfos[i].isUsed )
1500 if( gRenderTextureInfos[i].pRenderTexture->IsBeingRendered() )
1503 uint32 bufHeight = gRenderTextureInfos[i].knownHeight ? gRenderTextureInfos[i].N64Height : gRenderTextureInfos[i].maxUsedHeight;
1504 uint32 bufMemSize = gRenderTextureInfos[i].CI_Info.dwSize*gRenderTextureInfos[i].N64Width*bufHeight;
1505 if( addr >=gRenderTextureInfos[i].CI_Info.dwAddr && addr < gRenderTextureInfos[i].CI_Info.dwAddr+bufMemSize)
1509 // Check the CRC in RDRAM
1510 if( gRenderTextureInfos[i].crcCheckedAtFrame < status.gDlistCount )
1512 uint32 crc = ComputeRenderTextureCRCInRDRAM(i);
1513 if( gRenderTextureInfos[i].crcInRDRAM != crc )
1515 // RDRAM has been modified by CPU core
1516 TRACE3("Buf %d CRC in RDRAM changed from %08X to %08X", i, gRenderTextureInfos[i].crcInRDRAM, crc );
1517 TXTRBUF_DUMP(TRACE2("Delete txtr buf %d at %08X, crcInRDRAM failed.", i, gRenderTextureInfos[i].CI_Info.dwAddr ));
1518 SAFE_DELETE(gRenderTextureInfos[i].pRenderTexture);
1519 gRenderTextureInfos[i].isUsed = false;
1524 gRenderTextureInfos[i].crcCheckedAtFrame = status.gDlistCount;
1529 TXTRBUF_DUMP(TRACE2("Loading texture addr = %08X from txtr buf %d", addr, i));
1537 // Load texture from render_texture buffer
1538 void FrameBufferManager::LoadTextureFromRenderTexture(TxtrCacheEntry* pEntry, int infoIdx)
1540 if( infoIdx < 0 || infoIdx >= numOfTxtBufInfos )
1542 infoIdx = CheckAddrInRenderTextures(pEntry->ti.Address);
1545 if( infoIdx >= 0 && gRenderTextureInfos[infoIdx].isUsed && gRenderTextureInfos[infoIdx].pRenderTexture )
1547 TXTRBUF_DUMP(TRACE1("Loading from render_texture %d", infoIdx));
1548 gRenderTextureInfos[infoIdx].pRenderTexture->LoadTexture(pEntry);
1552 void FrameBufferManager::RestoreNormalBackBuffer()
1554 if( m_curRenderTextureIndex >= 0 && m_curRenderTextureIndex < numOfTxtBufInfos )
1556 if( gRenderTextureInfos[m_curRenderTextureIndex].pRenderTexture )
1557 gRenderTextureInfos[m_curRenderTextureIndex].pRenderTexture->SetAsRenderTarget(false);
1558 m_isRenderingToTexture = false;
1559 m_lastTextureBufferIndex = m_curRenderTextureIndex;
1562 if( !status.bFrameBufferIsDrawn || !status.bFrameBufferDrawnByTriangles )
1564 gRenderTextureInfos[m_curRenderTextureIndex].isUsed = false;
1565 TXTRBUF_DUMP(TRACE2("Delete txtr buf %d at %08X, it is never rendered", m_curRenderTextureIndex, gRenderTextureInfos[m_curRenderTextureIndex].CI_Info.dwAddr ));
1566 SAFE_DELETE(gRenderTextureInfos[m_curRenderTextureIndex].pRenderTexture);
1570 uint32 FrameBufferManager::ComputeRenderTextureCRCInRDRAM(int infoIdx)
1572 if( infoIdx >= numOfTxtBufInfos || infoIdx < 0 || !gRenderTextureInfos[infoIdx].isUsed )
1575 RenderTextureInfo &info = gRenderTextureInfos[infoIdx];
1576 uint32 height = info.knownHeight ? info.N64Height : info.maxUsedHeight;
1577 uint8 *pAddr = (uint8*)(g_pRDRAMu8+info.CI_Info.dwAddr);
1578 uint32 pitch = (info.N64Width << info.CI_Info.dwSize ) >> 1;
1580 return CalculateRDRAMCRC(pAddr, 0, 0, info.N64Width, height, info.CI_Info.dwSize, pitch);
1583 // Activates texture buffer for drawing
1584 void FrameBufferManager::ActiveTextureBuffer(void)
1586 status.bCIBufferIsRendered = true;
1588 if( status.bHandleN64RenderTexture )
1590 // Checking against previous render_texture infos
1593 //uint32 memsize = ((newRenderTextureInfo.N64Height*newRenderTextureInfo.N64Width)>>1)<<newRenderTextureInfo.CI_Info.dwSize;
1595 matchidx = CheckRenderTexturesWithNewCI(g_CI,newRenderTextureInfo.N64Height,true);
1600 // Reuse the matched slot
1601 idxToUse = matchidx;
1605 idxToUse = FindASlot();
1608 if( gRenderTextureInfos[idxToUse].pRenderTexture == NULL || matchidx < 0 )
1610 int w = newRenderTextureInfo.bufferWidth;
1611 if( newRenderTextureInfo.knownHeight == RDP_SETSCISSOR && newRenderTextureInfo.CI_Info.dwAddr == g_ZI.dwAddr )
1613 w = gRDP.scissor.right;
1616 gRenderTextureInfos[idxToUse].pRenderTexture =
1617 new COGLRenderTexture(w, newRenderTextureInfo.bufferHeight, &gRenderTextureInfos[idxToUse], AS_RENDER_TARGET);
1620 // Need to set all variables for gRenderTextureInfos[idxToUse]
1621 CRenderTexture *pRenderTexture = gRenderTextureInfos[idxToUse].pRenderTexture;
1622 memcpy(&gRenderTextureInfos[idxToUse], &newRenderTextureInfo, sizeof(RenderTextureInfo) );
1623 gRenderTextureInfos[idxToUse].pRenderTexture = pRenderTexture;
1624 gRenderTextureInfos[idxToUse].isUsed = true;
1625 gRenderTextureInfos[idxToUse].txtEntry.pTexture = pRenderTexture->m_pTexture;
1626 gRenderTextureInfos[idxToUse].txtEntry.txtrBufIdx = idxToUse+1;
1628 g_pRenderTextureInfo = &gRenderTextureInfos[idxToUse];
1630 // Active the render_texture
1631 if( m_curRenderTextureIndex >= 0 && gRenderTextureInfos[m_curRenderTextureIndex].isUsed && gRenderTextureInfos[m_curRenderTextureIndex].pRenderTexture )
1633 gRenderTextureInfos[m_curRenderTextureIndex].pRenderTexture->SetAsRenderTarget(false);
1634 m_isRenderingToTexture = false;
1637 if( gRenderTextureInfos[idxToUse].pRenderTexture->SetAsRenderTarget(true) )
1639 m_isRenderingToTexture = true;
1641 //Clear(CLEAR_COLOR_AND_DEPTH_BUFFER,0x80808080,1.0f);
1642 if( frameBufferOptions.bFillRectNextTextureBuffer )
1643 CGraphicsContext::g_pGraphicsContext->Clear(CLEAR_COLOR_BUFFER,gRDP.fillColor,1.0f);
1644 else if( options.enableHackForGames == HACK_FOR_MARIO_TENNIS && g_pRenderTextureInfo->N64Width > 64 && g_pRenderTextureInfo->N64Width < 300 )
1646 CGraphicsContext::g_pGraphicsContext->Clear(CLEAR_COLOR_BUFFER,0,1.0f);
1648 else if( options.enableHackForGames == HACK_FOR_MARIO_TENNIS && g_pRenderTextureInfo->N64Width < 64 && g_pRenderTextureInfo->N64Width > 32 )
1650 CGraphicsContext::g_pGraphicsContext->Clear(CLEAR_COLOR_BUFFER,0,1.0f);
1653 m_curRenderTextureIndex = idxToUse;
1655 status.bDirectWriteIntoRDRAM = false;
1657 //SetScreenMult(1, 1);
1658 SetScreenMult(gRenderTextureInfos[m_curRenderTextureIndex].scaleX, gRenderTextureInfos[m_curRenderTextureIndex].scaleY);
1659 CRender::g_pRender->UpdateClipRectangle();
1661 // If needed, draw RDRAM into the render_texture
1662 //if( frameBufferOptions.bLoadRDRAMIntoRenderTexture )
1664 // CRender::GetRender()->LoadTxtrBufFromRDRAM();
1669 if( CDeviceBuilder::m_deviceGeneralType == DIRECTX_DEVICE )
1671 TRACE1("Error to set Render Target: %d", idxToUse);
1672 TRACE1("Addr = %08X", gRenderTextureInfos[idxToUse].CI_Info.dwAddr);
1673 TRACE2("Width = %d, Height=%d", gRenderTextureInfos[idxToUse].N64Width, gRenderTextureInfos[idxToUse].N64Height);
1678 TXTRBUF_DUMP(TRACE2("Rendering to render_texture %d, addr=%08X", idxToUse, g_CI.dwAddr));
1679 DEBUGGER_PAUSE_AND_DUMP_NO_UPDATE(NEXT_RENDER_TEXTURE,
1680 {DebuggerAppendMsg("Paused after activating render_texture:\nAddr: 0x%08x, Fmt: %s Size: %s Width: %d, Height:%d",
1681 g_CI.dwAddr, pszImgFormat[g_CI.dwFormat], pszImgSize[g_CI.dwSize], g_CI.dwWidth, g_pRenderTextureInfo->N64Height);});
1685 UpdateRecentCIAddr(g_CI);
1686 CheckRenderTexturesWithNewCI(g_CI,gRDP.scissor.bottom,false);
1690 #define SAVE_CI {g_CI.dwAddr = newCI.dwAddr;g_CI.dwFormat = newCI.dwFormat;g_CI.dwSize = newCI.dwSize;g_CI.dwWidth = newCI.dwWidth;g_CI.bpl=newCI.bpl;}
1692 // Sets CI address for framebuffer copies
1693 void FrameBufferManager::Set_CI_addr(SetImgInfo &newCI)
1695 bool wasDrawingTextureBuffer = status.bN64IsDrawingTextureBuffer;
1696 status.bN64IsDrawingTextureBuffer = ( newCI.dwSize != TXT_SIZE_16b || newCI.dwFormat != TXT_FMT_RGBA || newCI.dwWidth < 200 || ( newCI.dwAddr != g_ZI.dwAddr && newCI.dwWidth != 512 && !g_pFrameBufferManager->HasAddrBeenDisplayed(newCI.dwAddr, newCI.dwWidth)) );
1697 status.bN64FrameBufferIsUsed = status.bN64IsDrawingTextureBuffer;
1699 if( !wasDrawingTextureBuffer && g_CI.dwAddr == g_ZI.dwAddr && status.bCIBufferIsRendered )
1701 TXTRBUF_DUMP(TRACE0("ZI is rendered"));
1703 if( options.enableHackForGames != HACK_FOR_CONKER && g_uRecentCIInfoPtrs[0]->bCopied == false )
1705 // Conker is not actually using a backbuffer
1706 g_pFrameBufferManager->UpdateRecentCIAddr(g_CI);
1707 if( status.leftRendered != -1 && status.topRendered != -1 && status.rightRendered != -1 && status.bottomRendered != -1 )
1709 RECT rect={status.leftRendered,status.topRendered,status.rightRendered,status.bottomRendered};
1710 g_pFrameBufferManager->SaveBackBuffer(0,&rect);
1714 g_pFrameBufferManager->SaveBackBuffer(0,NULL);
1719 frameBufferOptions.bFillRectNextTextureBuffer = false;
1720 if( g_CI.dwAddr == newCI.dwAddr && status.bHandleN64RenderTexture && (g_CI.dwFormat != newCI.dwFormat || g_CI.dwSize != newCI.dwSize || g_CI.dwWidth != newCI.dwWidth ) )
1722 // Mario Tennis player shadow
1723 g_pFrameBufferManager->CloseRenderTexture(true);
1724 if( options.enableHackForGames == HACK_FOR_MARIO_TENNIS )
1725 frameBufferOptions.bFillRectNextTextureBuffer = true; // Hack for Mario Tennis
1730 if( g_CI.dwAddr == g_ZI.dwAddr && !status.bN64IsDrawingTextureBuffer )
1732 if( g_pFrameBufferManager->IsDIaRenderTexture() )
1734 status.bN64IsDrawingTextureBuffer = true;
1735 status.bN64FrameBufferIsUsed = status.bN64IsDrawingTextureBuffer;
1739 status.bCIBufferIsRendered = false;
1740 status.leftRendered = status.topRendered = status.rightRendered = status.bottomRendered = -1;
1742 if( currentRomOptions.screenUpdateSetting==SCREEN_UPDATE_AT_CI_CHANGE && !status.bN64IsDrawingTextureBuffer )
1744 if( status.curRenderBuffer == 0 )
1746 status.curRenderBuffer = g_CI.dwAddr;
1748 else if( status.curRenderBuffer != g_CI.dwAddr )
1750 status.curDisplayBuffer = status.curRenderBuffer;
1751 CGraphicsContext::Get()->UpdateFrame();
1752 status.curRenderBuffer = g_CI.dwAddr;
1753 DEBUGGER_IF_DUMP(pauseAtNext,{DebuggerAppendMsg("Screen Update because CI change to %08X, Display Buf=%08X", status.curRenderBuffer, status.curDisplayBuffer);});
1757 if( frameBufferOptions.bAtEachFrameUpdate && !status.bHandleN64RenderTexture )
1759 if( status.curRenderBuffer != g_CI.dwAddr )
1761 if( status.gDlistCount%(currentRomOptions.N64FrameBufferWriteBackControl+1) == 0 )
1763 g_pFrameBufferManager->StoreBackBufferToRDRAM(status.curRenderBuffer,
1764 newCI.dwFormat, newCI.dwSize, windowSetting.uViWidth, windowSetting.uViHeight,
1765 windowSetting.uDisplayWidth, windowSetting.uDisplayHeight);
1769 //status.curDisplayBuffer = status.curRenderBuffer;
1770 status.curRenderBuffer = g_CI.dwAddr;
1774 switch( currentRomOptions.N64RenderToTextureEmuType )
1777 if( status.bHandleN64RenderTexture )
1778 g_pFrameBufferManager->CloseRenderTexture(false);
1779 status.bHandleN64RenderTexture = false; // Don't handle N64 render_texture stuffs
1780 if( !status.bN64IsDrawingTextureBuffer )
1781 g_pFrameBufferManager->UpdateRecentCIAddr(g_CI);
1784 if( status.bHandleN64RenderTexture )
1787 if( pauseAtNext && eventToPause == NEXT_RENDER_TEXTURE )
1790 eventToPause = NEXT_RENDER_TEXTURE;
1793 g_pFrameBufferManager->CloseRenderTexture(true);
1796 status.bHandleN64RenderTexture = status.bN64IsDrawingTextureBuffer;
1797 if( status.bHandleN64RenderTexture )
1799 if( options.enableHackForGames != HACK_FOR_BANJO_TOOIE )
1801 g_pFrameBufferManager->SetRenderTexture();
1807 if( g_CI.dwWidth == 512 && pauseAtNext && (eventToPause==NEXT_OBJ_BG || eventToPause==NEXT_SET_CIMG) )
1809 DebuggerAppendMsg("Warning SetCImg: new Addr=0x%08X, fmt:%s size=%sb, Width=%d\n",
1810 g_CI.dwAddr, pszImgFormat[newCI.dwFormat], pszImgSize[newCI.dwSize], newCI.dwWidth);
1813 //g_pFrameBufferManager->UpdateRecentCIAddr(g_CI); // Delay this until the CI buffer is actally drawn
1818 TXTRBUF_DUMP(TRACE4("SetCImg : Addr=0x%08X, Fmt:%s-%sb, Width=%d\n",
1819 g_CI.dwAddr, pszImgFormat[newCI.dwFormat], pszImgSize[newCI.dwSize], newCI.dwWidth));
1821 DEBUGGER_PAUSE_AND_DUMP_NO_UPDATE(NEXT_SET_CIMG,
1823 DebuggerAppendMsg("Pause after SetCImg: Addr=0x%08X, Fmt:%s-%sb, Width=%d\n",
1824 g_CI.dwAddr, pszImgFormat[newCI.dwFormat], pszImgSize[newCI.dwSize], newCI.dwWidth);
1830 void FrameBufferManager::StoreRenderTextureToRDRAM(int infoIdx)
1832 if( !frameBufferOptions.bRenderTextureWriteBack )
1836 infoIdx = m_lastTextureBufferIndex;
1838 if( !gRenderTextureInfos[infoIdx].pRenderTexture )
1841 if( gRenderTextureInfos[infoIdx].pRenderTexture->IsBeingRendered() )
1843 TXTRBUF_DUMP(TRACE1("Cannot SaveTextureBuffer %d, it is being rendered", infoIdx));
1847 gRenderTextureInfos[infoIdx].pRenderTexture->StoreToRDRAM(infoIdx);
1851 //does FB copy to N64 RDAM structure
1852 void FrameBufferManager::CopyBufferToRDRAM(uint32 addr, uint32 fmt, uint32 siz, uint32 width, uint32 height, uint32 bufWidth, uint32 bufHeight, uint32 startaddr, uint32 memsize, uint32 pitch, TextureFmt bufFmt, void *buffer, uint32 bufPitch)
1856 if( startaddr == 0xFFFFFFFF )
1859 startline = (startaddr-addr)/siz/pitch;
1860 if( startline >= height )
1862 //TRACE0("Warning: check me");
1866 uint32 endline = height;
1867 if( memsize != 0xFFFFFFFF )
1869 endline = (startaddr+memsize-addr)/siz;
1870 if( endline % pitch == 0 )
1873 endline = endline/pitch+1;
1875 if( endline > height )
1880 if( memsize != 0xFFFFFFFF )
1882 TXTRBUF_DUMP(DebuggerAppendMsg("Start at: 0x%X, from line %d to %d", startaddr-addr, startline, endline););
1889 float ratio = bufWidth/(float)width;
1890 for( uint32 j=0; j<width; j++ )
1898 if( siz == TXT_SIZE_16b )
1900 uint16 *frameBufferBase = (uint16*)(g_pRDRAMu8+addr);
1902 if( bufFmt==TEXTURE_FMT_A8R8G8B8 )
1905 float ratio = bufHeight/(float)height;
1907 for( uint32 i=startline; i<endline; i++ )
1909 sy0 = int(i*ratio+0.5);
1911 uint16 *pD = frameBufferBase + i * pitch;
1912 uint8 *pS0 = (uint8 *)buffer + sy0 * bufPitch;
1914 for( uint32 j=0; j<width; j++ )
1917 uint8 r = pS0[indexes[j]+2];
1918 uint8 g = pS0[indexes[j]+1];
1919 uint8 b = pS0[indexes[j]+0];
1920 uint8 a = pS0[indexes[j]+3];
1923 *(pD+(j^1)) = ConvertRGBATo555( r, g, b, a);
1929 TRACE1("Copy %sb FrameBuffer to Rdram, not implemented", pszImgSize[siz]);
1932 else if( siz == TXT_SIZE_8b && fmt == TXT_FMT_CI )
1934 uint8 *frameBufferBase = (uint8*)(g_pRDRAMu8+addr);
1936 if( bufFmt==TEXTURE_FMT_A8R8G8B8 )
1939 InitTlutReverseLookup();
1941 for( uint32 i=startline; i<endline; i++ )
1943 uint8 *pD = frameBufferBase + i * width;
1944 uint8 *pS = (uint8 *)buffer + i*bufHeight/height * bufPitch;
1945 for( uint32 j=0; j<width; j++ )
1947 int pos = 4*(j*bufWidth/width);
1948 tempword = ConvertRGBATo555((pS[pos+2]), // Red
1949 (pS[pos+1]), // Green
1950 (pS[pos+0]), // Blue
1951 (pS[pos+3])); // Alpha
1953 //*pD = CIFindIndex(tempword);
1954 *(pD+(j^3)) = RevTlutTable[tempword];
1960 TRACE1("Copy %sb FrameBuffer to Rdram, not implemented", pszImgSize[siz]);
1962 DEBUGGER_IF_DUMP(pauseAtNext,{DebuggerAppendMsg("Copy %sb FrameBuffer to Rdram", pszImgSize[siz]);});
1964 else if( siz == TXT_SIZE_8b && fmt == TXT_FMT_I )
1966 uint8 *frameBufferBase = (uint8*)(g_pRDRAMu8+addr);
1968 if( bufFmt==TEXTURE_FMT_A8R8G8B8 )
1971 float ratio = bufHeight/(float)height;
1973 for( uint32 i=startline; i<endline; i++ )
1975 sy0 = int(i*ratio+0.5);
1977 uint8 *pD = frameBufferBase + i * width;
1978 uint8 *pS0 = (uint8 *)buffer + sy0 * bufPitch;
1980 for( uint32 j=0; j<width; j++ )
1983 uint32 r = pS0[indexes[j]+2];
1984 uint32 g = pS0[indexes[j]+1];
1985 uint32 b = pS0[indexes[j]+0];
1988 *(pD+(j^3)) = (uint8)((r+b+g)/3);
1994 //DebuggerAppendMsg("Copy %sb FrameBuffer to Rdram, not implemented", pszImgSize[siz]);
1996 DEBUGGER_IF_DUMP(pauseAtNext,{DebuggerAppendMsg("Copy %sb FrameBuffer to Rdram", pszImgSize[siz]);});
2002 void FrameBufferManager::DisplayRenderTexture(int infoIdx)
2005 infoIdx = m_lastTextureBufferIndex;
2007 if( gRenderTextureInfos[infoIdx].pRenderTexture )
2009 if( gRenderTextureInfos[infoIdx].pRenderTexture->IsBeingRendered() )
2011 TRACE1("Render texture %d is being rendered, cannot display", infoIdx);
2015 TRACE1("Texture buffer %d:", infoIdx);
2016 TRACE1("Addr=%08X", gRenderTextureInfos[infoIdx].CI_Info.dwAddr);
2017 TRACE2("Width=%d, Created Height=%d", gRenderTextureInfos[infoIdx].N64Width,gRenderTextureInfos[infoIdx].N64Height);
2018 TRACE2("Fmt=%d, Size=%d", gRenderTextureInfos[infoIdx].CI_Info.dwFormat,gRenderTextureInfos[infoIdx].CI_Info.dwSize);
2023 TRACE1("Texture buffer %d is not used", infoIdx);
2031 // this is the core to the current framebuffer code
2032 // We need to save backbuffer when changed by framebuffer
2033 // so that we can use it for framebuffer effects
2034 void FrameBufferManager::SaveBackBuffer(int ciInfoIdx, RECT* pSrcRect, bool forceToSaveToRDRAM)
2036 RecentCIInfo &ciInfo = *g_uRecentCIInfoPtrs[ciInfoIdx];
2038 if( ciInfoIdx == 1 ) // to save the current front buffer
2040 CGraphicsContext::g_pGraphicsContext->UpdateFrame(true);
2043 if( frameBufferOptions.bWriteBackBufToRDRAM || forceToSaveToRDRAM )
2045 uint32 width = ciInfo.dwWidth;
2046 uint32 height = ciInfo.dwHeight;
2048 if( ciInfo.dwWidth == *g_GraphicsInfo.VI_WIDTH_REG && ciInfo.dwWidth != windowSetting.uViWidth )
2050 width = windowSetting.uViWidth;
2051 height = windowSetting.uViHeight;
2054 StoreBackBufferToRDRAM( ciInfo.dwAddr, ciInfo.dwFormat, ciInfo.dwSize, width, height,
2055 windowSetting.uDisplayWidth, windowSetting.uDisplayHeight);
2057 g_uRecentCIInfoPtrs[ciInfoIdx]->bCopied = true;
2058 if( ciInfoIdx == 1 ) // to save the current front buffer
2060 CGraphicsContext::g_pGraphicsContext->UpdateFrame(true);
2066 SetImgInfo tempinfo;
2067 tempinfo.dwAddr = ciInfo.dwAddr;
2068 tempinfo.dwFormat = ciInfo.dwFormat;
2069 tempinfo.dwSize = ciInfo.dwSize;
2070 tempinfo.dwWidth = ciInfo.dwWidth;
2072 int idx = SetBackBufferAsRenderTexture(tempinfo, ciInfoIdx);
2074 CopyBackBufferToRenderTexture(idx, ciInfo, pSrcRect);
2076 gRenderTextureInfos[idx].crcCheckedAtFrame = status.gDlistCount;
2077 gRenderTextureInfos[idx].crcInRDRAM = ComputeRenderTextureCRCInRDRAM(idx);
2079 DEBUGGER_IF_DUMP((logTextureBuffer&&pSrcRect==NULL),TRACE1("SaveBackBuffer at 0x%08X", ciInfo.dwAddr));
2080 DEBUGGER_IF_DUMP((logTextureBuffer&&pSrcRect),TRACE5("SaveBackBuffer at 0x%08X, {%d,%d -%d,%d)", ciInfo.dwAddr,
2081 pSrcRect->left,pSrcRect->top,pSrcRect->right,pSrcRect->bottom));
2082 DEBUGGER_IF_DUMP(( pauseAtNext && eventToPause == NEXT_RENDER_TEXTURE),{g_pFrameBufferManager->DisplayRenderTexture(idx);});
2084 g_uRecentCIInfoPtrs[ciInfoIdx]->bCopied = true;