mirror of
https://github.com/blawar/GLideN64.git
synced 2024-07-04 10:03:36 +00:00
152 lines
3.3 KiB
C++
152 lines
3.3 KiB
C++
#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)
|
|
{
|
|
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 + 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
|
|
|
|
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) {
|
|
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);
|
|
}
|