TxtrCacheEntry * CTextureManager::GetTexture(TxtrInfo * pgti, bool fromTMEM, bool doCRCCheck, bool AutoExtendTexture) { TxtrCacheEntry *pEntry; if( g_curRomInfo.bDisableTextureCRC ) doCRCCheck = false; gRDP.texturesAreReloaded = true; dwAsmCRC = 0; uint32 dwPalCRC = 0; pEntry = GetTxtrCacheEntry(pgti); bool loadFromTextureBuffer=false; int txtBufIdxToLoadFrom = -1; if( (frameBufferOptions.bCheckRenderTextures&&!frameBufferOptions.bWriteBackBufToRDRAM) || (frameBufferOptions.bCheckBackBufs&&!frameBufferOptions.bWriteBackBufToRDRAM) ) { txtBufIdxToLoadFrom = g_pFrameBufferManager->CheckAddrInRenderTextures(pgti->Address); if( txtBufIdxToLoadFrom >= 0 ) { loadFromTextureBuffer = true; // Check if it is the same size, RenderTextureInfo &info = gRenderTextureInfos[txtBufIdxToLoadFrom]; //if( info.pRenderTexture && info.CI_Info.dwAddr == pgti->Address && info.CI_Info.dwFormat == pgti->Format if( info.pRenderTexture && info.CI_Info.dwFormat == pgti->Format && info.CI_Info.dwSize == pgti->Size ) { info.txtEntry.ti = *pgti; return &info.txtEntry; } } } if( frameBufferOptions.bCheckBackBufs && g_pFrameBufferManager->CheckAddrInBackBuffers(pgti->Address, pgti->HeightToLoad*pgti->Pitch) >= 0 ) { if( !frameBufferOptions.bWriteBackBufToRDRAM ) { // Load the texture from recent back buffer txtBufIdxToLoadFrom = g_pFrameBufferManager->CheckAddrInRenderTextures(pgti->Address); if( txtBufIdxToLoadFrom >= 0 ) { loadFromTextureBuffer = true; // Check if it is the same size, RenderTextureInfo &info = gRenderTextureInfos[txtBufIdxToLoadFrom]; //if( info.pRenderTexture && info.CI_Info.dwAddr == pgti->Address && info.CI_Info.dwFormat == pgti->Format if( info.pRenderTexture && info.CI_Info.dwFormat == pgti->Format && info.CI_Info.dwSize == pgti->Size ) { info.txtEntry.ti = *pgti; return &info.txtEntry; } } } } if (pEntry && pEntry->dwTimeLastUsed == status.gRDPTime && status.gDlistCount != 0 && !status.bN64FrameBufferIsUsed ) // This is not good, Palatte may changes { // We've already calculated a CRC this frame! dwAsmCRC = pEntry->dwCRC; } else { if ( doCRCCheck ) { if( loadFromTextureBuffer ) dwAsmCRC = gRenderTextureInfos[txtBufIdxToLoadFrom].crcInRDRAM; else CalculateRDRAMCRC(pgti->pPhysicalAddress, pgti->LeftToLoad, pgti->TopToLoad, pgti->WidthToLoad, pgti->HeightToLoad, pgti->Size, pgti->Pitch); } } int maxCI = 0; if ( doCRCCheck && (pgti->Format == TXT_FMT_CI || (pgti->Format == TXT_FMT_RGBA && pgti->Size <= TXT_SIZE_8b ))) { //maxCI = pgti->Size == TXT_SIZE_8b ? 255 : 15; extern unsigned char CalculateMaxCI(void *pPhysicalAddress, uint32 left, uint32 top, uint32 width, uint32 height, uint32 size, uint32 pitchInBytes ); if( !pEntry || pEntry->dwCRC != dwAsmCRC || pEntry->maxCI < 0 ) { maxCI = CalculateMaxCI(pgti->pPhysicalAddress, pgti->LeftToLoad, pgti->TopToLoad, pgti->WidthToLoad, pgti->HeightToLoad, pgti->Size, pgti->Pitch); } else { maxCI = pEntry->maxCI; } //Check PAL CRC uint8 * pStart; uint32 dwPalSize = 16; uint32 dwOffset; if( pgti->Size == TXT_SIZE_8b ) { dwPalSize = 256; dwOffset = 0; } else { dwOffset = pgti->Palette << 4; } pStart = (uint8*)pgti->PalAddress+dwOffset*2; //uint32 y; //for (y = 0; y < dwPalSize*2; y+=4) //{ // dwPalCRC = (dwPalCRC + *(uint32*)&pStart[y]); //} uint32 dwAsmCRCSave = dwAsmCRC; //dwPalCRC = CalculateRDRAMCRC(pStart, 0, 0, dwPalSize, 1, TXT_SIZE_16b, dwPalSize*2); dwPalCRC = CalculateRDRAMCRC(pStart, 0, 0, maxCI+1, 1, TXT_SIZE_16b, dwPalSize*2); dwAsmCRC = dwAsmCRCSave; } if (pEntry && doCRCCheck ) { if(pEntry->dwCRC == dwAsmCRC && pEntry->dwPalCRC == dwPalCRC && (!loadFromTextureBuffer || gRenderTextureInfos[txtBufIdxToLoadFrom].updateAtFrame < pEntry->FrameLastUsed ) ) { // Tile is ok, return pEntry->dwUses++; pEntry->dwTimeLastUsed = status.gRDPTime; pEntry->FrameLastUsed = status.gDlistCount; LOG_TEXTURE(TRACE0(" Use current texture:\n")); pEntry->lastEntry = g_lastTextureEntry; g_lastTextureEntry = pEntry; lastEntryModified = false; DEBUGGER_IF_DUMP((pauseAtNext && loadFromTextureBuffer) , {DebuggerAppendMsg("Load cached texture from render_texture");} );
TxtrCacheEntry * CTextureManager::GetTexture(TxtrInfo * pgti, bool fromTMEM, bool doCRCCheck, bool AutoExtendTexture) { TxtrCacheEntry *pEntry; if( g_curRomInfo.bDisableTextureCRC ) doCRCCheck = false; gRDP.texturesAreReloaded = true; dwAsmCRC = 0; uint32 dwPalCRC = 0; pEntry = GetTxtrCacheEntry(pgti); bool loadFromTextureBuffer=false; int txtBufIdxToLoadFrom = -1; if( (frameBufferOptions.bCheckRenderTextures&&!frameBufferOptions.bWriteBackBufToRDRAM) || (frameBufferOptions.bCheckBackBufs&&!frameBufferOptions.bWriteBackBufToRDRAM) ) { txtBufIdxToLoadFrom = g_pFrameBufferManager->CheckAddrInRenderTextures(pgti->Address); if( txtBufIdxToLoadFrom >= 0 ) { loadFromTextureBuffer = true; // Check if it is the same size, RenderTextureInfo &info = gRenderTextureInfos[txtBufIdxToLoadFrom]; //if( info.pRenderTexture && info.CI_Info.dwAddr == pgti->Address && info.CI_Info.dwFormat == pgti->Format if( info.pRenderTexture && info.CI_Info.dwFormat == pgti->Format && info.CI_Info.dwSize == pgti->Size ) { info.txtEntry.ti = *pgti; return &info.txtEntry; } } } bool loadFromBackBuffer=false; if( frameBufferOptions.bCheckBackBufs && g_pFrameBufferManager->CheckAddrInBackBuffers(pgti->Address, pgti->HeightToLoad*pgti->Pitch) >= 0 ) { if( !frameBufferOptions.bWriteBackBufToRDRAM ) { // Load the texture from recent back buffer loadFromBackBuffer = true; txtBufIdxToLoadFrom = g_pFrameBufferManager->CheckAddrInRenderTextures(pgti->Address); if( txtBufIdxToLoadFrom >= 0 ) { loadFromTextureBuffer = true; // Check if it is the same size, RenderTextureInfo &info = gRenderTextureInfos[txtBufIdxToLoadFrom]; //if( info.pRenderTexture && info.CI_Info.dwAddr == pgti->Address && info.CI_Info.dwFormat == pgti->Format if( info.pRenderTexture && info.CI_Info.dwFormat == pgti->Format && info.CI_Info.dwSize == pgti->Size ) { info.txtEntry.ti = *pgti; return &info.txtEntry; } } } } if (pEntry && pEntry->dwTimeLastUsed == status.gRDPTime && status.gDlistCount != 0 && !status.bN64FrameBufferIsUsed ) // This is not good, Palatte may changes { // We've already calculated a CRC this frame! dwAsmCRC = pEntry->dwCRC; } else { if ( doCRCCheck ) { if( loadFromTextureBuffer ) dwAsmCRC = gRenderTextureInfos[txtBufIdxToLoadFrom].crcInRDRAM; else CalculateRDRAMCRC(pgti->pPhysicalAddress, pgti->LeftToLoad, pgti->TopToLoad, pgti->WidthToLoad, pgti->HeightToLoad, pgti->Size, pgti->Pitch); } } int maxCI = 0; if ( doCRCCheck && (pgti->Format == TXT_FMT_CI || (pgti->Format == TXT_FMT_RGBA && pgti->Size <= TXT_SIZE_8b ))) { //maxCI = pgti->Size == TXT_SIZE_8b ? 255 : 15; extern BYTE CalculateMaxCI(void *pPhysicalAddress, uint32 left, uint32 top, uint32 width, uint32 height, uint32 size, uint32 pitchInBytes ); if( !pEntry || pEntry->dwCRC != dwAsmCRC || pEntry->maxCI < 0 ) { maxCI = CalculateMaxCI(pgti->pPhysicalAddress, pgti->LeftToLoad, pgti->TopToLoad, pgti->WidthToLoad, pgti->HeightToLoad, pgti->Size, pgti->Pitch); } else { maxCI = pEntry->maxCI; } //Check PAL CRC uint8 * pStart; uint32 dwPalSize = 16; uint32 dwOffset; if( pgti->Size == TXT_SIZE_8b ) { dwPalSize = 256; dwOffset = 0; } else { dwOffset = pgti->Palette << 4; } pStart = (uint8*)pgti->PalAddress+dwOffset*2; //uint32 y; //for (y = 0; y < dwPalSize*2; y+=4) //{ // dwPalCRC = (dwPalCRC + *(uint32*)&pStart[y]); //} uint32 dwAsmCRCSave = dwAsmCRC; //dwPalCRC = CalculateRDRAMCRC(pStart, 0, 0, dwPalSize, 1, TXT_SIZE_16b, dwPalSize*2); dwPalCRC = CalculateRDRAMCRC(pStart, 0, 0, maxCI+1, 1, TXT_SIZE_16b, dwPalSize*2); dwAsmCRC = dwAsmCRCSave; } // Fix for textures where ti is identical. In this case just the first texture has been added to the Cache. // for further instances this texture has just been replaced instead of adding the additional texture to the same index // in the cachelist. This was causing the slowdowns. Thus we have to iterate through the bucket of the cache list and see // which of the textures that have been placed to it is the one we are looking for if(pEntry && doCRCCheck && pEntry->dwCRC == dwAsmCRC && pEntry->dwPalCRC != dwPalCRC && (!loadFromTextureBuffer || gRenderTextureInfos[txtBufIdxToLoadFrom].updateAtFrame < pEntry->FrameLastUsed )){ bool bChecksumDoMatch=false; // iterate through all textures located in the same bucket while(pEntry->pNext){ // check the next texture in the same bucket pEntry = pEntry->pNext; // let's see if this one is the one we are actually looking for if(pEntry->dwCRC == dwAsmCRC && pEntry->dwPalCRC == dwPalCRC && (!loadFromTextureBuffer || gRenderTextureInfos[txtBufIdxToLoadFrom].updateAtFrame < pEntry->FrameLastUsed )){ // found it in the neighbourhood bChecksumDoMatch = true; break; } } // cannot find it if(!bChecksumDoMatch){ // try to load it pEntry = NULL; } } if (pEntry && doCRCCheck ) { if(pEntry->dwCRC == dwAsmCRC && pEntry->dwPalCRC == dwPalCRC && (!loadFromTextureBuffer || gRenderTextureInfos[txtBufIdxToLoadFrom].updateAtFrame < pEntry->FrameLastUsed ) ) { // Tile is ok, return pEntry->dwUses++; pEntry->dwTimeLastUsed = status.gRDPTime; pEntry->FrameLastUsed = status.gDlistCount; LOG_TEXTURE(TRACE0(" Use current texture:\n")); pEntry->lastEntry = g_lastTextureEntry; g_lastTextureEntry = pEntry; lastEntryModified = false; DEBUGGER_IF_DUMP((pauseAtNext && loadFromTextureBuffer) , {DebuggerAppendMsg("Load cached texture from render_texture");} );