1
0
mirror of https://github.com/blawar/GLideN64.git synced 2024-07-07 03:13:49 +00:00
GLideN64/RSP.cpp
Sergey Lipskiy d06befb4eb Add a hack for Mario Golf replays.
Replays works only if depth buffer FBO is NOT used as texture
because CPU copies color frame buffer for replays into depth buffer area.
Pause screen in Zelda OOT is copied into depth buffer area and it works only
id depth buffer FBO IS used as texture. Thus it is impossible to write general code
for both situations.
2015-05-13 10:18:42 +06:00

318 lines
7.6 KiB
C++

#include <algorithm>
#include "Debug.h"
#include "RSP.h"
#include "RDP.h"
#include "N64.h"
#include "F3D.h"
#include "Turbo3D.h"
#include "VI.h"
#include "Combiner.h"
#include "FrameBuffer.h"
#include "DepthBuffer.h"
#include "GBI.h"
#include "PluginAPI.h"
#include "Config.h"
using namespace std;
RSPInfo RSP;
void RSP_LoadMatrix( f32 mtx[4][4], u32 address )
{
f32 recip = 1.5258789e-05f;
#ifdef WIN32_ASM
__asm {
mov esi, dword ptr [RDRAM];
add esi, dword ptr [address];
mov edi, dword ptr [mtx];
mov ecx, 4
LoadLoop:
fild word ptr [esi+02h]
movzx eax, word ptr [esi+22h]
mov dword ptr [edi], eax
fild dword ptr [edi]
fmul dword ptr [recip]
fadd
fstp dword ptr [edi]
fild word ptr [esi+00h]
movzx eax, word ptr [esi+20h]
mov dword ptr [edi+04h], eax
fild dword ptr [edi+04h]
fmul dword ptr [recip]
fadd
fstp dword ptr [edi+04h]
fild word ptr [esi+06h]
movzx eax, word ptr [esi+26h]
mov dword ptr [edi+08h], eax
fild dword ptr [edi+08h]
fmul dword ptr [recip]
fadd
fstp dword ptr [edi+08h]
fild word ptr [esi+04h]
movzx eax, word ptr [esi+24h]
mov dword ptr [edi+0Ch], eax
fild dword ptr [edi+0Ch]
fmul dword ptr [recip]
fadd
fstp dword ptr [edi+0Ch]
add esi, 08h
add edi, 10h
loop LoadLoop
}
#else // WIN32_ASM
# ifdef X86_ASM
__asm__ __volatile__(
".intel_syntax noprefix" "\n\t"
"LoadLoop:" "\n\t"
" fild word ptr [esi+0x02]" "\n\t"
" movzx eax, word ptr [esi+0x22]" "\n\t"
" mov dword ptr [edi], eax" "\n\t"
" fild dword ptr [edi]" "\n\t"
" fmul %0" "\n\t"
" fadd" "\n\t"
" fstp dword ptr [edi]" "\n\t"
" fild word ptr [esi+0x00]" "\n\t"
" movzx eax, word ptr [esi+0x20]" "\n\t"
" mov dword ptr [edi+0x04], eax" "\n\t"
" fild dword ptr [edi+0x04]" "\n\t"
" fmul %0" "\n\t"
" fadd" "\n\t"
" fstp dword ptr [edi+0x04]" "\n\t"
" fild word ptr [esi+0x06]" "\n\t"
" movzx eax, word ptr [esi+0x26]" "\n\t"
" mov dword ptr [edi+0x08], eax" "\n\t"
" fild dword ptr [edi+0x08]" "\n\t"
" fmul %0" "\n\t"
" fadd" "\n\t"
" fstp dword ptr [edi+0x08]" "\n\t"
" fild word ptr [esi+0x04]" "\n\t"
" movzx eax, word ptr [esi+0x24]" "\n\t"
" mov dword ptr [edi+0x0C], eax" "\n\t"
" fild dword ptr [edi+0x0C]" "\n\t"
" fmul %0" "\n\t"
" fadd" "\n\t"
" fstp dword ptr [edi+0x0C]" "\n\t"
" add esi, 0x08" "\n\t"
" add edi, 0x10" "\n\t"
" loop LoadLoop" "\n\t"
".att_syntax prefix" "\n\t"
: /* no output */
: "f"(recip), "S"((int)RDRAM+address), "D"(mtx), "c"(4)
: "memory" );
# else // X86_ASM
struct _N64Matrix
{
SHORT integer[4][4];
WORD fraction[4][4];
} *n64Mat = (struct _N64Matrix *)&RDRAM[address];
int i, j;
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
mtx[i][j] = (GLfloat)(n64Mat->integer[i][j^1]) + (GLfloat)(n64Mat->fraction[i][j^1]) * recip;
# endif // !X86_ASM
#endif // WIN32_ASM
}
void RSP_CheckDLCounter()
{
if (RSP.count != -1) {
--RSP.count;
if (RSP.count == 0) {
RSP.count = -1;
--RSP.PCi;
DebugMsg( DEBUG_LOW | DEBUG_HANDLED, "End of DL\n" );
}
}
}
void RSP_ProcessDList()
{
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.changed &= ~CHANGED_CPU_FB_WRITE;
gSP.changed |= CHANGED_MATRIX;
gDPSetDepthSource(G_ZS_PIXEL);
gDPSetTexturePersp(G_TP_PERSP);
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().setNotCleared();
if (GBI.getMicrocodeType() == Turbo3D)
RunTurbo3D();
else {
while (!RSP.halt) {
if ((RSP.PC[RSP.PCi] + 8) > RDRAMSize) {
#ifdef DEBUG
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:
DebugMsg( DEBUG_MEDIUM | DEBUG_ERROR, "Attempting to execute RSP command at invalid RDRAM location\n" );
break;
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" );
}
}*/
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 );
#endif
RSP.PC[RSP.PCi] += 8;
RSP.nextCmd = _SHIFTR(*(u32*)&RDRAM[RSP.PC[RSP.PCi]], 24, 8);
GBI.cmd[RSP.cmd](w0, w1);
RSP_CheckDLCounter();
}
}
if (config.frameBufferEmulation.copyToRDRAM)
FrameBuffer_CopyToRDRAM( gDP.colorImage.address );
if (config.frameBufferEmulation.copyDepthToRDRAM)
FrameBuffer_CopyDepthBuffer( gDP.colorImage.address );
RSP.busy = FALSE;
gSP.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[0].x = gSP.lookat[1].x = 1.0f;
gSP.lookatEnable = false;
gSP.objMatrix.A = 1.0f;
gSP.objMatrix.B = 0.0f;
gSP.objMatrix.C = 0.0f;
gSP.objMatrix.D = 1.0f;
gSP.objMatrix.X = 0.0f;
gSP.objMatrix.Y = 0.0f;
gSP.objMatrix.baseScaleX = 1.0f;
gSP.objMatrix.baseScaleY = 1.0f;
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;
gDPSetAlphaCompare(G_AC_NONE);
gDPSetDepthSource(G_ZS_PIXEL);
gDPSetRenderMode(0, 0);
gDPSetAlphaDither(G_AD_DISABLE);
gDPSetColorDither(G_CD_DISABLE);
gDPSetCombineKey(G_CK_NONE);
gDPSetTextureConvert(G_TC_FILT);
gDPSetTextureFilter(G_TF_POINT);
gDPSetTextureLUT(G_TT_NONE);
gDPSetTextureLOD(G_TL_TILE);
gDPSetTextureDetail(G_TD_CLAMP);
gDPSetTexturePersp(G_TP_PERSP);
gDPSetCycleType(G_CYC_1CYCLE);
gDPPipelineMode(G_PM_NPRIMITIVE);
}
void RSP_Init()
{
#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;
#endif // OS_WINDOWS
RSP.DList = 0;
RSP.uc_start = RSP.uc_dstart = 0;
RSP.bLLE = 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);
if (strstr(RSP.romname, (const char *)"OgreBattle64"))
config.generalEmulation.hacks |= hack_Ogre64;
else if (strstr(RSP.romname, (const char *)"MarioGolf64"))
config.generalEmulation.hacks |= hack_MarioGolf;
api().FindPluginPath(RSP.pluginpath);
RSP_SetDefaultState();
}