1
0
mirror of https://github.com/blawar/GLideN64.git synced 2024-07-02 09:03:37 +00:00

Implement T3DUX ucode.

Ucode decoded by olivieryuyu.

Details:
Toukon road 1 & 2, last legion UX: HLE implementation (extended turbo3D)? #624
https://github.com/gonetz/GLideN64/wiki/T3DUX-ucode
This commit is contained in:
Sergey Lipskiy 2017-06-16 13:23:00 +07:00
parent 312a9a77f2
commit 4722a75b24
11 changed files with 332 additions and 12 deletions

View File

@ -355,6 +355,7 @@
<ClCompile Include="..\..\src\RSP.cpp" />
<ClCompile Include="..\..\src\RSP_LoadMatrixX86.cpp" />
<ClCompile Include="..\..\src\SoftwareRender.cpp" />
<ClCompile Include="..\..\src\T3DUX.cpp" />
<ClCompile Include="..\..\src\TexrectDrawer.cpp" />
<ClCompile Include="..\..\src\TextDrawer.cpp" />
<ClCompile Include="..\..\src\TextureFilterHandler.cpp" />
@ -480,6 +481,7 @@
<ClInclude Include="..\..\src\GraphicsDrawer.h" />
<ClInclude Include="..\..\src\RSP.h" />
<ClInclude Include="..\..\src\SoftwareRender.h" />
<ClInclude Include="..\..\src\T3DUX.h" />
<ClInclude Include="..\..\src\TexrectDrawer.h" />
<ClInclude Include="..\..\src\TextDrawer.h" />
<ClInclude Include="..\..\src\TextureFilterHandler.h" />

View File

