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

352 lines
10 KiB
C++
Raw Normal View History

#include <algorithm>
#include <assert.h>
2015-10-10 17:34:47 +00:00
#include <cctype>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
2013-11-29 05:15:58 +00:00
#include "convert.h"
2013-11-27 10:08:48 +00:00
#include "N64.h"
2013-04-21 14:28:50 +00:00
#include "GLideN64.h"
#include "GBI.h"
#include "RDP.h"
#include "RSP.h"
#include "F3D.h"
#include "F3DEX.h"
#include "F3DEX2.h"
#include "L3D.h"
#include "L3DEX.h"
#include "L3DEX2.h"
#include "S2DEX.h"
#include "S2DEX2.h"
#include "F3DAM.h"
#include "F3DDKR.h"
#include "F3DBETA.h"
#include "F3DPD.h"
#include "F3DSETA.h"
2016-12-13 16:14:22 +00:00
#include "F3DGOLDEN.h"
2014-10-16 10:49:32 +00:00
#include "F3DEX2CBFD.h"
2016-12-19 13:27:31 +00:00
#include "F3DEX2MM.h"
#include "F3DTEXA.h"
#include "F3DEX2ACCLAIM.h"
#include "F3DSWRS.h"
2014-11-01 15:07:07 +00:00
#include "ZSort.h"
#include "CRC.h"
2014-03-21 07:41:21 +00:00
#include "Log.h"
2017-05-25 08:54:30 +00:00
#include "DebugDump.h"
2017-01-22 13:43:05 +00:00
#include "Graphics/Context.h"
#include "Graphics/Parameters.h"
2014-03-21 07:41:21 +00:00
u32 last_good_ucode = (u32) -1;
SpecialMicrocodeInfo specialMicrocodes[] =
{
{ F3D, false, true, 0xe62a706d, "Fast3D" },
{ F3D, false, false, 0x7d372819, "Super3D" }, // Pachinko nichi 365
{ F3D, false, false, 0xe01e14be, "Super3D" }, // Eikou no Saint Andrews
{ F3D, false, true, 0x4AED6B3B, "Fast3D" }, //Vivid Dolls [ALECK64]
{ F3DSETA, false, true, 0x2edee7be, "RSP SW Version: 2.0D, 04-01-96" },
{ F3DBETA, false, true, 0xd17906e2, "RSP SW Version: 2.0D, 04-01-96" }, // Wave Race (U)
{ F3DBETA, false, true, 0x94c4c833, "RSP SW Version: 2.0D, 04-01-96" }, // Star Wars Shadows of Empire
{ F3DEX, true, true, 0x637b4b58, "RSP SW Version: 2.0D, 04-01-96" },
{ F3D, true, true, 0x54c558ba, "RSP SW Version: 2.0D, 04-01-96" }, // Pilot Wings
{ F3DGOLDEN, true, true, 0x302bca09, "RSP SW Version: 2.0G, 09-30-96" }, // GoldenEye
{ S2DEX, false, true, 0x9df31081, "RSP Gfx ucode S2DEX 1.06 Yoshitaka Yasumoto Nintendo." },
{ F3DDKR, false, true, 0x8d91244f, "Diddy Kong Racing" },
{ F3DDKR, false, true, 0x6e6fc893, "Diddy Kong Racing" },
{ F3DJFG, false, true, 0xbde9d1fb, "Jet Force Gemini" },
{ F3DPD, true, true, 0x1c4f7869, "Perfect Dark" },
{ Turbo3D, false, true, 0x2bdcfc8a, "Turbo3D" },
{ F3DEX2CBFD, true, true, 0x1b4ace88, "Conker's Bad Fur Day" },
{ F3DSWRS, false, false, 0xda51ccdb, "Star Wars RS" },
{ F3DEX2MM, true, true, 0xd39a0d4f, "Animal Forest" },
{ S2DEX2, false, true, 0x2c399dd, "Animal Forest" },
{ T3DUX, false, true, 0xbad437f2, "T3DUX vers 0.83 for Toukon Road" },
{ T3DUX, false, true, 0xd0a1aa3d, "T3DUX vers 0.85 for Toukon Road 2" },
{ F3DEX2ACCLAIM,true, true, 0xe44df568, "Acclaim games: Turok2 & 3, Armories and South park" }
};
u32 G_RDPHALF_1, G_RDPHALF_2, G_RDPHALF_CONT;
u32 G_SPNOOP;
u32 G_SETOTHERMODE_H, G_SETOTHERMODE_L;
u32 G_DL, G_ENDDL, G_CULLDL, G_BRANCH_Z;
u32 G_LOAD_UCODE;
u32 G_MOVEMEM, G_MOVEWORD;
u32 G_MTX, G_POPMTX;
u32 G_GEOMETRYMODE, G_SETGEOMETRYMODE, G_CLEARGEOMETRYMODE;
u32 G_TEXTURE;
u32 G_DMA_IO, G_DMA_DL, G_DMA_TRI, G_DMA_MTX, G_DMA_VTX, G_DMA_TEX_OFFSET, G_DMA_OFFSETS;
u32 G_SPECIAL_1, G_SPECIAL_2, G_SPECIAL_3;
u32 G_VTX, G_MODIFYVTX, G_VTXCOLORBASE;
u32 G_TRI1, G_TRI2, G_TRIX;
u32 G_QUAD, G_LINE3D;
u32 G_RESERVED0, G_RESERVED1, G_RESERVED2, G_RESERVED3;
u32 G_SPRITE2D_BASE;
u32 G_BG_1CYC, G_BG_COPY;
u32 G_OBJ_RECTANGLE, G_OBJ_SPRITE, G_OBJ_MOVEMEM;
u32 G_SELECT_DL, G_OBJ_RENDERMODE, G_OBJ_RECTANGLE_R;
u32 G_OBJ_LOADTXTR, G_OBJ_LDTX_SPRITE, G_OBJ_LDTX_RECT, G_OBJ_LDTX_RECT_R;
u32 G_RDPHALF_0;
u32 G_PERSPNORM;
u32 G_MTX_STACKSIZE;
u32 G_MTX_MODELVIEW;
u32 G_MTX_PROJECTION;
u32 G_MTX_MUL;
u32 G_MTX_LOAD;
u32 G_MTX_NOPUSH;
u32 G_MTX_PUSH;
u32 G_TEXTURE_ENABLE;
u32 G_SHADING_SMOOTH;
u32 G_CULL_FRONT;
u32 G_CULL_BACK;
u32 G_CULL_BOTH;
u32 G_CLIPPING;
u32 G_MV_VIEWPORT;
u32 G_MWO_aLIGHT_1, G_MWO_bLIGHT_1;
u32 G_MWO_aLIGHT_2, G_MWO_bLIGHT_2;
u32 G_MWO_aLIGHT_3, G_MWO_bLIGHT_3;
u32 G_MWO_aLIGHT_4, G_MWO_bLIGHT_4;
u32 G_MWO_aLIGHT_5, G_MWO_bLIGHT_5;
u32 G_MWO_aLIGHT_6, G_MWO_bLIGHT_6;
u32 G_MWO_aLIGHT_7, G_MWO_bLIGHT_7;
u32 G_MWO_aLIGHT_8, G_MWO_bLIGHT_8;
GBIInfo GBI;
void GBI_Unknown( u32 w0, u32 w1 )
{
2017-05-25 08:54:30 +00:00
DebugMsg(DEBUG_NORMAL, "UNKNOWN GBI COMMAND 0x%02X", _SHIFTR(w0, 24, 8));
}
void GBIInfo::init()
{
m_pCurrent = nullptr;
_flushCommands();
}
void GBIInfo::destroy()
{
m_pCurrent = nullptr;
m_list.clear();
}
bool GBIInfo::isHWLSupported() const
{
if (m_pCurrent == nullptr)
return false;
switch (m_pCurrent->type) {
case S2DEX:
case S2DEX2:
case F3DDKR:
case F3DJFG:
case F3DEX2CBFD:
case F3DEX2ACCLAIM:
return false;
}
return true;
}
void GBIInfo::_flushCommands()
{
std::fill(std::begin(cmd), std::end(cmd), GBI_Unknown);
}
void GBIInfo::_makeCurrent(MicrocodeInfo * _pCurrent)
{
if (_pCurrent->type == NONE) {
LOG(LOG_ERROR, "[GLideN64]: error - unknown ucode!!!\n");
return;
}
if (m_pCurrent == nullptr || (m_pCurrent->type != _pCurrent->type)) {
2014-10-16 10:49:32 +00:00
m_pCurrent = _pCurrent;
_flushCommands();
RDP_Init();
G_TRI1 = G_TRI2 = G_TRIX = G_QUAD = -1; // For correct work of gSPFlushTriangles()
2014-10-16 10:49:32 +00:00
switch (m_pCurrent->type) {
case F3D: F3D_Init(); break;
case F3DEX: F3DEX_Init(); break;
case F3DEX2: F3DEX2_Init(); break;
case L3D: L3D_Init(); break;
case L3DEX: L3DEX_Init(); break;
case L3DEX2: L3DEX2_Init(); break;
case S2DEX: S2DEX_Init(); break;
case S2DEX2: S2DEX2_Init(); break;
case F3DDKR: F3DDKR_Init(); break;
case F3DJFG: F3DJFG_Init(); break;
case F3DBETA: F3DBETA_Init(); break;
case F3DPD: F3DPD_Init(); break;
case F3DAM: F3DAM_Init(); break;
case Turbo3D: F3D_Init(); break;
case ZSortp: ZSort_Init(); break;
case F3DEX2CBFD: F3DEX2CBFD_Init(); break;
case F3DSETA: F3DSETA_Init(); break;
case F3DGOLDEN: F3DGOLDEN_Init(); break;
case F3DEX2MM: F3DEX2MM_Init(); break;
case F3DTEXA: F3DTEXA_Init(); break;
case T3DUX: F3D_Init(); break;
case F3DEX2ACCLAIM: F3DEX2ACCLAIM_Init(); break;
case F3DSWRS: F3DSWRS_Init(); break;
}
if (gfxContext.isSupported(graphics::SpecialFeatures::NearPlaneClipping)) {
if (m_pCurrent->NoN) {
// Disable near and far plane clipping
gfxContext.enable(graphics::enable::DEPTH_CLAMP, true);
// Enable Far clipping plane in vertex shader
gfxContext.enable(graphics::enable::CLIP_DISTANCE0, true);
} else {
gfxContext.enable(graphics::enable::DEPTH_CLAMP, false);
gfxContext.enable(graphics::enable::CLIP_DISTANCE0, false);
}
}
} else if (m_pCurrent->NoN != _pCurrent->NoN) {
if (gfxContext.isSupported(graphics::SpecialFeatures::NearPlaneClipping)) {
if (_pCurrent->NoN) {
// Disable near and far plane clipping
gfxContext.enable(graphics::enable::DEPTH_CLAMP, true);
// Enable Far clipping plane in vertex shader
gfxContext.enable(graphics::enable::CLIP_DISTANCE0, true);
}
else {
gfxContext.enable(graphics::enable::DEPTH_CLAMP, false);
gfxContext.enable(graphics::enable::CLIP_DISTANCE0, false);
}
}
}
m_pCurrent = _pCurrent;
}
bool GBIInfo::_makeExistingMicrocodeCurrent(u32 uc_start, u32 uc_dstart, u32 uc_dsize)
{
auto iter = std::find_if(m_list.begin(), m_list.end(), [=](const MicrocodeInfo& info) {
return info.address == uc_start && info.dataAddress == uc_dstart && info.dataSize == uc_dsize;
});
if (iter == m_list.end())
return false;
_makeCurrent(&*iter);
return true;
}
void GBIInfo::loadMicrocode(u32 uc_start, u32 uc_dstart, u16 uc_dsize)
{
if (_makeExistingMicrocodeCurrent(uc_start, uc_dstart, uc_dsize))
return;
m_list.emplace_front();
MicrocodeInfo & current = m_list.front();
current.address = uc_start;
current.dataAddress = uc_dstart;
current.dataSize = uc_dsize;
current.NoN = false;
current.negativeY = true;
current.textureGen = true;
current.texturePersp = true;
current.type = NONE;
// See if we can identify it by CRC
const u32 uc_crc = CRC_Calculate_Strict( 0xFFFFFFFF, &RDRAM[uc_start & 0x1FFFFFFF], 4096 );
const u32 numSpecialMicrocodes = sizeof(specialMicrocodes) / sizeof(SpecialMicrocodeInfo);
for (u32 i = 0; i < numSpecialMicrocodes; ++i) {
if (uc_crc == specialMicrocodes[i].crc) {
current.type = specialMicrocodes[i].type;
current.NoN = specialMicrocodes[i].NoN;
current.negativeY = specialMicrocodes[i].negativeY;
_makeCurrent(&current);
return;
}
}
// See if we can identify it by text
char uc_data[2048];
UnswapCopyWrap(RDRAM, uc_dstart & 0x1FFFFFFF, (u8*)uc_data, 0, 0x7FF, 2048);
char uc_str[256];
strcpy(uc_str, "Not Found");
for (u32 i = 0; i < 2046; ++i) {
if ((uc_data[i] == 'R') && (uc_data[i+1] == 'S') && (uc_data[i+2] == 'P')) {
u32 j = 0;
while (uc_data[i+j] > 0x0A) {
uc_str[j] = uc_data[i+j];
j++;
}
uc_str[j] = 0x00;
int type = NONE;
if (strncmp( &uc_str[4], "SW", 2 ) == 0)
type = F3D;
else if (strncmp( &uc_str[4], "Gfx", 3 ) == 0) {
current.NoN = (strstr( uc_str + 4, ".NoN") != nullptr);
if (strncmp( &uc_str[14], "F3D", 3 ) == 0) {
if (uc_str[28] == '1' || strncmp(&uc_str[28], "0.95", 4) == 0 || strncmp(&uc_str[28], "0.96", 4) == 0)
type = F3DEX;
else if (uc_str[31] == '2')
type = F3DEX2;
if (strncmp(&uc_str[14], "F3DF", 4) == 0)
current.textureGen = false;
else if (strncmp(&uc_str[14], "F3DZEX", 6) == 0) {
// Zelda games
// Check ucode version
if (strncmp(&uc_str[31], "2.08I", 5) == 0)
type = F3DEX2MM;
else
type = F3DEX2;
} else if (strncmp(&uc_str[14], "F3DTEX/A", 8) == 0)
type = F3DTEXA;
else if (strncmp(&uc_str[14], "F3DAM", 5) == 0)
type = F3DAM;
else if (strncmp(&uc_str[14], "F3DLX.Rej", 9) == 0)
current.NoN = true;
else if (strncmp(&uc_str[14], "F3DLP.Rej", 9) == 0) {
current.texturePersp = false;
current.NoN = true;
}
}
else if (strncmp( &uc_str[14], "L3D", 3 ) == 0) {
2014-10-23 15:10:29 +00:00
u32 t = 22;
2015-10-10 17:34:47 +00:00
while (!std::isdigit(uc_str[t]) && t++ < j);
2014-10-23 15:10:29 +00:00
if (uc_str[t] == '1')
type = L3DEX;
2014-10-23 15:10:29 +00:00
else if (uc_str[t] == '2')
type = L3DEX2;
}
else if (strncmp( &uc_str[14], "S2D", 3 ) == 0) {
2014-10-23 15:10:29 +00:00
u32 t = 20;
2015-10-10 17:34:47 +00:00
while (!std::isdigit(uc_str[t]) && t++ < j);
2014-10-23 15:10:29 +00:00
if (uc_str[t] == '1')
type = S2DEX;
2014-10-23 15:10:29 +00:00
else if (uc_str[t] == '2')
type = S2DEX2;
current.texturePersp = false;
}
2014-11-01 15:07:07 +00:00
else if (strncmp(&uc_str[14], "ZSortp", 6) == 0) {
type = ZSortp;
}
}
if (type != NONE) {
current.type = type;
_makeCurrent(&current);
return;
}
break;
}
}
2015-02-10 15:51:45 +00:00
assert(false && "unknown ucode!!!'n");
_makeCurrent(&current);
}