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 );