@ -338,9 +338,6 @@
<ClCompile Include="..\..\src\TexrectDrawer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\F3DTEXA.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\Graphics\ObjectHandle.cpp">
<Filter>Source Files\Graphics</Filter>
</ClCompile>
@ -353,6 +350,12 @@
<ClCompile Include="..\..\src\xxHash\xxhash.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\F3DTEXA.cpp">
<Filter>Source Files\uCodes</Filter>
</ClCompile>
<ClCompile Include="..\..\src\T3DUX.cpp">
<Filter>Source Files\uCodes</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\3DMath.h">
@ -649,11 +652,14 @@
<ClInclude Include="..\..\src\TexrectDrawer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\src\F3DTEXA.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\src\xxHash\xxhash.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\src\T3DUX.h">
<Filter>Header Files\uCodes</Filter>
</ClInclude>
<ClInclude Include="..\..\src\F3DTEXA.h">
<Filter>Header Files\uCodes</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -50,6 +50,7 @@ set(GLideN64_SOURCES
S2DEX2.cpp
S2DEX.cpp
SoftwareRender.cpp
T3DUX.cpp
TexrectDrawer.cpp
TextDrawer.cpp
TextureFilterHandler.cpp

View File

@ -57,8 +57,10 @@ SpecialMicrocodeInfo specialMicrocodes[] =
{ F3DPD, true, 0x1c4f7869, "Perfect Dark" },
{ Turbo3D, false, 0x2bdcfc8a, "Turbo3D" },
{ F3DEX2CBFD, true, 0x1b4ace88, "Conker's Bad Fur Day" },
{ F3DEX2MM, true, 0xd39a0d4f, "Animal Forest" },
{ S2DEX2, false, 0x2c399dd, "Animal Forest" }
{ F3DEX2MM, true, 0xd39a0d4f, "Animal Forest" },
{ S2DEX2, false, 0x2c399dd, "Animal Forest" },
{ T3DUX, false, 0xbad437f2, "T3DUX vers 0.83 for Toukon Road" },
{ T3DUX, false, 0xd0a1aa3d, "T3DUX vers 0.85 for Toukon Road 2" }
};
u32 G_RDPHALF_1, G_RDPHALF_2, G_RDPHALF_CONT;
@ -192,6 +194,7 @@ void GBIInfo::_makeCurrent(MicrocodeInfo * _pCurrent)
case F3DGOLDEN: F3DGOLDEN_Init(); break;
case F3DEX2MM: F3DEX2MM_Init(); break;
case F3DTEXA: F3DTEXA_Init(); break;
case T3DUX: F3D_Init(); break;
}
if (gfxContext.isSupported(graphics::SpecialFeatures::NearPlaneClipping)) {

View File

@ -25,7 +25,8 @@
#define F3DSETA 16
#define F3DEX2MM 17
#define F3DTEXA 18
#define NONE 19
#define T3DUX 19
#define NONE 20
// Fixed point conversion factors
#define FIXED2FLOATRECIP1 0.5f

View File

@ -6,6 +6,7 @@
#include "N64.h"
#include "F3D.h"
#include "Turbo3D.h"
#include "T3DUX.h"
#include "VI.h"
#include "Combiner.h"
#include "FrameBuffer.h"
@ -70,9 +71,14 @@ void RSP_ProcessDList()
depthBufferList().setNotCleared();
if (GBI.getMicrocodeType() == Turbo3D)
switch (GBI.getMicrocodeType()) {
case Turbo3D:
RunTurbo3D();
else {
break;
case T3DUX:
RunT3DUX();
break;
default:
while (!RSP.halt) {
if ((RSP.PC[RSP.PCi] + 8) > RDRAMSize) {
#ifdef DEBUG

231
src/T3DUX.cpp Normal file
View File

@ -0,0 +1,231 @@
#include "T3DUX.h"
#include "N64.h"
#include "RSP.h"
#include "RDP.h"
#include "gSP.h"
#include "gDP.h"
#include "DisplayWindow.h"
/******************T3DUX 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 */
u8 dmemVtxAddr;
u8 vtxCount; /* number of verts */
u8 texmode;
u8 geommode;
u8 dmemVtxAttribsAddr;
u8 attribsCount; /* number of colors and texture coords */
u8 matrixFlag;
u8 triCount; /* how many tris? */
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 */
u8 pal, v2tex, v1tex, v0tex; /* indexes in texture coords list */
};
static u32 t32uxSetTileW0 = 0;
static u32 t32uxSetTileW1 = 0;
static
void T3DUX_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 );
switch (RSP.cmd) {
case G_TEXRECT:
case G_TEXRECTFLIP:
RDP.w2 = ((u32*)RDRAM)[addr++];
RDP.w3 = ((u32*)RDRAM)[addr++];
break;
case G_SETTILE:
t32uxSetTileW0 = w0;
t32uxSetTileW1 = w1;
break;
}
}
RSP.bLLE = false;
}
}
static
void T3DUX_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);
T3DUX_ProcessRDP(gstate->rdpCmds);
}
static
void T3DUX_LoadObject(u32 pstate, u32 pvtx, u32 ptri, u32 pcol)
{
T3DState *ostate = (T3DState*)&RDRAM[RSP_SegmentToPhysical(pstate)];
// TODO: fix me
const u32 tile = 0;
gSP.texture.tile = tile;
gSP.textureTile[0] = &gDP.tiles[tile];
gSP.textureTile[1] = &gDP.tiles[(tile + 1) & 7];
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
if ((ostate->matrixFlag & 1) == 0) //load matrix
gSPForceMatrix(pstate + sizeof(T3DState));
gSPClearGeometryMode(G_LIGHTING | G_FOG);
gSPSetGeometryMode(ostate->renderState | G_SHADING_SMOOTH | G_SHADE | G_ZBUFFER | G_CULL_BACK);
if (pvtx != 0) //load vtx
gSPT3DUXVertex(pvtx, ostate->vtxCount, pcol);
T3DUX_ProcessRDP(ostate->rdpCmds);
if (ptri == 0)
return;
GraphicsDrawer & drawer = dwnd().getDrawer();
const u32 coladdr = RSP_SegmentToPhysical(pcol);
const T3DTriN * tri = (const T3DTriN*)&RDRAM[RSP_SegmentToPhysical(ptri)];
u8 pal = _SHIFTR(t32uxSetTileW1, 20, 4);
t32uxSetTileW1 &= 0xFF0FFFFF;
const bool flatShading = (ostate->geommode & 0x0F) == 0;
const bool texturing = ostate->texmode != 1;
f32 flatr, flatg, flatb, flata;
drawer.setDMAVerticesSize(ostate->triCount * 3);
SPVertex * pVtx = drawer.getDMAVerticesData();
for (int t = 0; t < ostate->triCount; ++t, ++tri) {
if (texturing && tri->pal != 0) {
const u32 w1 = t32uxSetTileW1 | (tri->pal << 20);
const u32 newPal = _SHIFTR(w1, 20, 4);
if (pal != newPal) {
drawer.drawDMATriangles(pVtx - drawer.getDMAVerticesData());
pVtx = drawer.getDMAVerticesData();
pal = newPal;
RDP_SetTile(t32uxSetTileW0, w1);
}
}
if (tri->v0 >= ostate->vtxCount || tri->v1 >= ostate->vtxCount || tri->v2 >= ostate->vtxCount)
continue;
if (drawer.isClipped(tri->v0, tri->v1, tri->v2))
continue;
if (flatShading) {
struct T3DUXColor
{
u8 a;
u8 b;
u8 g;
u8 r;
} color = *(T3DUXColor*)&RDRAM[coladdr + ((tri->flag << 2) & 0x03FC)];
flata = _FIXED2FLOAT(color.a, 8);
flatb = _FIXED2FLOAT(color.b, 8);
flatg = _FIXED2FLOAT(color.g, 8);
flatr = _FIXED2FLOAT(color.r, 8);
}
u32 vtxIdx[3] = { tri->v0, tri->v1, tri->v2 };
u32 texIdx[3] = { tri->v0tex, tri->v1tex, tri->v2tex };
for (u32 v = 0; v < 3; ++v) {
*pVtx = drawer.getVertex(vtxIdx[v]);
if (texturing) {
u32 texcoords = *(const u32*)&RDRAM[coladdr + (texIdx[v] << 2)];
pVtx->s = _FIXED2FLOAT(_SHIFTR(texcoords, 16, 16), 5);
pVtx->t = _FIXED2FLOAT(_SHIFTR(texcoords, 0, 16), 5);
} else {
pVtx->s = 0.0f;
pVtx->t = 0.0f;
}
if (flatShading) {
pVtx->r = flatr;
pVtx->g = flatg;
pVtx->b = flatb;
pVtx->a = flata;
}
++pVtx;
}
}
drawer.drawDMATriangles(pVtx - drawer.getDMAVerticesData());
}
void RunT3DUX()
{
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++];
const u32 pcol = ((u32*)RDRAM)[addr++];
//const u32 pstore = ((u32*)RDRAM)[addr];
if (pstate == 0) {
RSP.halt = 1;
break;
}
if (pgstate != 0)
T3DUX_LoadGlobState(pgstate);
T3DUX_LoadObject(pstate, pvtx, ptri, pcol);
// Go to the next instruction
RSP.PC[RSP.PCi] += 24;
} while (pstate != 0);
}

