1
0
mirror of https://github.com/blawar/GLideN64.git synced 2024-06-25 22:09:35 +00:00
GLideN64/src/RSP.cpp
Sergey Lipskiy 3d74542d24 Correct geometry mode update for Turbo3D.
Fixed glitches in Dark Rift, #2033
2019-04-03 21:32:50 +07:00

354 lines
11 KiB
C++

#include <algorithm>
#include <cstring>
#include "DebugDump.h"
#include "RSP.h"
#include "RDP.h"
#include "N64.h"
#include "uCodes/F3D.h"
#include "uCodes/Turbo3D.h"
#include "uCodes/T3DUX.h"
#include "VI.h"
#include "Combiner.h"
#include "FrameBuffer.h"
#include "DepthBuffer.h"
#include "FrameBufferInfo.h"
#include "GBI.h"
#include "PluginAPI.h"
#include "Config.h"
#include "TextureFilterHandler.h"
#include "DisplayWindow.h"
using namespace std;
#define SP_STATUS_HALT 0x0001
#define SP_STATUS_BROKE 0x0002
#define SP_STATUS_TASKDONE 0x0200
RSPInfo RSP;
static
void _ProcessDList()
{
while (!RSP.halt) {
if ((RSP.PC[RSP.PCi] + 8) > RDRAMSize) {
#ifdef DEBUG_DUMP
if ((config.debug.dumpMode & DEBUG_DETAIL) != 0)
DebugMsg(DEBUG_DETAIL | DEBUG_ERROR, "// Attempting to execute RSP command at invalid RDRAM location\n");
else if ((config.debug.dumpMode & DEBUG_NORMAL) != 0)
DebugMsg(DEBUG_NORMAL | DEBUG_ERROR, "Attempting to execute RSP command at invalid RDRAM location\n");
else if ((config.debug.dumpMode & DEBUG_LOW) != 0)
DebugMsg(DEBUG_LOW | DEBUG_ERROR, "ATTEMPTING TO EXECUTE RSP COMMAND AT INVALID RDRAM LOCATION\n");
#endif
break;
}
RSP.w0 = *(u32*)&RDRAM[RSP.PC[RSP.PCi]];
RSP.w1 = *(u32*)&RDRAM[RSP.PC[RSP.PCi] + 4];
RSP.cmd = _SHIFTR(RSP.w0, 24, 8);
#ifdef DEBUG_DUMP
DebugMsg(DEBUG_LOW, "0x%08lX: CMD=0x%02lX W0=0x%08lX W1=0x%08lX\n", RSP.PC[RSP.PCi], _SHIFTR(RSP.w0, 24, 8), RSP.w0, RSP.w1);
#endif
RSP.PC[RSP.PCi] += 8;
u32 pci = RSP.PCi;
if (RSP.count == 1)
--pci;
RSP.nextCmd = _SHIFTR(*(u32*)&RDRAM[RSP.PC[pci]], 24, 8);
GBI.cmd[RSP.cmd](RSP.w0, RSP.w1);
RSP_CheckDLCounter();
}
}
static
void _ProcessDListFactor5()
{
// Lemmy's note: read first 64 bits of this dlist
RSP.F5DL[0] = _SHIFTR(*(u32*)&RDRAM[RSP.PC[0]], 0, 24);
RSP.PC[0] += 8;
static u32 vAddrToClear[7] = { 0x11C >> 2, 0x120 >> 2, 0x124 >> 2, 0x37C >> 2,
0x58C >> 2, 0x5B0 >> 2, 0x5B4 >> 2};
u32 * pDmem32 = reinterpret_cast<u32*>(DMEM);
for (u32 i = 0; i < 7; ++i)
pDmem32[vAddrToClear[i]] = 0U;
while (!RSP.halt) {
if ((RSP.PC[RSP.PCi] + 8) > RDRAMSize) {
break;
}
RSP.w0 = *(u32*)&RDRAM[RSP.PC[RSP.PCi]];
RSP.w1 = *(u32*)&RDRAM[RSP.PC[RSP.PCi] + 4];
RSP.cmd = _SHIFTR(RSP.w0, 24, 8);
#ifdef DEBUG_DUMP
DebugMsg(DEBUG_LOW, "0x%08lX: CMD=0x%02lX W0=0x%08lX W1=0x%08lX\n", RSP.PC[RSP.PCi], _SHIFTR(RSP.w0, 24, 8), RSP.w0, RSP.w1);
#endif
RSP.nextCmd = _SHIFTR(*(u32*)&RDRAM[RSP.PC[RSP.PCi] + 8], 24, 8);
GBI.cmd[RSP.cmd](RSP.w0, RSP.w1);
RSP.PC[RSP.PCi] += 8;
RSP_CheckDLCounter();
}
}
void RSP_CheckDLCounter()
{
if (RSP.count != -1) {
--RSP.count;
if (RSP.count == 0) {
RSP.count = -1;
--RSP.PCi;
DebugMsg(DEBUG_NORMAL, "End of DL\n");
}
}
}
void RSP_ProcessDList()
{
if (ConfigOpen || dwnd().isResizeWindow()) {
*REG.MI_INTR |= MI_INTR_DP;
CheckInterrupts();
return;
}
if (RSP.infloop) {
RSP.infloop = false;
RSP.halt = false;
} else {
if (*REG.VI_ORIGIN != VI.lastOrigin) {
VI_UpdateSize();
dwnd().updateScale();
}
RSP.PC[0] = *(u32*)&DMEM[0x0FF0];
RSP.PCi = 0;
RSP.count = -1;
RSP.halt = false;
RSP.busy = true;
gSP.matrix.stackSize = min( 32U, *(u32*)&DMEM[0x0FE4] >> 6 );
if (gSP.matrix.stackSize == 0)
gSP.matrix.stackSize = 32;
gSP.matrix.modelViewi = 0;
gSP.status[0] = gSP.status[1] = gSP.status[2] = gSP.status[3] = 0;
gSP.geometryMode = 0U;
gSP.changed |= CHANGED_MATRIX | CHANGED_LIGHT | CHANGED_LOOKAT | CHANGED_GEOMETRYMODE;
gSP.tri_num = 0;
gSP.cbfd.advancedLighting = false;
gDP.changed &= ~CHANGED_CPU_FB_WRITE;
gDPSetTexturePersp(G_TP_PERSP);
// Get the start of the display list and the length of it
const u32 dlist_start = *(u32*)(DMEM + 0xFF0);
const u32 dlist_length = *(u32*)(DMEM + 0xFF4);
DebugMsg(DEBUG_NORMAL, "--- NEW DLIST --- ucode: %d, fbuf: %08lx, fbuf_width: %d, dlist start: %08lx, dlist_length: %d, x_scale: %f, y_scale: %f\n",
GBI.getMicrocodeType(), *REG.VI_ORIGIN, *REG.VI_WIDTH, dlist_start, dlist_length, (*REG.VI_X_SCALE & 0xFFF) / 1024.0f, (*REG.VI_Y_SCALE & 0xFFF) / 1024.0f);
u32 uc_start = *(u32*)&DMEM[0x0FD0];
u32 uc_dstart = *(u32*)&DMEM[0x0FD8];
u32 uc_dsize = *(u32*)&DMEM[0x0FDC];
if ((uc_start != RSP.uc_start) || (uc_dstart != RSP.uc_dstart))
gSPLoadUcodeEx(uc_start, uc_dstart, uc_dsize);
depthBufferList().setCleared(false);
if (GBI.getMicrocodeType() == ZSortBOSS) {
RSP.PC[1] = *(u32*)&DMEM[0xff8];
*REG.SP_STATUS &= ~0x300; // clear sig1 | sig2
*REG.SP_STATUS |= 0x800; // set sig4
}
}
switch (GBI.getMicrocodeType()) {
case Turbo3D:
RunTurbo3D();
break;
case T3DUX:
RunT3DUX();
break;
case F5Rogue:
case F5Indi_Naboo:
_ProcessDListFactor5();
break;
default:
_ProcessDList();
break;
}
if (RSP.infloop && REG.SP_STATUS) {
*REG.SP_STATUS &= ~(SP_STATUS_TASKDONE | SP_STATUS_HALT | SP_STATUS_BROKE);
return;
}
if (config.frameBufferEmulation.copyDepthToRDRAM != Config::cdDisable) {
if ((config.generalEmulation.hacks & hack_rectDepthBufferCopyCBFD) != 0) {
; // do nothing
} else if ((config.generalEmulation.hacks & hack_rectDepthBufferCopyPD) != 0) {
if (rectDepthBufferCopyFrame == dwnd().getBuffersSwapCount())
FrameBuffer_CopyDepthBuffer(gDP.colorImage.address);
} else if (!FBInfo::fbInfo.isSupported())
FrameBuffer_CopyDepthBuffer(gDP.colorImage.address);
}
RSP.busy = false;
gDP.changed |= CHANGED_COLORBUFFER;
}
static
void RSP_SetDefaultState()
{
memset(&gSP, 0, sizeof(gSPInfo));
gSPTexture(1.0f, 1.0f, 0, 0, TRUE);
gDP.loadTile = &gDP.tiles[7];
gSP.textureTile[0] = &gDP.tiles[0];
gSP.textureTile[1] = &gDP.tiles[1];
gSP.lookat.xyz[0][Y] = gSP.lookat.xyz[1][X] = 1.0f;
gSP.lookatEnable = true;
gSP.objRendermode = 0;
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
gSP.matrix.modelView[0][i][j] = 0.0f;
gSP.matrix.modelView[0][0][0] = 1.0f;
gSP.matrix.modelView[0][1][1] = 1.0f;
gSP.matrix.modelView[0][2][2] = 1.0f;
gSP.matrix.modelView[0][3][3] = 1.0f;
gSP.clipRatio = 2U;
gDP.otherMode._u64 = 0U;
gDP.otherMode.bi_lerp0 = gDP.otherMode.bi_lerp1 = 1;
}
u32 DepthClearColor = 0xfffcfffc;
static
void setDepthClearColor()
{
if (strstr(RSP.romname, (const char *)"Elmo's") != nullptr)
DepthClearColor = 0xFFFFFFFF;
else if (strstr(RSP.romname, (const char *)"Taz Express") != nullptr)
DepthClearColor = 0xFFBCFFBC;
else if (strstr(RSP.romname, (const char *)"NFL QBC 2000") != nullptr || strstr(RSP.romname, (const char *)"NFL Quarterback Club") != nullptr || strstr(RSP.romname, (const char *)"Jeremy McGrath Super") != nullptr)
DepthClearColor = 0xFFFDFFFC;
else
DepthClearColor = 0xFFFCFFFC;
}
void RSP_Init()
{
if (RDRAMSize == 0) {
#ifdef OS_WINDOWS
// Calculate RDRAM size by intentionally causing an access violation
u32 test;
try
{
test = RDRAM[0x007FFFFF] + 1;
}
catch (...)
{
test = 0;
}
if (test > 0)
RDRAMSize = 0x7FFFFF;
else
RDRAMSize = 0x3FFFFF;
#else // OS_WINDOWS
RDRAMSize = 1024 * 1024 * 8 - 1;
#endif // OS_WINDOWS
}
RSP.uc_start = RSP.uc_dstart = 0;
RSP.LLE = false;
RSP.infloop = false;
// get the name of the ROM
char romname[21];
for (int i = 0; i < 20; ++i)
romname[i] = HEADER[(32 + i) ^ 3];
romname[20] = 0;
// remove all trailing spaces
while (romname[strlen(romname) - 1] == ' ')
romname[strlen(romname) - 1] = 0;
if (strcmp(RSP.romname, romname) != 0)
TFH.shutdown();
strncpy(RSP.romname, romname, 21);
setDepthClearColor();
config.generalEmulation.hacks = 0;
if (strstr(RSP.romname, (const char *)"OgreBattle64") != nullptr)
config.generalEmulation.hacks |= hack_Ogre64;
else if (strstr(RSP.romname, (const char *)"F1 POLE POSITION 64") != nullptr)
config.generalEmulation.hacks |= hack_noDepthFrameBuffers;
else if (strstr(RSP.romname, (const char *)"ROADSTERS TROPHY") != nullptr)
config.generalEmulation.hacks |= hack_noDepthFrameBuffers;
else if (strstr(RSP.romname, (const char *)"VIGILANTE 8") != nullptr)
config.generalEmulation.hacks |= hack_noDepthFrameBuffers;
else if (strstr(RSP.romname, (const char *)"CONKER BFD") != nullptr)
config.generalEmulation.hacks |= hack_blurPauseScreen | hack_rectDepthBufferCopyCBFD;
else if (strstr(RSP.romname, (const char *)"MICKEY USA") != nullptr)
config.generalEmulation.hacks |= hack_blurPauseScreen;
else if (strstr(RSP.romname, (const char *)"GOLDENEYE") != nullptr)
config.generalEmulation.hacks |= hack_clearAloneDepthBuffer;
else if (strstr(RSP.romname, (const char *)"STARCRAFT 64") != nullptr)
config.generalEmulation.hacks |= hack_StarCraftBackgrounds;
else if (strstr(RSP.romname, (const char *)"POKEMON STADIUM 2") != nullptr ||
strstr(RSP.romname, (const char *)"Bottom of the 9th") != nullptr)
config.generalEmulation.hacks |= hack_texrect_shade_alpha;
else if (strstr(RSP.romname, (const char *)"THE LEGEND OF ZELDA") != nullptr ||
strstr(RSP.romname, (const char *)"ZELDA MASTER QUEST") != nullptr)
config.generalEmulation.hacks |= hack_subscreen | hack_ZeldaMonochrome;
else if (strstr(RSP.romname, (const char *)"DOUBUTSUNOMORI") != nullptr ||
strstr(RSP.romname, (const char *)"ANIMAL FOREST") != nullptr)
config.generalEmulation.hacks |= hack_subscreen;
else if (strstr(RSP.romname, (const char *)"Lode Runner 3D") != nullptr)
config.generalEmulation.hacks |= hack_LodeRunner;
else if (strstr(RSP.romname, (const char *)"Blast") != nullptr)
config.generalEmulation.hacks |= hack_blastCorps;
else if (strstr(RSP.romname, (const char *)"MASK") != nullptr) // Zelda MM
config.generalEmulation.hacks |= hack_ZeldaMonochrome | hack_ZeldaMM;
else if (strstr(RSP.romname, (const char *)"Perfect Dark") != nullptr ||
strstr(RSP.romname, (const char *)"PERFECT DARK") != nullptr)
config.generalEmulation.hacks |= hack_rectDepthBufferCopyPD | hack_clearAloneDepthBuffer;
else if (strstr(RSP.romname, (const char *)"Jeremy McGrath Super") != nullptr)
config.generalEmulation.hacks |= hack_ModifyVertexXyInShader;
else if (strstr(RSP.romname, (const char *)"RAT ATTACK") != nullptr)
config.generalEmulation.hacks |= hack_ModifyVertexXyInShader;
else if (strstr(RSP.romname, (const char *)"Quake") != nullptr)
config.generalEmulation.hacks |= hack_doNotResetOtherModeH|hack_doNotResetOtherModeL;
else if (strstr(RSP.romname, (const char *)"QUAKE II") != nullptr ||
strstr(RSP.romname, (const char *)"GAUNTLET LEGENDS") != nullptr)
config.generalEmulation.hacks |= hack_doNotResetOtherModeH;
else if (strstr(RSP.romname, (const char *)"quarterback_club_98") != nullptr)
config.generalEmulation.hacks |= hack_LoadDepthTextures;
else if (strstr(RSP.romname, (const char *)"WIN BACK") != nullptr ||
strstr(RSP.romname, (const char *)"OPERATION WINBACK") != nullptr)
config.generalEmulation.hacks |= hack_WinBack;
else if (strstr(RSP.romname, (const char *)"POKEMON SNAP") != nullptr)
config.generalEmulation.hacks |= hack_Snap;
else if (strstr(RSP.romname, (const char *)"MARIOKART64") != nullptr)
config.generalEmulation.hacks |= hack_MK64;
else if (strstr(RSP.romname, (const char *)"Resident Evil II") ||
strstr(RSP.romname, (const char *)"BioHazard II"))
config.generalEmulation.hacks |= hack_RE2 | hack_ModifyVertexXyInShader | hack_LoadDepthTextures;
else if (strstr(RSP.romname, (const char *)"THPS") != nullptr)
config.generalEmulation.hacks |= hack_TonyHawk;
else if (strstr(RSP.romname, (const char *)"NITRO64") != nullptr)
config.generalEmulation.hacks |= hack_WCWNitro;
api().FindPluginPath(RSP.pluginpath);
RSP_SetDefaultState();
}