X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=source%2Frice_gles%2Fsrc%2FRSP_GBI_Others.h;fp=source%2Frice_gles%2Fsrc%2FRSP_GBI_Others.h;h=c8649d6ae4353a302873d99f397277e008bbf425;hb=d07c171fa694cae985ad7045f9ce2b2f1a5699b4;hp=0000000000000000000000000000000000000000;hpb=ca22e7b76883b946060a6b40bb8709c1981e1cf6;p=mupen64plus-pandora.git diff --git a/source/rice_gles/src/RSP_GBI_Others.h b/source/rice_gles/src/RSP_GBI_Others.h new file mode 100644 index 0000000..c8649d6 --- /dev/null +++ b/source/rice_gles/src/RSP_GBI_Others.h @@ -0,0 +1,1731 @@ +/* +Copyright (C) 2002 Rice1964 + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +// A few ucode used in DKR and Others Special games + +#include + +#include "Render.h" +#include "Timing.h" +#include "osal_preproc.h" + +uint32 dwConkerVtxZAddr=0; + +static void RDP_GFX_DumpVtxInfoDKR(uint32 dwAddr, uint32 dwV0, uint32 dwN); + +void RDP_GFX_DLInMem(Gfx *gfx) +{ + uint32 dwLimit = ((gfx->words.w0) >> 16) & 0xFF; + uint32 dwPush = RSP_DLIST_PUSH; //((gfx->words.w0) >> 16) & 0xFF; + uint32 dwAddr = 0x00000000 | (gfx->words.w1); //RSPSegmentAddr((gfx->words.w1)); + + LOG_UCODE(" Address=0x%08x Push: 0x%02x", dwAddr, dwPush); + + switch (dwPush) + { + case RSP_DLIST_PUSH: + LOG_UCODE(" Pushing DisplayList 0x%08x", dwAddr); + gDlistStackPointer++; + gDlistStack[gDlistStackPointer].pc = dwAddr; + gDlistStack[gDlistStackPointer].countdown = dwLimit; + + break; + case RSP_DLIST_NOPUSH: + LOG_UCODE(" Jumping to DisplayList 0x%08x", dwAddr); + gDlistStack[gDlistStackPointer].pc = dwAddr; + gDlistStack[gDlistStackPointer].countdown = dwLimit; + break; + } + + LOG_UCODE(""); + LOG_UCODE("\\/ \\/ \\/ \\/ \\/ \\/ \\/ \\/ \\/ \\/ \\/ \\/ \\/ \\/ \\/"); + LOG_UCODE("#############################################"); +} + +extern Matrix ALIGN(16, dkrMatrixTransposed) +void RSP_Mtx_DKR(Gfx *gfx) +{ + uint32 dwAddr = RSPSegmentAddr((gfx->words.w1)); + uint32 dwCommand = ((gfx->words.w0)>>16)&0xFF; + //uint32 dwLength = ((gfx->words.w0)) &0xFFFF; + + dwAddr = (gfx->words.w1)+RSPSegmentAddr(gRSP.dwDKRMatrixAddr); + + //gRSP.DKRCMatrixIndex = ((gfx->words.w0)>>22)&3; + bool mul=false; + int index = 0; + switch( dwCommand ) + { + case 0xC0: // DKR + gRSP.DKRCMatrixIndex = index = 3; + break; + case 0x80: // DKR + gRSP.DKRCMatrixIndex = index = 2; + break; + case 0x40: // DKR + gRSP.DKRCMatrixIndex = index = 1; + break; + case 0x20: // DKR + gRSP.DKRCMatrixIndex = index = 0; + break; + case 0x00: + gRSP.DKRCMatrixIndex = index = 0; + break; + case 0x01: + //mul = true; + gRSP.DKRCMatrixIndex = index = 1; + break; + case 0x02: + //mul = true; + gRSP.DKRCMatrixIndex = index = 2; + break; + case 0x03: + //mul = true; + gRSP.DKRCMatrixIndex = index = 3; + break; + case 0x81: + index = 1; + mul = true; + break; + case 0x82: + index = 2; + mul = true; + break; + case 0x83: + index = 3; + mul = true; + break; + default: + DebuggerAppendMsg("Fix me, mtx DKR, cmd=%08X", dwCommand); + break; + } + + // Load matrix from dwAddr + Matrix &mat = gRSP.DKRMatrixes[index]; + LoadMatrix(dwAddr); + + if( mul ) + { + mat = matToLoad*gRSP.DKRMatrixes[0]; + } + else + { + mat = matToLoad; + } + + if( status.isSSEEnabled ) + MatrixTranspose(&dkrMatrixTransposed, &mat); + + DEBUGGER_IF_DUMP(logMatrix,TRACE3("DKR Matrix: cmd=0x%X, idx = %d, mul=%d", dwCommand, index, mul)); + LOG_UCODE(" DKR Loading Mtx: %d, command=%d", index, dwCommand); + DEBUGGER_PAUSE_AND_DUMP(NEXT_MATRIX_CMD,{TRACE0("Paused at DKR Matrix Cmd");}); +} + +void RSP_Vtx_DKR(Gfx *gfx) +{ + uint32 dwAddr = RSPSegmentAddr((gfx->words.w1)); + uint32 dwV0 = (((gfx->words.w0) >> 9 )&0x1F); + uint32 dwN = (((gfx->words.w0) >>19 )&0x1F)+1; + + if( gfx->words.w0 & 0x00010000 ) + { + if( gRSP.DKRBillBoard ) + gRSP.DKRVtxCount = 1; + } + else + { + gRSP.DKRVtxCount = 0; + } + + dwV0 += gRSP.DKRVtxCount; + + LOG_UCODE(" Address 0x%08x, v0: %d, Num: %d", dwAddr, dwV0, dwN); + DEBUGGER_ONLY_IF( (pauseAtNext && (eventToPause==NEXT_VERTEX_CMD||eventToPause==NEXT_MATRIX_CMD)), {DebuggerAppendMsg("DKR Vtx: Cmd0=%08X, Cmd1=%08X", (gfx->words.w0), (gfx->words.w1));}); + + VTX_DUMP(TRACE2("Vtx_DKR, cmd0=%08X cmd1=%08X", (gfx->words.w0), (gfx->words.w1))); + VTX_DUMP(TRACE2("Vtx_DKR, v0=%d n=%d", dwV0, dwN)); + + if (dwV0 >= 32) + dwV0 = 31; + + if ((dwV0 + dwN) > 32) + { + WARNING(TRACE0("Warning, attempting to load into invalid vertex positions")); + dwN = 32 - dwV0; + } + + + //if( dwAddr == 0 || dwAddr < 0x2000) + { + dwAddr = (gfx->words.w1)+RSPSegmentAddr(gRSP.dwDKRVtxAddr); + } + + // Check that address is valid... + if ((dwAddr + (dwN*16)) > g_dwRamSize) + { + WARNING(TRACE1("ProcessVertexData: Address out of range (0x%08x)", dwAddr)); + } + else + { + ProcessVertexDataDKR(dwAddr, dwV0, dwN); + + status.dwNumVertices += dwN; + + RDP_GFX_DumpVtxInfoDKR(dwAddr, dwV0, dwN); + } +} + + +void RSP_Vtx_Gemini(Gfx *gfx) +{ + uint32 dwAddr = RSPSegmentAddr((gfx->words.w1)); + uint32 dwV0 = (((gfx->words.w0)>>9)&0x1F); + uint32 dwN = (((gfx->words.w0) >>19 )&0x1F); + + LOG_UCODE(" Address 0x%08x, v0: %d, Num: %d", dwAddr, dwV0, dwN); + DEBUGGER_ONLY_IF( (pauseAtNext && (eventToPause==NEXT_VERTEX_CMD||eventToPause==NEXT_MATRIX_CMD)), {DebuggerAppendMsg("DKR Vtx: Cmd0=%08X, Cmd1=%08X", (gfx->words.w0), (gfx->words.w1));}); + + VTX_DUMP(TRACE2("Vtx_DKR, cmd0=%08X cmd1=%08X", (gfx->words.w0), (gfx->words.w1))); + + if (dwV0 >= 32) + dwV0 = 31; + + if ((dwV0 + dwN) > 32) + { + TRACE0("Warning, attempting to load into invalid vertex positions"); + dwN = 32 - dwV0; + } + + + //if( dwAddr == 0 || dwAddr < 0x2000) + { + dwAddr = (gfx->words.w1)+RSPSegmentAddr(gRSP.dwDKRVtxAddr); + } + + // Check that address is valid... + if ((dwAddr + (dwN*16)) > g_dwRamSize) + { + TRACE1("ProcessVertexData: Address out of range (0x%08x)", dwAddr); + } + else + { + ProcessVertexDataDKR(dwAddr, dwV0, dwN); + + status.dwNumVertices += dwN; + + RDP_GFX_DumpVtxInfoDKR(dwAddr, dwV0, dwN); + } +} + +// DKR verts are extra 4 bytes +void RDP_GFX_DumpVtxInfoDKR(uint32 dwAddr, uint32 dwV0, uint32 dwN) +{ +#ifdef DEBUGGER + uint32 dwV; + int i; + + short * psSrc = (short *)(g_pRDRAMu8 + dwAddr); + + i = 0; + for (dwV = dwV0; dwV < dwV0 + dwN; dwV++) + { + float x = (float)psSrc[(i + 0) ^ 1]; + float y = (float)psSrc[(i + 1) ^ 1]; + float z = (float)psSrc[(i + 2) ^ 1]; + + //uint16 wFlags = CRender::g_pRender->m_dwVecFlags[dwV]; //(uint16)psSrc[3^0x1]; + + uint16 wA = psSrc[(i + 3) ^ 1]; + uint16 wB = psSrc[(i + 4) ^ 1]; + + uint8 a = wA>>8; + uint8 b = (uint8)wA; + uint8 c = wB>>8; + uint8 d = (uint8)wB; + + XVECTOR4 & t = g_vecProjected[dwV]; + + + LOG_UCODE(" #%02d Pos: {% 6f,% 6f,% 6f} Extra: %02x %02x %02x %02x (transf: {% 6f,% 6f,% 6f})", + dwV, x, y, z, a, b, c, d, t.x, t.y, t.z ); + + i+=5; + } + + + uint16 * pwSrc = (uint16 *)(g_pRDRAMu8 + dwAddr); + i = 0; + for (dwV = dwV0; dwV < dwV0 + dwN; dwV++) + { + LOG_UCODE(" #%02d %04x %04x %04x %04x %04x", + dwV, pwSrc[(i + 0) ^ 1], + pwSrc[(i + 1) ^ 1], + pwSrc[(i + 2) ^ 1], + pwSrc[(i + 3) ^ 1], + pwSrc[(i + 4) ^ 1]); + + i += 5; + } + +#endif // DEBUGGER +} + +void DLParser_Set_Addr_Ucode6(Gfx *gfx) +{ + gRSP.dwDKRMatrixAddr = (gfx->words.w0)&0x00FFFFFF; + gRSP.dwDKRVtxAddr = (gfx->words.w1)&0x00FFFFFF; + gRSP.DKRVtxCount=0; +} + + + +void RSP_Vtx_WRUS(Gfx *gfx) +{ + uint32 dwAddr = RSPSegmentAddr((gfx->words.w1)); + uint32 dwLength = ((gfx->words.w0))&0xFFFF; + + uint32 dwN= (dwLength + 1) / 0x210; + //uint32 dwN= (dwLength >> 9); + //uint32 dwV0 = (((gfx->words.w0)>>16)&0x3f)/5; + uint32 dwV0 = (((gfx->words.w0)>>16)&0xFF)/5; + + LOG_UCODE(" Address 0x%08x, v0: %d, Num: %d, Length: 0x%04x", dwAddr, dwV0, dwN, dwLength); + + if (dwV0 >= 32) + dwV0 = 31; + + if ((dwV0 + dwN) > 32) + { + TRACE0("Warning, attempting to load into invalid vertex positions"); + dwN = 32 - dwV0; + } + + ProcessVertexData(dwAddr, dwV0, dwN); + + status.dwNumVertices += dwN; + + DisplayVertexInfo(dwAddr, dwV0, dwN); +} + +void RSP_Vtx_ShadowOfEmpire(Gfx *gfx) +{ + uint32 dwAddr = RSPSegmentAddr((gfx->words.w1)); + uint32 dwLength = ((gfx->words.w0))&0xFFFF; + + uint32 dwN= (((gfx->words.w0) >> 4) & 0xFFF) / 33 + 1; + uint32 dwV0 = 0; + + LOG_UCODE(" Address 0x%08x, v0: %d, Num: %d, Length: 0x%04x", dwAddr, dwV0, dwN, dwLength); + + if (dwV0 >= 32) + dwV0 = 31; + + if ((dwV0 + dwN) > 32) + { + TRACE0("Warning, attempting to load into invalid vertex positions"); + dwN = 32 - dwV0; + } + + ProcessVertexData(dwAddr, dwV0, dwN); + + status.dwNumVertices += dwN; + + DisplayVertexInfo(dwAddr, dwV0, dwN); +} + + +void RSP_DL_In_MEM_DKR(Gfx *gfx) +{ + // This cmd is likely to execute number of ucode at the given address + uint32 dwAddr = (gfx->words.w1);//RSPSegmentAddr((gfx->words.w1)); + { + gDlistStackPointer++; + gDlistStack[gDlistStackPointer].pc = dwAddr; + gDlistStack[gDlistStackPointer].countdown = (((gfx->words.w0)>>16)&0xFF); + } +} +uint16 ConvertYUVtoR5G5B5X1(int y, int u, int v) +{ + float r = y + (1.370705f * (v-128)); + float g = y - (0.698001f * (v-128)) - (0.337633f * (u-128)); + float b = y + (1.732446f * (u-128)); + r *= 0.125f; + g *= 0.125f; + b *= 0.125f; + + //clipping the result + if (r > 32) r = 32; + if (g > 32) g = 32; + if (b > 32) b = 32; + if (r < 0) r = 0; + if (g < 0) g = 0; + if (b < 0) b = 0; + + uint16 c = (uint16)(((uint16)(r) << 11) | + ((uint16)(g) << 6) | + ((uint16)(b) << 1) | 1); + return c; +} + +void TexRectToN64FrameBuffer_YUV_16b(uint32 x0, uint32 y0, uint32 width, uint32 height) +{ + // Convert YUV image at TImg and Copy the texture into the N64 RDRAM framebuffer memory + + uint32 n64CIaddr = g_CI.dwAddr; + uint32 n64CIwidth = g_CI.dwWidth; + + for (uint32 y = 0; y < height; y++) + { + uint32* pN64Src = (uint32*)(g_pRDRAMu8+(g_TI.dwAddr&(g_dwRamSize-1)))+y*(g_TI.dwWidth>>1); + uint16* pN64Dst = (uint16*)(g_pRDRAMu8+(n64CIaddr&(g_dwRamSize-1)))+(y+y0)*n64CIwidth; + + for (uint32 x = 0; x < width; x+=2) + { + uint32 val = *pN64Src++; + int y0 = (uint8)val&0xFF; + int v = (uint8)(val>>8)&0xFF; + int y1 = (uint8)(val>>16)&0xFF; + int u = (uint8)(val>>24)&0xFF; + + pN64Dst[x+x0] = ConvertYUVtoR5G5B5X1(y0,u,v); + pN64Dst[x+x0+1] = ConvertYUVtoR5G5B5X1(y1,u,v); + } + } +} + +extern uObjMtxReal gObjMtxReal; +void DLParser_OgreBatter64BG(Gfx *gfx) +{ +#ifdef DEBUGGER +uint32 dwAddr = RSPSegmentAddr((gfx->words.w1)); +uObjTxSprite *ptr = (uObjTxSprite*)(g_pRDRAMu8+dwAddr); +#endif + +PrepareTextures(); + +CTexture *ptexture = g_textures[0].m_pCTexture; +TexRectToN64FrameBuffer_16b( (uint32)gObjMtxReal.X, (uint32)gObjMtxReal.Y, ptexture->m_dwWidth, ptexture->m_dwHeight, gRSP.curTile); + +#ifdef DEBUGGER +CRender::g_pRender->DrawSpriteR(*ptr, false); + +DEBUGGER_PAUSE_AT_COND_AND_DUMP_COUNT_N((pauseAtNext && +(eventToPause==NEXT_OBJ_TXT_CMD|| eventToPause==NEXT_FLUSH_TRI)), +{DebuggerAppendMsg("OgreBatter 64 BG: Addr=%08X\n", dwAddr);}); +#endif +} + +void DLParser_Bomberman2TextRect(Gfx *gfx) +{ + // Bomberman 64 - The Second Attack! (U) [!] + // The 0x02 cmd, list a TexRect cmd + + if( options.enableHackForGames == HACK_FOR_OGRE_BATTLE && gRDP.tiles[7].dwFormat == TXT_FMT_YUV ) + { + TexRectToN64FrameBuffer_YUV_16b( (uint32)gObjMtxReal.X, (uint32)gObjMtxReal.Y, 16, 16); + //DLParser_OgreBatter64BG((gfx->words.w0), (gfx->words.w1)); + return; + } + + uint32 dwAddr = RSPSegmentAddr((gfx->words.w1)); + uObjSprite *info = (uObjSprite*)(g_pRDRAMu8+dwAddr); + + uint32 dwTile = gRSP.curTile; + + PrepareTextures(); + + //CRender::g_pRender->SetCombinerAndBlender(); + + uObjTxSprite drawinfo; + memcpy( &(drawinfo.sprite), info, sizeof(uObjSprite)); + CRender::g_pRender->DrawSpriteR(drawinfo, false, dwTile, 0, 0, drawinfo.sprite.imageW/32, drawinfo.sprite.imageH/32); + + DEBUGGER_PAUSE_AT_COND_AND_DUMP_COUNT_N((pauseAtNext && (eventToPause==NEXT_TRIANGLE|| eventToPause==NEXT_FLUSH_TRI)), + { + DebuggerAppendMsg("Bomberman 64 - TextRect: Addr=%08X\n", dwAddr); + dwAddr &= (g_dwRamSize-1); + DebuggerAppendMsg("%08X-%08X-%08X-%08X-%08X-%08X\n", RDRAM_UWORD(dwAddr), RDRAM_UWORD(dwAddr+4), + RDRAM_UWORD(dwAddr+8), RDRAM_UWORD(dwAddr+12), RDRAM_UWORD(dwAddr+16), RDRAM_UWORD(dwAddr+20) ); + } + ); +} + + +void RSP_MoveWord_DKR(Gfx *gfx) +{ + SP_Timing(RSP_GBI1_MoveWord); + uint32 dwNumLights; + + switch ((gfx->words.w0) & 0xFF) + { + case RSP_MOVE_WORD_NUMLIGHT: + dwNumLights = (gfx->words.w1)&0x7; + LOG_UCODE(" RSP_MOVE_WORD_NUMLIGHT: Val:%d", dwNumLights); + + gRSP.ambientLightIndex = dwNumLights; + SetNumLights(dwNumLights); + //gRSP.DKRBillBoard = (gfx->words.w1)&0x1 ? true : false; + gRSP.DKRBillBoard = (gfx->words.w1)&0x7 ? true : false; + + LOG_UCODE(" gRSP.DKRBillBoard = %d", gRSP.DKRBillBoard); + DEBUGGER_PAUSE_AND_DUMP_COUNT_N(NEXT_MATRIX_CMD, {DebuggerAppendMsg("DKR Moveword, select gRSP.DKRBillBoard %s, cmd0=%08X, cmd1=%08X", gRSP.DKRBillBoard?"true":"false", (gfx->words.w0), (gfx->words.w1));}); + break; + case RSP_MOVE_WORD_LIGHTCOL: + gRSP.DKRCMatrixIndex = ((gfx->words.w1)>>6)&7; + //gRSP.DKRCMatrixIndex = ((gfx->words.w1)>>6)&3; + LOG_UCODE(" gRSP.DKRCMatrixIndex = %d", gRSP.DKRCMatrixIndex); + DEBUGGER_PAUSE_AND_DUMP_COUNT_N(NEXT_MATRIX_CMD, {DebuggerAppendMsg("DKR Moveword, select matrix %d, cmd0=%08X, cmd1=%08X", gRSP.DKRCMatrixIndex, (gfx->words.w0), (gfx->words.w1));}); + break; + default: + RSP_GBI1_MoveWord(gfx); + break; + } +} + + +void RSP_DMA_Tri_DKR(Gfx *gfx) +{ + BOOL bTrisAdded = FALSE; + uint32 dwAddr = RSPSegmentAddr((gfx->words.w1)); + uint32 flag = ((gfx->words.w0) & 0xFF0000) >> 16; + if (flag&1) + CRender::g_pRender->SetCullMode(false,true); + else + CRender::g_pRender->SetCullMode(false,false); + + uint32 dwNum = (((gfx->words.w0) & 0xFFF0) >>4 ); + uint32 * pData = (uint32*)&g_pRDRAMu32[dwAddr/4]; + + if( dwAddr+16*dwNum >= g_dwRamSize ) + { + TRACE0("DMATRI invalid memory pointer"); + return; + } + + TRI_DUMP(TRACE2("DMATRI, addr=%08X, Cmd0=%08X\n", dwAddr, (gfx->words.w0))); + + status.primitiveType = PRIM_DMA_TRI; + + for (uint32 i = 0; i < dwNum; i++) + { + LOG_UCODE(" 0x%08x: %08x %08x %08x %08x", dwAddr + i*16, + pData[0], pData[1], pData[2], pData[3]); + + uint32 dwInfo = pData[0]; + + uint32 dwV0 = (dwInfo >> 16) & 0x1F; + uint32 dwV1 = (dwInfo >> 8) & 0x1F; + uint32 dwV2 = (dwInfo ) & 0x1F; + + TRI_DUMP(TRACE5("DMATRI: %d, %d, %d (%08X-%08X)", dwV0,dwV1,dwV2,(gfx->words.w0),(gfx->words.w1))); + + //if (IsTriangleVisible(dwV0, dwV1, dwV2)) + { + DEBUG_DUMP_VERTEXES("DmaTri", dwV0, dwV1, dwV2); + LOG_UCODE(" Tri: %d,%d,%d", dwV0, dwV1, dwV2); + if (!bTrisAdded )//&& CRender::g_pRender->IsTextureEnabled()) + { + PrepareTextures(); + InitVertexTextureConstants(); + } + + // Generate texture coordinates + short s0 = ((short)(pData[1]>>16)); + short t0 = ((short)(pData[1]&0xFFFF)); + short s1 = ((short)(pData[2]>>16)); + short t1 = ((short)(pData[2]&0xFFFF)); + short s2 = ((short)(pData[3]>>16)); + short t2 = ((short)(pData[3]&0xFFFF)); + + TRI_DUMP( + { + DebuggerAppendMsg(" (%d,%d), (%d,%d), (%d,%d)",s0,t0,s1,t1,s2,t2); + DebuggerAppendMsg(" (%08X), (%08X), (%08X), (%08X)",pData[0],pData[1],pData[2],pData[3]); + }); + CRender::g_pRender->SetVtxTextureCoord(dwV0, s0, t0); + CRender::g_pRender->SetVtxTextureCoord(dwV1, s1, t1); + CRender::g_pRender->SetVtxTextureCoord(dwV2, s2, t2); + + if( !bTrisAdded ) + { + CRender::g_pRender->SetCombinerAndBlender(); + } + + bTrisAdded = true; + PrepareTriangle(dwV0, dwV1, dwV2); + } + + pData += 4; + + } + + if (bTrisAdded) + { + CRender::g_pRender->DrawTriangles(); + } + gRSP.DKRVtxCount=0; +} + +uint32 dwPDCIAddr = 0; +void ProcessVertexDataPD(uint32 dwAddr, uint32 dwV0, uint32 dwNum); +void RSP_Vtx_PD(Gfx *gfx) +{ + SP_Timing(RSP_GBI0_Vtx); + + uint32 dwAddr = RSPSegmentAddr((gfx->words.w1)); + uint32 dwV0 = ((gfx->words.w0)>>16)&0x0F; + uint32 dwN = (((gfx->words.w0)>>20)&0x0F)+1; + //uint32 dwLength = ((gfx->words.w0))&0xFFFF; + + LOG_UCODE(" Address 0x%08x, v0: %d, Num: %d", dwAddr, dwV0, dwN); + + ProcessVertexDataPD(dwAddr, dwV0, dwN); + status.dwNumVertices += dwN; +} + +void RSP_Set_Vtx_CI_PD(Gfx *gfx) +{ + // Color index buf address + dwPDCIAddr = RSPSegmentAddr((gfx->words.w1)); +} + +void RSP_Tri4_PD(Gfx *gfx) +{ + uint32 w0 = gfx->words.w0; + uint32 w1 = gfx->words.w1; + + status.primitiveType = PRIM_TRI2; + + // While the next command pair is Tri2, add vertices + uint32 dwPC = gDlistStack[gDlistStackPointer].pc; + + BOOL bTrisAdded = FALSE; + + do { + uint32 dwFlag = (w0>>16)&0xFF; + LOG_UCODE(" PD Tri4: 0x%08x 0x%08x Flag: 0x%02x", w0, w1, dwFlag); + + BOOL bVisible; + for( uint32 i=0; i<4; i++) + { + uint32 v0 = (w1>>(4+(i<<3))) & 0xF; + uint32 v1 = (w1>>( (i<<3))) & 0xF; + uint32 v2 = (w0>>( (i<<2))) & 0xF; + bVisible = IsTriangleVisible(v0, v2, v1); + LOG_UCODE(" (%d, %d, %d) %s", v0, v1, v2, bVisible ? "": "(clipped)"); + if (bVisible) + { + DEBUG_DUMP_VERTEXES("Tri4_PerfectDark 1/2", v0, v1, v2); + if (!bTrisAdded && CRender::g_pRender->IsTextureEnabled()) + { + PrepareTextures(); + InitVertexTextureConstants(); + } + + if( !bTrisAdded ) + { + CRender::g_pRender->SetCombinerAndBlender(); + } + + bTrisAdded = true; + PrepareTriangle(v0, v2, v1); + } + } + + w0 = *(uint32 *)(g_pRDRAMu8 + dwPC+0); + w1 = *(uint32 *)(g_pRDRAMu8 + dwPC+4); + dwPC += 8; + +#ifdef DEBUGGER + } while (!(pauseAtNext && eventToPause==NEXT_TRIANGLE) && (w0>>24) == (uint8)RSP_TRI2); +#else + } while ((w0>>24) == (uint8)RSP_TRI2); +#endif + + gDlistStack[gDlistStackPointer].pc = dwPC-8; + + if (bTrisAdded) + { + CRender::g_pRender->DrawTriangles(); + } + + DEBUG_TRIANGLE(TRACE0("Pause at PD Tri4")); +} + + +void DLParser_Tri4_Conker(Gfx *gfx) +{ + uint32 w0 = gfx->words.w0; + uint32 w1 = gfx->words.w1; + + status.primitiveType = PRIM_TRI2; + + // While the next command pair is Tri2, add vertices + uint32 dwPC = gDlistStack[gDlistStackPointer].pc; + + BOOL bTrisAdded = FALSE; + + do { + LOG_UCODE(" Conker Tri4: 0x%08x 0x%08x", w0, w1); + uint32 idx[12]; + idx[0] = (w1 )&0x1F; + idx[1] = (w1>> 5)&0x1F; + idx[2] = (w1>>10)&0x1F; + idx[3] = (w1>>15)&0x1F; + idx[4] = (w1>>20)&0x1F; + idx[5] = (w1>>25)&0x1F; + + idx[6] = (w0 )&0x1F; + idx[7] = (w0>> 5)&0x1F; + idx[8] = (w0>>10)&0x1F; + + idx[ 9] = (((w0>>15)&0x7)<<2)|(w1>>30); + idx[10] = (w0>>18)&0x1F; + idx[11] = (w0>>23)&0x1F; + + BOOL bVisible; + for( uint32 i=0; i<4; i++) + { + uint32 v0=idx[i*3 ]; + uint32 v1=idx[i*3+1]; + uint32 v2=idx[i*3+2]; + bVisible = IsTriangleVisible(v0, v1, v2); + LOG_UCODE(" (%d, %d, %d) %s", v0, v1, v2, bVisible ? "": "(clipped)"); + if (bVisible) + { + DEBUG_DUMP_VERTEXES("Tri4 Conker:", v0, v1, v2); + if (!bTrisAdded && CRender::g_pRender->IsTextureEnabled()) + { + PrepareTextures(); + InitVertexTextureConstants(); + } + + if( !bTrisAdded ) + { + CRender::g_pRender->SetCombinerAndBlender(); + } + + bTrisAdded = true; + PrepareTriangle(v0, v1, v2); + } + } + + w0 = *(uint32 *)(g_pRDRAMu8 + dwPC+0); + w1 = *(uint32 *)(g_pRDRAMu8 + dwPC+4); + dwPC += 8; + +#ifdef DEBUGGER + } while (!(pauseAtNext && eventToPause==NEXT_TRIANGLE) && (w0>>28) == 1 ); +#else + } while ((w0>>28) == 1); +#endif + + gDlistStack[gDlistStackPointer].pc = dwPC-8; + + if (bTrisAdded) + { + CRender::g_pRender->DrawTriangles(); + } + + DEBUG_TRIANGLE(TRACE0("Pause at Conker Tri4")); +} + +void RDP_GFX_Force_Vertex_Z_Conker(uint32 dwAddr) +{ + VTX_DUMP( + { + s8 * pcBase = g_pRDRAMs8 + (dwAddr&(g_dwRamSize-1)); + uint32 * pdwBase = (uint32 *)pcBase; + + for (int i = 0; i < 4; i++) + { + DebuggerAppendMsg(" %08x %08x %08x %08x", pdwBase[0], pdwBase[1], pdwBase[2], pdwBase[3]); + pdwBase+=4; + } + }); + + dwConkerVtxZAddr = dwAddr; + DEBUGGER_PAUSE_AND_DUMP(NEXT_VERTEX_CMD,{TRACE0("Paused at RDP_GFX_Force_Matrix_Conker Cmd");}); +} + + + +void DLParser_MoveMem_Conker(Gfx *gfx) +{ + uint32 dwType = ((gfx->words.w0) ) & 0xFE; + uint32 dwAddr = RSPSegmentAddr((gfx->words.w1)); + if( dwType == RSP_GBI2_MV_MEM__MATRIX ) + { + LOG_UCODE(" DLParser_MoveMem_Conker"); + RDP_GFX_Force_Vertex_Z_Conker(dwAddr); + } + else if( dwType == RSP_GBI2_MV_MEM__LIGHT ) + { + LOG_UCODE(" MoveMem Light Conker"); + uint32 dwOffset2 = ((gfx->words.w0) >> 5) & 0x3FFF; + uint32 dwLight=0xFF; + if( dwOffset2 >= 0x30 ) + { + dwLight = (dwOffset2 - 0x30)/0x30; + LOG_UCODE(" Light %d:", dwLight); + RSP_MoveMemLight(dwLight, dwAddr); + } + else + { + // fix me + //TRACE0("Check me in DLParser_MoveMem_Conker - MoveMem Light"); + } + DEBUGGER_PAUSE_AND_DUMP_COUNT_N( NEXT_SET_LIGHT, + { + DebuggerAppendMsg("RSP_MoveMemLight: %d, Addr=%08X, cmd0=%08X", dwLight, dwAddr, (gfx->words.w0)); + TRACE0("Pause after MoveMemLight"); + }); + } + else + { + RSP_GBI2_MoveMem(gfx); + } +} + +extern void ProcessVertexDataConker(uint32 dwAddr, uint32 dwV0, uint32 dwNum); +void RSP_Vtx_Conker(Gfx *gfx) +{ + uint32 dwAddr = RSPSegmentAddr((gfx->words.w1)); + uint32 dwVEnd = (((gfx->words.w0) )&0xFFF)/2; + uint32 dwN = (((gfx->words.w0)>>12)&0xFFF); + uint32 dwV0 = dwVEnd - dwN; + + LOG_UCODE(" Vtx: Address 0x%08x, vEnd: %d, v0: %d, Num: %d", dwAddr, dwVEnd, dwV0, dwN); + + ProcessVertexDataConker(dwAddr, dwV0, dwN); + status.dwNumVertices += dwN; + DisplayVertexInfo(dwAddr, dwV0, dwN); +} + + +void DLParser_MoveWord_Conker(Gfx *gfx) +{ + uint32 dwType = ((gfx->words.w0) >> 16) & 0xFF; + if( dwType != RSP_MOVE_WORD_NUMLIGHT ) + { + RSP_GBI2_MoveWord(gfx); + } + else + { + uint32 dwNumLights = ((gfx->words.w1)/48); + LOG_UCODE("Conker RSP_MOVE_WORD_NUMLIGHT: %d", dwNumLights); + gRSP.ambientLightIndex = dwNumLights+1; + SetNumLights(dwNumLights); + DEBUGGER_PAUSE_AND_DUMP_COUNT_N( NEXT_SET_LIGHT, + { + DebuggerAppendMsg("SetNumLights: %d", dwNumLights); + TRACE0("Pause after SetNumLights"); + }); + } +} + +void DLParser_Ucode8_0x0(Gfx *gfx) +{ + LOG_UCODE("DLParser_Ucode8_0x0"); + + if( (gfx->words.w0) == 0 && (gfx->words.w1) ) + { + uint32 newaddr = RSPSegmentAddr((gfx->words.w1)); + + if( newaddr && newaddr < g_dwRamSize) + { + if( gDlistStackPointer < MAX_DL_STACK_SIZE-1 ) + { + gDlistStackPointer++; + gDlistStack[gDlistStackPointer].pc = newaddr+8; // Always skip the first 2 entries + gDlistStack[gDlistStackPointer].countdown = MAX_DL_COUNT; + } + else + { + DebuggerAppendMsg("Error, gDlistStackPointer overflow"); + } + } + } + else + { + LOG_UCODE("DLParser_Ucode8_0x0, skip 0x%08X, 0x%08x", (gfx->words.w0), (gfx->words.w1)); + gDlistStack[gDlistStackPointer].pc += 8; + } +} + + +uint32 Rogue_Squadron_Vtx_XYZ_Cmd; +uint32 Rogue_Squadron_Vtx_XYZ_Addr; +uint32 Rogue_Squadron_Vtx_Color_Cmd; +uint32 Rogue_Squadron_Vtx_Color_Addr; +uint32 GSBlkAddrSaves[100][2]; + +void ProcessVertexData_Rogue_Squadron(uint32 dwXYZAddr, uint32 dwColorAddr, uint32 dwXYZCmd, uint32 dwColorCmd); + +void DLParser_RS_Color_Buffer(Gfx *gfx) +{ + uint32 dwPC = gDlistStack[gDlistStackPointer].pc-8; + uint32 dwAddr = RSPSegmentAddr((gfx->words.w1)); + + if( dwAddr > g_dwRamSize ) + { + TRACE0("DL, addr is wrong"); + dwAddr = (gfx->words.w1)&(g_dwRamSize-1); + } + + Rogue_Squadron_Vtx_Color_Cmd = (gfx->words.w0); + Rogue_Squadron_Vtx_Color_Addr = dwAddr; + + LOG_UCODE("Vtx_Color at PC=%08X: 0x%08x 0x%08x\n", dwPC-8, (gfx->words.w0), (gfx->words.w1)); +#ifdef DEBUGGER + if( pauseAtNext && (eventToPause == NEXT_VERTEX_CMD ) ) + { + DebuggerAppendMsg("Vtx_Color at PC=%08X: 0x%08x 0x%08x\n", dwPC-8, (gfx->words.w0), (gfx->words.w1)); + if( dwAddr < g_dwRamSize ) + { + DumpHex(dwAddr, min(64, g_dwRamSize-dwAddr)); + } + } +#endif + + ProcessVertexData_Rogue_Squadron(Rogue_Squadron_Vtx_XYZ_Addr, Rogue_Squadron_Vtx_Color_Addr, Rogue_Squadron_Vtx_XYZ_Cmd, Rogue_Squadron_Vtx_Color_Cmd); + +} + + +void DLParser_RS_Vtx_Buffer(Gfx *gfx) +{ + uint32 dwPC = gDlistStack[gDlistStackPointer].pc-8; + uint32 dwAddr = RSPSegmentAddr((gfx->words.w1)); + if( dwAddr > g_dwRamSize ) + { + TRACE0("DL, addr is wrong"); + dwAddr = (gfx->words.w1)&(g_dwRamSize-1); + } + + LOG_UCODE("Vtx_XYZ at PC=%08X: 0x%08x 0x%08x\n", dwPC-8, (gfx->words.w0), (gfx->words.w1)); + Rogue_Squadron_Vtx_XYZ_Cmd = (gfx->words.w0); + Rogue_Squadron_Vtx_XYZ_Addr = dwAddr; + +#ifdef DEBUGGER + if( pauseAtNext && (eventToPause == NEXT_VERTEX_CMD ) ) + { + DebuggerAppendMsg("Vtx_XYZ at PC=%08X: 0x%08x 0x%08x\n", dwPC-8, (gfx->words.w0), (gfx->words.w1)); + if( dwAddr < g_dwRamSize ) + { + DumpHex(dwAddr, min(64, g_dwRamSize-dwAddr)); + } + } +#endif +} + + +void DLParser_RS_Block(Gfx *gfx) +{ + uint32 dwPC = gDlistStack[gDlistStackPointer].pc-8; + LOG_UCODE("ucode 0x80 at PC=%08X: 0x%08x 0x%08x\n", dwPC, (gfx->words.w0), (gfx->words.w1)); +} + +void DLParser_RS_MoveMem(Gfx *gfx) +{ + //uint32 dwPC = gDlistStack[gDlistStackPointer].pc; + //uint32 cmd1 = ((dwPC)&0x00FFFFFF)|0x80000000; + RSP_GBI1_MoveMem(gfx); + /* + LOG_UCODE("RS_MoveMem", ((gfx->words.w0)>>24)); + LOG_UCODE("\tPC=%08X: 0x%08x 0x%08x", dwPC, (gfx->words.w0), (gfx->words.w1)); + dwPC+=8; + uint32 dwCmd2 = *(uint32 *)(g_pRDRAMu8 + dwPC); + uint32 dwCmd3 = *(uint32 *)(g_pRDRAMu8 + dwPC+4); + LOG_UCODE("\tPC=%08X: 0x%08x 0x%08x", dwPC, dwCmd2, dwCmd3); + dwPC+=8; + uint32 dwCmd4 = *(uint32 *)(g_pRDRAMu8 + dwPC); + uint32 dwCmd5 = *(uint32 *)(g_pRDRAMu8 + dwPC+4); + LOG_UCODE("\tPC=%08X: 0x%08x 0x%08x\n", dwPC, dwCmd4, dwCmd5); + */ + gDlistStack[gDlistStackPointer].pc += 16; + + //DEBUGGER_PAUSE_AND_DUMP(NEXT_SET_MODE_CMD, { + // DebuggerAppendMsg("Pause after RS_MoveMem at: %08X\n", dwPC-8); + //}); + +} + +void DLParser_RS_0xbe(Gfx *gfx) +{ + uint32 dwPC = gDlistStack[gDlistStackPointer].pc-8; + LOG_UCODE("ucode %02X, skip 1", ((gfx->words.w0)>>24)); + LOG_UCODE("\tPC=%08X: 0x%08x 0x%08x", dwPC, (gfx->words.w0), (gfx->words.w1)); + dwPC+=8; + uint32 dwCmd2 = *(uint32 *)(g_pRDRAMu8 + dwPC); + uint32 dwCmd3 = *(uint32 *)(g_pRDRAMu8 + dwPC+4); + LOG_UCODE("\tPC=%08X: 0x%08x 0x%08x\n", dwPC, dwCmd2, dwCmd3); + gDlistStack[gDlistStackPointer].pc += 8; + + DEBUGGER_PAUSE_AND_DUMP(NEXT_SET_MODE_CMD, { + DebuggerAppendMsg("Pause after RS_0xbe at: %08X\n", dwPC-8); + DebuggerAppendMsg("\t0x%08x 0x%08x", (gfx->words.w0), (gfx->words.w1)); + DebuggerAppendMsg("\t0x%08x 0x%08x", dwCmd2, dwCmd3); + }); +} + + +void DLParser_Ucode8_EndDL(Gfx *gfx) +{ +#ifdef DEBUGGER + uint32 dwPC = gDlistStack[gDlistStackPointer].pc-8; +#endif + + RDP_GFX_PopDL(); + DEBUGGER_PAUSE_AND_DUMP(NEXT_DLIST, DebuggerAppendMsg("PC=%08X: EndDL, return to %08X\n\n", dwPC, gDlistStack[gDlistStackPointer].pc)); +} + +void DLParser_Ucode8_DL(Gfx *gfx) // DL Function Call +{ +#ifdef DEBUGGER + uint32 dwPC = gDlistStack[gDlistStackPointer].pc-8; +#endif + + uint32 dwAddr = RSPSegmentAddr((gfx->words.w1)); + uint32 dwCmd2 = *(uint32 *)(g_pRDRAMu8 + dwAddr); + uint32 dwCmd3 = *(uint32 *)(g_pRDRAMu8 + dwAddr+4); + + if( dwAddr > g_dwRamSize ) + { + TRACE0("DL, addr is wrong"); + dwAddr = (gfx->words.w1)&(g_dwRamSize-1); + } + + // Detect looping + /*if(gDlistStackPointer>0 ) + { + for( int i=0; i>24) == 0x80 ) + { + GSBlkAddrSaves[gDlistStackPointer][0] = dwCmd2; + GSBlkAddrSaves[gDlistStackPointer][1] = dwCmd3; + } + + DEBUGGER_PAUSE_AND_DUMP(NEXT_DLIST, + DebuggerAppendMsg("\nPC=%08X: Call DL at Address %08X - %08X, %08X\n\n", + dwPC, dwAddr, dwCmd2, dwCmd3)); +} + +void DLParser_Ucode8_JUMP(Gfx *gfx) // DL Function Call +{ + if( ((gfx->words.w0)&0x00FFFFFF) == 0 ) + { +#ifdef DEBUGGER + uint32 dwPC = gDlistStack[gDlistStackPointer].pc-8; +#endif + + uint32 dwAddr = RSPSegmentAddr((gfx->words.w1)); + + if( dwAddr > g_dwRamSize ) + { + TRACE0("DL, addr is wrong"); + dwAddr = (gfx->words.w1)&(g_dwRamSize-1); + } + +#ifdef DEBUGGER + uint32 dwCmd2 = *(uint32 *)(g_pRDRAMu8 + dwAddr); + uint32 dwCmd3 = *(uint32 *)(g_pRDRAMu8 + dwAddr+4); +#endif + + gDlistStack[gDlistStackPointer].pc = dwAddr+8; // Jump to new address + DEBUGGER_PAUSE_AND_DUMP(NEXT_DLIST, + DebuggerAppendMsg("\nPC=%08X: Jump to Address %08X - %08X, %08X\n\n", dwPC, dwAddr, dwCmd2, dwCmd3)); + } + else + { + uint32 dwPC = gDlistStack[gDlistStackPointer].pc-8; + LOG_UCODE("ucode 0x07 at PC=%08X: 0x%08x 0x%08x\n", dwPC, (gfx->words.w0), (gfx->words.w1)); + } +} + +void DLParser_Ucode8_Unknown(Gfx *gfx) +{ + uint32 dwPC = gDlistStack[gDlistStackPointer].pc-8; + LOG_UCODE("ucode %02X at PC=%08X: 0x%08x 0x%08x\n", ((gfx->words.w0)>>24), dwPC, (gfx->words.w0), (gfx->words.w1)); +} + +void DLParser_Unknown_Skip1(Gfx *gfx) +{ + uint32 dwPC = gDlistStack[gDlistStackPointer].pc-8; + LOG_UCODE("ucode %02X, skip 1", ((gfx->words.w0)>>24)); + gfx++; + LOG_UCODE("\tPC=%08X: 0x%08x 0x%08x", dwPC, (gfx->words.w0), (gfx->words.w1)); + dwPC+=8; + gfx++; + LOG_UCODE("\tPC=%08X: 0x%08x 0x%08x\n", dwPC, (gfx->words.w0), (gfx->words.w1)); + gDlistStack[gDlistStackPointer].pc += 8; +} + +void DLParser_Unknown_Skip2(Gfx *gfx) +{ + uint32 dwPC = gDlistStack[gDlistStackPointer].pc-8; + LOG_UCODE("ucode %02X, skip 2", ((gfx->words.w0)>>24)); + gfx++; + LOG_UCODE("\tPC=%08X: 0x%08x 0x%08x", dwPC, (gfx->words.w0), (gfx->words.w1)); + dwPC+=8; + gfx++; + LOG_UCODE("\tPC=%08X: 0x%08x 0x%08x", dwPC, (gfx->words.w0), (gfx->words.w1)); + dwPC+=8; + gfx++; + LOG_UCODE("\tPC=%08X: 0x%08x 0x%08x\n", dwPC, (gfx->words.w0), (gfx->words.w1)); + gDlistStack[gDlistStackPointer].pc += 16; +} + +void DLParser_Unknown_Skip3(Gfx *gfx) +{ + uint32 dwPC = gDlistStack[gDlistStackPointer].pc-8; + LOG_UCODE("ucode %02X, skip 3", ((gfx->words.w0)>>24)); + gfx++; + LOG_UCODE("\tPC=%08X: 0x%08x 0x%08x", dwPC, (gfx->words.w0), (gfx->words.w1)); + dwPC+=8; + gfx++; + LOG_UCODE("\tPC=%08X: 0x%08x 0x%08x", dwPC, (gfx->words.w0), (gfx->words.w1)); + dwPC+=8; + gfx++; + LOG_UCODE("\tPC=%08X: 0x%08x 0x%08x", dwPC, (gfx->words.w0), (gfx->words.w1)); + dwPC+=8; + gfx++; + LOG_UCODE("\tPC=%08X: 0x%08x 0x%08x\n", dwPC, (gfx->words.w0), (gfx->words.w1)); + gDlistStack[gDlistStackPointer].pc += 24; +} + +void DLParser_Unknown_Skip4(Gfx *gfx) +{ + uint32 dwPC = gDlistStack[gDlistStackPointer].pc-8; + LOG_UCODE("ucode %02X, skip 4", ((gfx->words.w0)>>24)); + gfx++; + LOG_UCODE("\tPC=%08X: 0x%08x 0x%08x", dwPC, (gfx->words.w0), (gfx->words.w1)); + dwPC+=8; + gfx++; + LOG_UCODE("\tPC=%08X: 0x%08x 0x%08x", dwPC, (gfx->words.w0), (gfx->words.w1)); + dwPC+=8; + gfx++; + LOG_UCODE("\tPC=%08X: 0x%08x 0x%08x", dwPC, (gfx->words.w0), (gfx->words.w1)); + dwPC+=8; + gfx++; + LOG_UCODE("\tPC=%08X: 0x%08x 0x%08x", dwPC, (gfx->words.w0), (gfx->words.w1)); + dwPC+=8; + gfx++; + LOG_UCODE("\tPC=%08X: 0x%08x 0x%08x\n", dwPC, (gfx->words.w0), (gfx->words.w1)); + gDlistStack[gDlistStackPointer].pc += 32; +} + +void DLParser_Ucode8_0x05(Gfx *gfx) +{ + // Be careful, 0x05 is variable length ucode + /* + 0028E4E0: 05020088, 04D0000F - Reserved1 + 0028E4E8: 6BDC0306, 00000000 - G_NOTHING + 0028E4F0: 05010130, 01B0000F - Reserved1 + 0028E4F8: 918A01CA, 1EC5FF3B - G_NOTHING + 0028E500: 05088C68, F5021809 - Reserved1 + 0028E508: 04000405, 00000000 - RSP_VTX + 0028E510: 102ECE60, 202F2AA0 - G_NOTHING + 0028E518: 05088C90, F5021609 - Reserved1 + 0028E520: 04050405, F0F0F0F0 - RSP_VTX + 0028E528: 102ED0C0, 202F2D00 - G_NOTHING + 0028E530: B5000000, 00000000 - RSP_LINE3D + 0028E538: 8028E640, 8028E430 - G_NOTHING + 0028E540: 00000000, 00000000 - RSP_SPNOOP + */ + + if((gfx->words.w1) == 0) + return; + else + DLParser_Unknown_Skip4(gfx); +} + +void DLParser_Ucode8_0xb4(Gfx *gfx) +{ +#ifdef DEBUGGER + uint32 dwPC = gDlistStack[gDlistStackPointer].pc; +#endif + + if(((gfx->words.w0)&0xFF) == 0x06) + DLParser_Unknown_Skip3(gfx); + else if(((gfx->words.w0)&0xFF) == 0x04) + DLParser_Unknown_Skip1(gfx); + else if(((gfx->words.w0)&0xFFF) == 0x600) + DLParser_Unknown_Skip3(gfx); + else + { +#ifdef DEBUGGER + if(pauseAtNext) + { + DebuggerAppendMsg("ucode 0xb4 at PC=%08X: 0x%08x 0x%08x\n", dwPC-8, + (gfx->words.w0), (gfx->words.w1)); + } +#endif + DLParser_Unknown_Skip3(gfx); + } +} + +void DLParser_Ucode8_0xb5(Gfx *gfx) +{ + uint32 dwPC = gDlistStack[gDlistStackPointer].pc-8; + LOG_UCODE("ucode 0xB5 at PC=%08X: 0x%08x 0x%08x\n", dwPC-8, (gfx->words.w0), (gfx->words.w1)); + + uint32 dwCmd2 = *(uint32 *)(g_pRDRAMu8 + dwPC+8); + uint32 dwCmd3 = *(uint32 *)(g_pRDRAMu8 + dwPC+12); + LOG_UCODE(" : 0x%08x 0x%08x\n", dwCmd2, dwCmd3); + + //if( dwCmd2 == 0 && dwCmd3 == 0 ) + { + DLParser_Ucode8_EndDL(gfx); // Check me + return; + } + + gDlistStack[gDlistStackPointer].pc += 8; + return; + + + if( GSBlkAddrSaves[gDlistStackPointer][0] == 0 || GSBlkAddrSaves[gDlistStackPointer][1] == 0 ) + { +#ifdef DEBUGGER + if( pauseAtNext && eventToPause == NEXT_DLIST) + { + DebuggerAppendMsg("PC=%08X: 0xB5 - %08X : %08X, %08X, EndDL, no next blk\n", dwPC, (gfx->words.w1), dwCmd2, dwCmd3); + } +#endif + DLParser_Ucode8_EndDL(gfx); // Check me + return; + } + + if( ((dwCmd2>>24)!=0x80 && (dwCmd2>>24)!=0x00 ) || ((dwCmd3>>24)!=0x80 && (dwCmd3>>24)!=0x00 ) ) + { +#ifdef DEBUGGER + if( pauseAtNext && eventToPause == NEXT_DLIST) + { + DebuggerAppendMsg("PC=%08X: 0xB5 - %08X : %08X, %08X, EndDL, Unknown\n", dwPC, (gfx->words.w1), dwCmd2, dwCmd3); + } +#endif + DLParser_Ucode8_EndDL(gfx); // Check me + return; + } + + if( (dwCmd2>>24)!= (dwCmd3>>24) ) + { +#ifdef DEBUGGER + if( pauseAtNext && eventToPause == NEXT_DLIST) + { + DebuggerAppendMsg("PC=%08X: 0xB5 - %08X : %08X, %08X, EndDL, Unknown\n", dwPC, (gfx->words.w1), dwCmd2, dwCmd3); + } +#endif + DLParser_Ucode8_EndDL(gfx); // Check me + return; + } + + + if( (dwCmd2>>24)==0x80 && (dwCmd3>>24)==0x80 ) + { + if( dwCmd2 < dwCmd3 ) + { + // All right, the next block is not ucode, but data +#ifdef DEBUGGER + if( pauseAtNext && eventToPause == NEXT_DLIST) + { + DebuggerAppendMsg("PC=%08X: 0xB5 - %08X : %08X, %08X, EndDL, next blk is data\n", dwPC, (gfx->words.w1), dwCmd2, dwCmd3); + } +#endif + DLParser_Ucode8_EndDL(gfx); // Check me + return; + } + + uint32 dwCmd4 = *(uint32 *)(g_pRDRAMu8 + (dwCmd2&0x00FFFFFF)); + uint32 dwCmd5 = *(uint32 *)(g_pRDRAMu8 + (dwCmd2&0x00FFFFFF)+4); + uint32 dwCmd6 = *(uint32 *)(g_pRDRAMu8 + (dwCmd3&0x00FFFFFF)); + uint32 dwCmd7 = *(uint32 *)(g_pRDRAMu8 + (dwCmd3&0x00FFFFFF)+4); + if( (dwCmd4>>24) != 0x80 || (dwCmd5>>24) != 0x80 || (dwCmd6>>24) != 0x80 || (dwCmd7>>24) != 0x80 || dwCmd4 < dwCmd5 || dwCmd6 < dwCmd7 ) + { + // All right, the next block is not ucode, but data +#ifdef DEBUGGER + if( pauseAtNext && eventToPause == NEXT_DLIST) + { + DebuggerAppendMsg("PC=%08X: 0xB5 - %08X : %08X, %08X, EndDL, next blk is data\n", dwPC, (gfx->words.w1), dwCmd2, dwCmd3); + DebuggerAppendMsg("%08X, %08X %08X,%08X\n", dwCmd4, dwCmd5, dwCmd6, dwCmd7); + } +#endif + DLParser_Ucode8_EndDL(gfx); // Check me + return; + } + + gDlistStack[gDlistStackPointer].pc += 8; + DEBUGGER_PAUSE_AND_DUMP(NEXT_DLIST, + DebuggerAppendMsg("PC=%08X: 0xB5 - %08X : %08X, %08X, continue\n", dwPC, (gfx->words.w1), dwCmd2, dwCmd3); + ); + return; + } + else if( (dwCmd2>>24)==0x00 && (dwCmd3>>24)==0x00 ) + { +#ifdef DEBUGGER + if( pauseAtNext && eventToPause == NEXT_DLIST) + { + DebuggerAppendMsg("PC=%08X: 0xB5 - %08X : %08X, %08X, EndDL, next blk is data\n", dwPC, (gfx->words.w1), dwCmd2, dwCmd3); + } +#endif + DLParser_Ucode8_EndDL(gfx); // Check me + return; + } + else if( (dwCmd2>>24)==0x00 && (dwCmd3>>24)==0x00 ) + { + dwCmd2 = *(uint32 *)(g_pRDRAMu8 + dwPC+16); + dwCmd3 = *(uint32 *)(g_pRDRAMu8 + dwPC+20); + if( (dwCmd2>>24)==0x80 && (dwCmd3>>24)==0x80 && dwCmd2 < dwCmd3 ) + { + // All right, the next block is not ucode, but data +#ifdef DEBUGGER + if( pauseAtNext && eventToPause == NEXT_DLIST) + { + DebuggerAppendMsg("PC=%08X: 0xB5 - %08X : %08X, %08X, EndDL, next blk is data\n", dwPC, (gfx->words.w1), dwCmd2, dwCmd3); + } +#endif + DLParser_Ucode8_EndDL(gfx); // Check me + return; + } + else + { + gDlistStack[gDlistStackPointer].pc += 8; + DEBUGGER_PAUSE_AND_DUMP(NEXT_DLIST, + DebuggerAppendMsg("PC=%08X: 0xB5 - %08X : %08X, %08X, continue\n", dwPC, (gfx->words.w1), dwCmd2, dwCmd3) + ); + return; + } + } + +#ifdef DEBUGGER +uint32 dwAddr1 = RSPSegmentAddr(dwCmd2); +uint32 dwAddr2 = RSPSegmentAddr(dwCmd3); + + if( (gfx->words.w1) != 0 ) + { + DebuggerAppendMsg("!!!! PC=%08X: 0xB5 - %08X : %08X, %08X\n", dwPC, (gfx->words.w1), dwCmd2, dwCmd3); + } +#endif + + DEBUGGER_PAUSE_AND_DUMP(NEXT_DLIST, + DebuggerAppendMsg("PC=%08X: 0xB5 - %08X : %08X, %08X, continue\n", dwPC, (gfx->words.w1), dwAddr1, dwAddr2) + ); + + return; +} + +void DLParser_Ucode8_0xbc(Gfx *gfx) +{ + if( ((gfx->words.w0)&0xFFF) == 0x58C ) + { + DLParser_Ucode8_DL(gfx); + } + else + { + uint32 dwPC = gDlistStack[gDlistStackPointer].pc-8; + LOG_UCODE("ucode 0xBC at PC=%08X: 0x%08x 0x%08x\n", dwPC, (gfx->words.w0), (gfx->words.w1)); + } +} + +void DLParser_Ucode8_0xbd(Gfx *gfx) +{ + /* + 00359A68: BD000000, DB5B0077 - RSP_POPMTX + 00359A70: C8C0A000, 00240024 - RDP_TriFill + 00359A78: 01000100, 00000000 - RSP_MTX + 00359A80: BD000501, DB5B0077 - RSP_POPMTX + 00359A88: C8C0A000, 00240024 - RDP_TriFill + 00359A90: 01000100, 00000000 - RSP_MTX + 00359A98: BD000A02, DB5B0077 - RSP_POPMTX + 00359AA0: C8C0A000, 00240024 - RDP_TriFill + 00359AA8: 01000100, 00000000 - RSP_MTX + 00359AB0: BD000F04, EB6F0087 - RSP_POPMTX + 00359AB8: C8C0A000, 00280028 - RDP_TriFill + 00359AC0: 01000100, 00000000 - RSP_MTX + 00359AC8: BD001403, DB5B0077 - RSP_POPMTX + 00359AD0: C8C0A000, 00240024 - RDP_TriFill + 00359AD8: 01000100, 00000000 - RSP_MTX + 00359AE0: B5000000, 00000000 - RSP_LINE3D + 00359AE8: 1A000000, 16000200 - G_NOTHING + */ + + if( (gfx->words.w1) != 0 ) + { + DLParser_Unknown_Skip2(gfx); + return; + } + + uint32 dwPC = gDlistStack[gDlistStackPointer].pc; + LOG_UCODE("ucode 0xbd at PC=%08X: 0x%08x 0x%08x\n", dwPC-8, (gfx->words.w0), (gfx->words.w1)); +} + +void DLParser_Ucode8_0xbf(Gfx *gfx) +{ + if( ((gfx->words.w0)&0xFF) == 0x02 ) + DLParser_Unknown_Skip3(gfx); + else + DLParser_Unknown_Skip1(gfx); +} + +void PD_LoadMatrix_0xb4(uint32 addr) +{ + const float fRecip = 1.0f / 65536.0f; + + uint32 data[16]; + data[0] = *(uint32*)(g_pRDRAMu8+addr+4+ 0); + data[1] = *(uint32*)(g_pRDRAMu8+addr+4+ 8); + data[2] = *(uint32*)(g_pRDRAMu8+addr+4+16); + data[3] = *(uint32*)(g_pRDRAMu8+addr+4+24); + + data[8] = *(uint32*)(g_pRDRAMu8+addr+4+32); + data[9] = *(uint32*)(g_pRDRAMu8+addr+4+40); + data[10] = *(uint32*)(g_pRDRAMu8+addr+4+48); + data[11] = *(uint32*)(g_pRDRAMu8+addr+4+56); + + data[4] = *(uint32*)(g_pRDRAMu8+addr+4+ 0+64); + data[5] = *(uint32*)(g_pRDRAMu8+addr+4+ 8+64); + data[6] = *(uint32*)(g_pRDRAMu8+addr+4+16+64); + data[7] = *(uint32*)(g_pRDRAMu8+addr+4+24+64); + + data[12] = *(uint32*)(g_pRDRAMu8+addr+4+32+64); + data[13] = *(uint32*)(g_pRDRAMu8+addr+4+40+64); + data[14] = *(uint32*)(g_pRDRAMu8+addr+4+48+64); + data[15] = *(uint32*)(g_pRDRAMu8+addr+4+56+64); + + + for (int i = 0; i < 4; i++) + { + for (int j = 0; j < 4; j++) + { + int hi = *(short *)((unsigned char*)data + (((i<<3)+(j<<1) )^0x2)); + int lo = *(uint16*)((unsigned char*)data + (((i<<3)+(j<<1) + 32)^0x2)); + matToLoad.m[i][j] = (float)((hi<<16) | lo) * fRecip; + } + } + + +#ifdef DEBUGGER + LOG_UCODE( + " %#+12.5f %#+12.5f %#+12.5f %#+12.5f\r\n" + " %#+12.5f %#+12.5f %#+12.5f %#+12.5f\r\n" + " %#+12.5f %#+12.5f %#+12.5f %#+12.5f\r\n" + " %#+12.5f %#+12.5f %#+12.5f %#+12.5f\r\n", + matToLoad.m[0][0], matToLoad.m[0][1], matToLoad.m[0][2], matToLoad.m[0][3], + matToLoad.m[1][0], matToLoad.m[1][1], matToLoad.m[1][2], matToLoad.m[1][3], + matToLoad.m[2][0], matToLoad.m[2][1], matToLoad.m[2][2], matToLoad.m[2][3], + matToLoad.m[3][0], matToLoad.m[3][1], matToLoad.m[3][2], matToLoad.m[3][3]); +#endif // DEBUGGER +} + +void DLParser_RDPHalf_1_0xb4_GoldenEye(Gfx *gfx) +{ + SP_Timing(RSP_GBI1_RDPHalf_1); + if( ((gfx->words.w1)>>24) == 0xce ) + { + PrepareTextures(); + CRender::g_pRender->SetCombinerAndBlender(); + + uint32 dwPC = gDlistStack[gDlistStackPointer].pc; // This points to the next instruction + + //PD_LoadMatrix_0xb4(dwPC + 8*16 - 8); + + uint32 dw1 = *(uint32 *)(g_pRDRAMu8 + dwPC+8*0+4); + //uint32 dw2 = *(uint32 *)(g_pRDRAMu8 + dwPC+8*1+4); + //uint32 dw3 = *(uint32 *)(g_pRDRAMu8 + dwPC+8*2+4); + //uint32 dw4 = *(uint32 *)(g_pRDRAMu8 + dwPC+8*3+4); + //uint32 dw5 = *(uint32 *)(g_pRDRAMu8 + dwPC+8*4+4); + //uint32 dw6 = *(uint32 *)(g_pRDRAMu8 + dwPC+8*5+4); + //uint32 dw7 = *(uint32 *)(g_pRDRAMu8 + dwPC+8*6+4); + uint32 dw8 = *(uint32 *)(g_pRDRAMu8 + dwPC+8*7+4); + uint32 dw9 = *(uint32 *)(g_pRDRAMu8 + dwPC+8*8+4); + + uint32 r = (dw8>>16)&0xFF; + uint32 g = (dw8 )&0xFF; + uint32 b = (dw9>>16)&0xFF; + uint32 a = (dw9 )&0xFF; + uint32 color = COLOR_RGBA(r, g, b, a); + + //int x0 = 0; + //int x1 = gRDP.scissor.right; + int x0 = gRSP.nVPLeftN; + int x1 = gRSP.nVPRightN; + int y0 = int(dw1&0xFFFF)/4; + int y1 = int(dw1>>16)/4; + + float xscale = g_textures[0].m_pCTexture->m_dwWidth / (float)(x1-x0); + float yscale = g_textures[0].m_pCTexture->m_dwHeight / (float)(y1-y0); + //float fs0 = (short)(dw3&0xFFFF)/32768.0f*g_textures[0].m_pCTexture->m_dwWidth; + //float ft0 = (short)(dw3>>16)/32768.0f*256; + CRender::g_pRender->TexRect(x0,y0,x1,y1,0,0,xscale,yscale,true,color); + + gDlistStack[gDlistStackPointer].pc += 312; + +#ifdef DEBUGGER + if( logUcodes) + { + dwPC -= 8; + LOG_UCODE("GoldenEye Sky at PC=%08X: 0x%08x 0x%08x", dwPC, (gfx->words.w0), (gfx->words.w1)); + uint32 *ptr = (uint32 *)(g_pRDRAMu8 + dwPC); + for( int i=0; i<21; i++, dwPC+=16,ptr+=4 ) + { + LOG_UCODE("%08X: %08X %08X %08X %08X", dwPC, ptr[0], ptr[1], ptr[2], ptr[3]); + } + } +#endif + + DEBUGGER_PAUSE_AND_DUMP_COUNT_N(NEXT_FLUSH_TRI, { + TRACE0("Pause after Golden Sky Drawing\n"); + }); + } +} + +void DLParser_RSP_DL_WorldDriver(Gfx *gfx) +{ + uint32 dwAddr = RSPSegmentAddr((gfx->words.w1)); + if( dwAddr > g_dwRamSize ) + { + RSP_RDP_NOIMPL("Error: DL addr = %08X out of range, PC=%08X", dwAddr, gDlistStack[gDlistStackPointer].pc ); + dwAddr &= (g_dwRamSize-1); + DebuggerPauseCountN( NEXT_DLIST ); + } + + LOG_UCODE(" WorldDriver DisplayList 0x%08x", dwAddr); + gDlistStackPointer++; + gDlistStack[gDlistStackPointer].pc = dwAddr; + gDlistStack[gDlistStackPointer].countdown = MAX_DL_COUNT; + + LOG_UCODE("Level=%d", gDlistStackPointer+1); + LOG_UCODE("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"); +} + +void DLParser_RSP_Pop_DL_WorldDriver(Gfx *gfx) +{ + RDP_GFX_PopDL(); +} + +void DLParser_RSP_Last_Legion_0x80(Gfx *gfx) +{ + gDlistStack[gDlistStackPointer].pc += 16; + LOG_UCODE("DLParser_RSP_Last_Legion_0x80"); +} + +void DLParser_RSP_Last_Legion_0x00(Gfx *gfx) +{ + LOG_UCODE("DLParser_RSP_Last_Legion_0x00"); + gDlistStack[gDlistStackPointer].pc += 16; + + if( (gfx->words.w0) == 0 && (gfx->words.w1) ) + { + uint32 newaddr = RSPSegmentAddr((gfx->words.w1)); + if( newaddr >= g_dwRamSize ) + { + RDP_GFX_PopDL(); + return; + } + + //uint32 dw1 = *(uint32 *)(g_pRDRAMu8 + newaddr+8*0+4); + uint32 pc1 = *(uint32 *)(g_pRDRAMu8 + newaddr+8*1+4); + uint32 pc2 = *(uint32 *)(g_pRDRAMu8 + newaddr+8*4+4); + pc1 = RSPSegmentAddr(pc1); + pc2 = RSPSegmentAddr(pc2); + + if( pc1 && pc1 != 0xffffff && pc1 < g_dwRamSize) + { + // Need to call both DL + gDlistStackPointer++; + gDlistStack[gDlistStackPointer].pc = pc1; + gDlistStack[gDlistStackPointer].countdown = MAX_DL_COUNT; + } + + if( pc2 && pc2 != 0xffffff && pc2 < g_dwRamSize ) + { + gDlistStackPointer++; + gDlistStack[gDlistStackPointer].pc = pc2; + gDlistStack[gDlistStackPointer].countdown = MAX_DL_COUNT; + } + } + else if( (gfx->words.w1) == 0 ) + { + RDP_GFX_PopDL(); + } + else + { + // (gfx->words.w0) != 0 + RSP_RDP_Nothing(gfx); + RDP_GFX_PopDL(); + } +} + +void DLParser_TexRect_Last_Legion(Gfx *gfx) +{ + if( !status.bCIBufferIsRendered ) + g_pFrameBufferManager->ActiveTextureBuffer(); + + status.primitiveType = PRIM_TEXTRECT; + + // This command used 128bits, and not 64 bits. This means that we have to look one + // Command ahead in the buffer, and update the PC. + uint32 dwPC = gDlistStack[gDlistStackPointer].pc; // This points to the next instruction + uint32 dwCmd2 = *(uint32 *)(g_pRDRAMu8 + dwPC); + uint32 dwCmd3 = *(uint32 *)(g_pRDRAMu8 + dwPC+4); + + gDlistStack[gDlistStackPointer].pc += 8; + + + LOG_UCODE("0x%08x: %08x %08x", dwPC, *(uint32 *)(g_pRDRAMu8 + dwPC+0), *(uint32 *)(g_pRDRAMu8 + dwPC+4)); + + uint32 dwXH = (((gfx->words.w0)>>12)&0x0FFF)/4; + uint32 dwYH = (((gfx->words.w0) )&0x0FFF)/4; + uint32 tileno = ((gfx->words.w1)>>24)&0x07; + uint32 dwXL = (((gfx->words.w1)>>12)&0x0FFF)/4; + uint32 dwYL = (((gfx->words.w1) )&0x0FFF)/4; + + + if( (int)dwXL >= gRDP.scissor.right || (int)dwYL >= gRDP.scissor.bottom || (int)dwXH < gRDP.scissor.left || (int)dwYH < gRDP.scissor.top ) + { + // Clipping + return; + } + + uint16 uS = (uint16)( dwCmd2>>16)&0xFFFF; + uint16 uT = (uint16)( dwCmd2 )&0xFFFF; + short s16S = *(short*)(&uS); + short s16T = *(short*)(&uT); + + uint16 uDSDX = (uint16)(( dwCmd3>>16)&0xFFFF); + uint16 uDTDY = (uint16)(( dwCmd3 )&0xFFFF); + short s16DSDX = *(short*)(&uDSDX); + short s16DTDY = *(short*)(&uDTDY); + + uint32 curTile = gRSP.curTile; + ForceMainTextureIndex(tileno); + + float fS0 = s16S / 32.0f; + float fT0 = s16T / 32.0f; + + float fDSDX = s16DSDX / 1024.0f; + float fDTDY = s16DTDY / 1024.0f; + + uint32 cycletype = gRDP.otherMode.cycle_type; + + if (cycletype == CYCLE_TYPE_COPY) + { + fDSDX /= 4.0f; // In copy mode 4 pixels are copied at once. + dwXH++; + dwYH++; + } + else if (cycletype == CYCLE_TYPE_FILL) + { + dwXH++; + dwYH++; + } + + if( fDSDX == 0 ) fDSDX = 1; + if( fDTDY == 0 ) fDTDY = 1; + + float fS1 = fS0 + (fDSDX * (dwXH - dwXL)); + float fT1 = fT0 + (fDTDY * (dwYH - dwYL)); + + LOG_UCODE(" Tile:%d Screen(%d,%d) -> (%d,%d)", tileno, dwXL, dwYL, dwXH, dwYH); + LOG_UCODE(" Tex:(%#5f,%#5f) -> (%#5f,%#5f) (DSDX:%#5f DTDY:%#5f)", + fS0, fT0, fS1, fT1, fDSDX, fDTDY); + LOG_UCODE(""); + + float t0u0 = (fS0-gRDP.tiles[tileno].hilite_sl) * gRDP.tiles[tileno].fShiftScaleS; + float t0v0 = (fT0-gRDP.tiles[tileno].hilite_tl) * gRDP.tiles[tileno].fShiftScaleT; + float t0u1 = t0u0 + (fDSDX * (dwXH - dwXL))*gRDP.tiles[tileno].fShiftScaleS; + float t0v1 = t0v0 + (fDTDY * (dwYH - dwYL))*gRDP.tiles[tileno].fShiftScaleT; + + if( dwXL==0 && dwYL==0 && dwXH==windowSetting.fViWidth-1 && dwYH==windowSetting.fViHeight-1 && + t0u0 == 0 && t0v0==0 && t0u1==0 && t0v1==0 ) + { + //Using TextRect to clear the screen + } + else + { + if( status.bHandleN64RenderTexture && //status.bDirectWriteIntoRDRAM && + g_pRenderTextureInfo->CI_Info.dwFormat == gRDP.tiles[tileno].dwFormat && + g_pRenderTextureInfo->CI_Info.dwSize == gRDP.tiles[tileno].dwSize && + gRDP.tiles[tileno].dwFormat == TXT_FMT_CI && gRDP.tiles[tileno].dwSize == TXT_SIZE_8b ) + { + if( options.enableHackForGames == HACK_FOR_YOSHI ) + { + // Hack for Yoshi background image + PrepareTextures(); + TexRectToFrameBuffer_8b(dwXL, dwYL, dwXH, dwYH, t0u0, t0v0, t0u1, t0v1, tileno); + DEBUGGER_PAUSE_AT_COND_AND_DUMP_COUNT_N((eventToPause == NEXT_FLUSH_TRI || eventToPause == NEXT_TEXTRECT), { + DebuggerAppendMsg("TexRect: tile=%d, X0=%d, Y0=%d, X1=%d, Y1=%d,\nfS0=%f, fT0=%f, ScaleS=%f, ScaleT=%f\n", + gRSP.curTile, dwXL, dwYL, dwXH, dwYH, fS0, fT0, fDSDX, fDTDY); + DebuggerAppendMsg("Pause after TexRect for Yoshi\n"); + }); + } + else + { + if( frameBufferOptions.bUpdateCIInfo ) + { + PrepareTextures(); + TexRectToFrameBuffer_8b(dwXL, dwYL, dwXH, dwYH, t0u0, t0v0, t0u1, t0v1, tileno); + } + + if( !status.bDirectWriteIntoRDRAM ) + { + CRender::g_pRender->TexRect(dwXL, dwYL, dwXH, dwYH, fS0, fT0, fDSDX, fDTDY); + + status.dwNumTrisRendered += 2; + } + } + } + else + { + CRender::g_pRender->TexRect(dwXL, dwYL, dwXH, dwYH, fS0, fT0, fDSDX, fDTDY); + status.bFrameBufferDrawnByTriangles = true; + + status.dwNumTrisRendered += 2; + } + } + + if( status.bHandleN64RenderTexture ) + g_pRenderTextureInfo->maxUsedHeight = max(g_pRenderTextureInfo->maxUsedHeight,(int)dwYH); + + ForceMainTextureIndex(curTile); +} +