diff --git a/F3DEX2.cpp b/F3DEX2.cpp index d902c51b..a865dcf3 100644 --- a/F3DEX2.cpp +++ b/F3DEX2.cpp @@ -201,6 +201,7 @@ void F3DEX2_DMAIO( u32 w0, u32 w1 ) void F3DEX2_Special_1( u32 w0, u32 w1 ) { + gSPDlistCount(_SHIFTR( w0, 0, 8 ), w1); } void F3DEX2_Special_2( u32 w0, u32 w1 ) diff --git a/RSP.cpp b/RSP.cpp index 5b347f93..6f94962b 100644 --- a/RSP.cpp +++ b/RSP.cpp @@ -121,6 +121,18 @@ LoadLoop: #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() { VI_UpdateSize(); @@ -128,7 +140,7 @@ void RSP_ProcessDList() RSP.PC[0] = *(u32*)&DMEM[0x0FF0]; RSP.PCi = 0; - RSP.count = 0; + RSP.count = -1; RSP.halt = FALSE; RSP.busy = TRUE; @@ -213,6 +225,7 @@ void RSP_ProcessDList() RSP.nextCmd = _SHIFTR( *(u32*)&RDRAM[RSP.PC[RSP.PCi]], 24, 8 ); GBI.cmd[RSP.cmd]( w0, w1 ); + RSP_CheckDLCounter(); } if (config.frameBufferEmulation.copyToRDRAM) diff --git a/RSP.h b/RSP.h index c4a84e3a..795a5222 100644 --- a/RSP.h +++ b/RSP.h @@ -5,7 +5,8 @@ typedef struct { - u32 PC[18], PCi, busy, halt, close, DList, uc_start, uc_dstart, cmd, nextCmd, count; + u32 PC[18], PCi, busy, halt, close, DList, uc_start, uc_dstart, cmd, nextCmd; + s32 count; } RSPInfo; extern RSPInfo RSP; @@ -15,5 +16,6 @@ extern RSPInfo RSP; void RSP_Init(); void RSP_ProcessDList(); void RSP_LoadMatrix( f32 mtx[4][4], u32 address ); +void RSP_CheckDLCounter(); #endif diff --git a/gSP.cpp b/gSP.cpp index b7e9d043..3c93c661 100644 --- a/gSP.cpp +++ b/gSP.cpp @@ -934,6 +934,29 @@ void gSPBranchLessZ( u32 branchdl, u32 vtx, f32 zval ) #endif } +void gSPDlistCount(u32 count, u32 v) +{ + u32 address = RSP_SegmentToPhysical( v ); + if (address == 0 || (address + 8) > RDRAMSize) { + DebugMsg( DEBUG_HIGH | DEBUG_ERROR, "// Attempting to branch to display list at invalid address\n" ); + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gSPDlistCnt(%d, 0x%08X );\n", count, v ); + return; + } + + if (RSP.PCi >= 9) { + DebugMsg( DEBUG_HIGH | DEBUG_ERROR, "// ** DL stack overflow **\n" ); + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gSPDlistCnt(%d, 0x%08X );\n", count, v ); + return; + } + + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gSPDlistCnt(%d, 0x%08X );\n", count, v ); + + ++RSP.PCi; // go to the next PC in the stack + RSP.PC[RSP.PCi] = address; // jump to the address + RSP.nextCmd = _SHIFTR( *(u32*)&RDRAM[address], 24, 8 ); + RSP.count = count + 1; +} + void gSPSetDMAOffsets( u32 mtxoffset, u32 vtxoffset ) { gSP.DMAOffsets.mtx = mtxoffset; diff --git a/gSP.h b/gSP.h index b5e6105f..77a89bbb 100644 --- a/gSP.h +++ b/gSP.h @@ -166,6 +166,7 @@ void gSPDisplayList( u32 dl ); void gSPDMADisplayList( u32 dl, u32 n ); void gSPBranchList( u32 dl ); void gSPBranchLessZ( u32 branchdl, u32 vtx, f32 zval ); +void gSPDlistCount(u32 count, u32 v); void gSPSprite2DBase( u32 base ); void gSPDMATriangles( u32 tris, u32 n ); void gSP1Quadrangle( s32 v0, s32 v1, s32 v2, s32 v3 );