From 30959856c700b753fb24af2795ef4d9be90bd611 Mon Sep 17 00:00:00 2001 From: Sergey Lipskiy Date: Thu, 30 Oct 2014 10:23:50 +0600 Subject: [PATCH] Implement Turbo3D microcode. --- CMakeLists.txt | 1 + GBI.cpp | 6 +- GBI.h | 3 +- GLideN64.vcxproj | 2 + GLideN64.vcxproj.filters | 6 ++ RSP.cpp | 65 +++++++++-------- Turbo3D.cpp | 151 +++++++++++++++++++++++++++++++++++++++ Turbo3D.h | 6 ++ gSP.cpp | 2 +- gSP.h | 1 + 10 files changed, 208 insertions(+), 35 deletions(-) create mode 100644 Turbo3D.cpp create mode 100644 Turbo3D.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 082414d3..97f09b77 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,7 @@ set(GLideN64_SOURCES RSP.cpp S2DEX2.cpp S2DEX.cpp + Turbo3D.cpp Textures.cpp VI.cpp common/CommonAPIImpl_common.cpp diff --git a/GBI.cpp b/GBI.cpp index 3c12a5f2..cc80c2b2 100644 --- a/GBI.cpp +++ b/GBI.cpp @@ -37,7 +37,8 @@ SpecialMicrocodeInfo specialMicrocodes[] = { F3DDKR, FALSE, 0x6e6fc893, "Diddy Kong Racing" }, { F3DJFG, FALSE, 0xbde9d1fb, "Jet Force Gemini" }, { F3DPD, FALSE, 0x1c4f7869, "Perfect Dark" }, - { F3DEX2CBFD,TRUE, 0x1b4ace88, "Conker's Bad Fur Day"} + { Turbo3D, FALSE, 0x2bdcfc8a, "Turbo3D" }, + {F3DEX2CBFD, TRUE, 0x1b4ace88, "Conker's Bad Fur Day"} }; u32 G_RDPHALF_1, G_RDPHALF_2, G_RDPHALF_CONT; @@ -157,7 +158,8 @@ void GBIInfo::_makeCurrent(MicrocodeInfo * _pCurrent) case F3DJFG: F3DJFG_Init(); break; case F3DWRUS: F3DWRUS_Init(); break; case F3DPD: F3DPD_Init(); break; - case F3DEX2CBFD:F3DEX2CBFD_Init();break; + case Turbo3D: F3D_Init(); break; + case F3DEX2CBFD:F3DEX2CBFD_Init(); break; } } } diff --git a/GBI.h b/GBI.h index 67ed965e..9e2dae7b 100644 --- a/GBI.h +++ b/GBI.h @@ -19,7 +19,8 @@ #define F3DJFG 10 #define F3DWRUS 11 #define F3DEX2CBFD 12 -#define NONE 13 +#define Turbo3D 13 +#define NONE 14 // Fixed point conversion factors #define FIXED2FLOATRECIP1 0.5f diff --git a/GLideN64.vcxproj b/GLideN64.vcxproj index 1936b04a..e57847c8 100644 --- a/GLideN64.vcxproj +++ b/GLideN64.vcxproj @@ -284,6 +284,7 @@ + @@ -360,6 +361,7 @@ + diff --git a/GLideN64.vcxproj.filters b/GLideN64.vcxproj.filters index 63417b5e..fc9ca503 100644 --- a/GLideN64.vcxproj.filters +++ b/GLideN64.vcxproj.filters @@ -180,6 +180,9 @@ Source Files\mupenplus + + Source Files\uCodes + @@ -308,6 +311,9 @@ Header Files\uCodes + + Header Files\uCodes + diff --git a/RSP.cpp b/RSP.cpp index 8bac0117..085b7982 100644 --- a/RSP.cpp +++ b/RSP.cpp @@ -4,6 +4,7 @@ #include "RDP.h" #include "N64.h" #include "F3D.h" +#include "Turbo3D.h" #include "VI.h" #include "Combiner.h" #include "FrameBuffer.h" @@ -181,51 +182,53 @@ void RSP_ProcessDList() gDPSetCycleType( G_CYC_1CYCLE ); gDPPipelineMode( G_PM_NPRIMITIVE ); - while (!RSP.halt) - { - if ((RSP.PC[RSP.PCi] + 8) > RDRAMSize) - { + if (GBI.getMicrocodeType() == Turbo3D) + RunTurbo3D(); + else { + while (!RSP.halt) { + if ((RSP.PC[RSP.PCi] + 8) > RDRAMSize) { #ifdef DEBUG - switch (Debug.level) - { - case DEBUG_LOW: + switch (Debug.level) + { + case DEBUG_LOW: DebugMsg( DEBUG_LOW | DEBUG_ERROR, "ATTEMPTING TO EXECUTE RSP COMMAND AT INVALID RDRAM LOCATION\n" ); break; - case DEBUG_MEDIUM: + case DEBUG_MEDIUM: DebugMsg( DEBUG_MEDIUM | DEBUG_ERROR, "Attempting to execute RSP command at invalid RDRAM location\n" ); break; - case DEBUG_HIGH: + case DEBUG_HIGH: DebugMsg( DEBUG_HIGH | DEBUG_ERROR, "// Attempting to execute RSP command at invalid RDRAM location\n" ); break; - } + } #endif - break; - } - -// printf( "!!!!!! RDRAM = 0x%8.8x\n", RDRAM );//RSP.PC[RSP.PCi] ); -/* { - static u8 *lastRDRAM = 0; - if (lastRDRAM == 0) - lastRDRAM = RDRAM; - if (RDRAM != lastRDRAM) - { - __asm__( "int $3" ); + break; } - }*/ - u32 w0 = *(u32*)&RDRAM[RSP.PC[RSP.PCi]]; - u32 w1 = *(u32*)&RDRAM[RSP.PC[RSP.PCi] + 4]; - RSP.cmd = _SHIFTR( w0, 24, 8 ); + + // printf( "!!!!!! RDRAM = 0x%8.8x\n", RDRAM );//RSP.PC[RSP.PCi] ); + /* { + static u8 *lastRDRAM = 0; + if (lastRDRAM == 0) + lastRDRAM = RDRAM; + if (RDRAM != lastRDRAM) + { + __asm__( "int $3" ); + } + }*/ + u32 w0 = *(u32*)&RDRAM[RSP.PC[RSP.PCi]]; + u32 w1 = *(u32*)&RDRAM[RSP.PC[RSP.PCi] + 4]; + RSP.cmd = _SHIFTR(w0, 24, 8); #ifdef DEBUG - DebugRSPState( RSP.PCi, RSP.PC[RSP.PCi], _SHIFTR( w0, 24, 8 ), w0, w1 ); - DebugMsg( DEBUG_LOW | DEBUG_HANDLED, "0x%08lX: CMD=0x%02lX W0=0x%08lX W1=0x%08lX\n", RSP.PC[RSP.PCi], _SHIFTR( w0, 24, 8 ), w0, w1 ); + DebugRSPState( RSP.PCi, RSP.PC[RSP.PCi], _SHIFTR( w0, 24, 8 ), w0, w1 ); + DebugMsg( DEBUG_LOW | DEBUG_HANDLED, "0x%08lX: CMD=0x%02lX W0=0x%08lX W1=0x%08lX\n", RSP.PC[RSP.PCi], _SHIFTR( w0, 24, 8 ), w0, w1 ); #endif - RSP.PC[RSP.PCi] += 8; - RSP.nextCmd = _SHIFTR( *(u32*)&RDRAM[RSP.PC[RSP.PCi]], 24, 8 ); + RSP.PC[RSP.PCi] += 8; + RSP.nextCmd = _SHIFTR(*(u32*)&RDRAM[RSP.PC[RSP.PCi]], 24, 8); - GBI.cmd[RSP.cmd]( w0, w1 ); - RSP_CheckDLCounter(); + GBI.cmd[RSP.cmd](w0, w1); + RSP_CheckDLCounter(); + } } if (config.frameBufferEmulation.copyToRDRAM) diff --git a/Turbo3D.cpp b/Turbo3D.cpp new file mode 100644 index 00000000..2bfece78 --- /dev/null +++ b/Turbo3D.cpp @@ -0,0 +1,151 @@ +#include "Turbo3D.h" +#include "N64.h" +#include "RSP.h" +#include "RDP.h" +#include "gSP.h" +#include "gDP.h" +#include "OpenGL.h" + +/******************Turbo3D microcode*************************/ + +struct T3DGlobState +{ + u16 pad0; + u16 perspNorm; + u32 flag; + u32 othermode0; + u32 othermode1; + u32 segBases[16]; + /* the viewport to use */ + s16 vsacle1; + s16 vsacle0; + s16 vsacle3; + s16 vsacle2; + s16 vtrans1; + s16 vtrans0; + s16 vtrans3; + s16 vtrans2; + u32 rdpCmds; +}; + +struct T3DState +{ + u32 renderState; /* render state */ + u32 textureState; /* texture state */ + u8 flag; + u8 triCount; /* how many tris? */ + u8 vtxV0; /* where to load verts? */ + u8 vtxCount; /* how many verts? */ + u32 rdpCmds; /* ptr (segment address) to RDP DL */ + u32 othermode0; + u32 othermode1; +}; + + +struct T3DTriN +{ + u8 flag, v2, v1, v0; /* flag is which one for flat shade */ +}; + + +static +void Turbo3D_ProcessRDP(u32 _cmds) +{ + u32 addr = RSP_SegmentToPhysical(_cmds) >> 2; + if (addr != 0) { + RSP.bLLE = true; + u32 w0 = ((u32*)RDRAM)[addr++]; + u32 w1 = ((u32*)RDRAM)[addr++]; + RSP.cmd = _SHIFTR( w0, 24, 8 ); + while (w0 + w1 != 0) { + GBI.cmd[RSP.cmd]( w0, w1 ); + w0 = ((u32*)RDRAM)[addr++]; + w1 = ((u32*)RDRAM)[addr++]; + RSP.cmd = _SHIFTR( w0, 24, 8 ); + if (RSP.cmd == 0xE4 || RSP.cmd == 0xE5) { + RDP.w2 = ((u32*)RDRAM)[addr++]; + RDP.w3 = ((u32*)RDRAM)[addr++]; + } + } + RSP.bLLE = false; + } +} + +static +void Turbo3D_LoadGlobState(u32 pgstate) +{ + const u32 addr = RSP_SegmentToPhysical(pgstate); + T3DGlobState *gstate = (T3DGlobState*)&RDRAM[addr]; + const u32 w0 = gstate->othermode0; + const u32 w1 = gstate->othermode1; + gDPSetOtherMode( _SHIFTR( w0, 0, 24 ), // mode0 + w1 ); // mode1 + + for (int s = 0; s < 16; ++s) + gSPSegment(s, gstate->segBases[s] & 0x00FFFFFF); + + gSPViewport(pgstate + 80); + + Turbo3D_ProcessRDP(gstate->rdpCmds); +} + +static +void Turbo3D_LoadObject(u32 pstate, u32 pvtx, u32 ptri) +{ + const u32 addr = RSP_SegmentToPhysical(pstate); + T3DState *ostate = (T3DState*)&RDRAM[addr]; + const u32 tile = (ostate->textureState)&7; + gSP.texture.tile = tile; + gSP.textureTile[0] = &gDP.tiles[tile]; + gSP.textureTile[1] = &gDP.tiles[(tile < 7) ? (tile + 1) : tile]; + gSP.texture.scales = 1.0f; + gSP.texture.scalet = 1.0f; + + const u32 w0 = ostate->othermode0; + const u32 w1 = ostate->othermode1; + gDPSetOtherMode( _SHIFTR( w0, 0, 24 ), // mode0 + w1 ); // mode1 + + gSPSetGeometryMode(ostate->renderState); + + if ((ostate->flag&1) == 0) //load matrix + gSPForceMatrix(pstate + sizeof(T3DState)); + + gSPClearGeometryMode(G_LIGHTING); + gSPSetGeometryMode(G_SHADING_SMOOTH); + if (pvtx != 0) //load vtx + gSPVertex(pvtx, ostate->vtxCount, ostate->vtxV0); + + Turbo3D_ProcessRDP(ostate->rdpCmds); + + if (ptri != 0) { + u32 addr = RSP_SegmentToPhysical(ptri); + for (int t = 0; t < ostate->triCount; ++t) { + T3DTriN * tri = (T3DTriN*)&RDRAM[addr]; + addr += 4; + gSPTriangle(tri->v0, tri->v1, tri->v2); + } + video().getRender().drawTriangles(); + } +} + +void RunTurbo3D() +{ + u32 pstate; + do { + u32 addr = RSP.PC[RSP.PCi] >> 2; + const u32 pgstate = ((u32*)RDRAM)[addr++]; + pstate = ((u32*)RDRAM)[addr++]; + const u32 pvtx = ((u32*)RDRAM)[addr++]; + const u32 ptri = ((u32*)RDRAM)[addr]; + if (pstate == 0) { + RSP.halt = 1; + break; + } + if (pgstate != 0) + Turbo3D_LoadGlobState(pgstate); + Turbo3D_LoadObject(pstate, pvtx, ptri); + // Go to the next instruction + RSP.PC[RSP.PCi] += 16; + } while (pstate != 0); +} diff --git a/Turbo3D.h b/Turbo3D.h new file mode 100644 index 00000000..4677fb5d --- /dev/null +++ b/Turbo3D.h @@ -0,0 +1,6 @@ +#ifndef TURBO3D_H +#define TURBO3D_H + +void RunTurbo3D(); + +#endif // TURBO3D_H diff --git a/gSP.cpp b/gSP.cpp index d3f97359..683c7773 100644 --- a/gSP.cpp +++ b/gSP.cpp @@ -778,7 +778,7 @@ void gSPForceMatrix( u32 mptr ) return; } - RSP_LoadMatrix( gSP.matrix.combined, RSP_SegmentToPhysical( mptr ) ); + RSP_LoadMatrix(gSP.matrix.combined, address); gSP.changed &= ~CHANGED_MATRIX; diff --git a/gSP.h b/gSP.h index 0c44050b..e3028a33 100644 --- a/gSP.h +++ b/gSP.h @@ -219,6 +219,7 @@ void gSPCoordMod(u32 _w0, u32 _w1); void gSPTriangleUnknown(); +void gSPTriangle(s32 v0, s32 v1, s32 v2); void gSP1Triangle(s32 v0, s32 v1, s32 v2); void gSP2Triangles(const s32 v00, const s32 v01, const s32 v02, const s32 flag0, const s32 v10, const s32 v11, const s32 v12, const s32 flag1 );