6
src/T3DUX.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef T3DUX_H
#define T3DUX_H
void RunT3DUX();
#endif // T3DUX_H

View File

@ -1241,6 +1241,68 @@ void gSPCBFDVertex( u32 a, u32 n, u32 v0 )
}
}
void gSPT3DUXVertex(u32 a, u32 n, u32 ci)
{
const u32 address = RSP_SegmentToPhysical(a);
const u32 colors = RSP_SegmentToPhysical(ci);
struct T3DUXVertex {
s16 y;
s16 x;
u16 flag;
s16 z;
} *vertex = (T3DUXVertex*)&RDRAM[address];
struct T3DUXColor
{
u8 a;
u8 b;
u8 g;
u8 r;
} *color = (T3DUXColor*)&RDRAM[colors];
if ((address + sizeof(T3DUXVertex)* n) > RDRAMSize)
return;
GraphicsDrawer & drawer = dwnd().getDrawer();
u32 i = 0;
#ifdef __VEC4_OPT
for (; i < n - (n % 4); i += 4) {
u32 v = i;
for (int j = 0; j < 4; ++j) {
SPVertex & vtx = drawer.getVertex(v + j);
vtx.x = vertex->x;
vtx.y = vertex->y;
vtx.z = vertex->z;
vtx.s = 0;
vtx.t = 0;
vtx.r = _FIXED2FLOAT(color->r, 8);
vtx.g = _FIXED2FLOAT(color->g, 8);
vtx.b = _FIXED2FLOAT(color->b, 8);
vtx.a = _FIXED2FLOAT(color->a, 8);
vertex++;
color++;
}
gSPProcessVertex4(v);
}
#endif
for (; i < n; ++i) {
SPVertex & vtx = drawer.getVertex(i);
vtx.x = vertex->x;
vtx.y = vertex->y;
vtx.z = vertex->z;
vtx.s = 0;
vtx.t = 0;
vtx.r = _FIXED2FLOAT(color->r, 8);
vtx.g = _FIXED2FLOAT(color->g, 8);
vtx.b = _FIXED2FLOAT(color->b, 8);
vtx.a = _FIXED2FLOAT(color->a, 8);
gSPProcessVertex(i);
vertex++;
color++;
}
}
void gSPDisplayList( u32 dl )
{
u32 address = RSP_SegmentToPhysical( dl );

View File

@ -153,7 +153,8 @@ void gSPVertex( u32 v, u32 n, u32 v0 );
void gSPCIVertex( u32 v, u32 n, u32 v0 );
void gSPDMAVertex( u32 v, u32 n, u32 v0 );
void gSPCBFDVertex( u32 v, u32 n, u32 v0 );
void gSPDisplayList( u32 dl );
void gSPT3DUXVertex(u32 v, u32 n, u32 ci);
void gSPDisplayList(u32 dl);
void gSPBranchList( u32 dl );
void gSPBranchLessZ( u32 branchdl, u32 vtx, u32 zval );
void gSPBranchLessW( u32 branchdl, u32 vtx, u32 wval );

View File

@ -60,6 +60,7 @@ MY_LOCAL_SRC_FILES := \
$(SRCDIR)/S2DEX2.cpp \
$(SRCDIR)/S2DEX.cpp \
$(SRCDIR)/SoftwareRender.cpp \
$(SRCDIR)/T3DUX.cpp \
$(SRCDIR)/TexrectDrawer.cpp \
$(SRCDIR)/TextDrawer.cpp \
$(SRCDIR)/TextureFilterHandler.cpp \