diff --git a/desmume/src/FIFO.cpp b/desmume/src/FIFO.cpp index 4ae6db02b..7bff14f99 100644 --- a/desmume/src/FIFO.cpp +++ b/desmume/src/FIFO.cpp @@ -170,7 +170,11 @@ void GFX_FIFOclear() void GFX_FIFOsend(u8 cmd, u32 param) { - u32 gxstat = (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600) & 0xF000FFFF); + u32 gxstat = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600); + + //INFO("gxFIFO: send 0x%02X = 0x%08X (size %03i/0x%02X) gxstat 0x%08X\n", cmd, param, gxFIFO.size, gxFIFO.size, gxstat); + + gxstat &= 0xF000FFFF; if (gxFIFO.size == 0) // FIFO empty { @@ -192,11 +196,11 @@ void GFX_FIFOsend(u8 cmd, u32 param) } } - //INFO("GFX FIFO: Send GFX 3D cmd 0x%02X to FIFO - 0x%08X (%03i/%02X)\n", cmd, param, gxFIFO.tail, gxFIFO.tail); if (gxFIFO.size > 255) { #ifdef USE_GEOMETRY_FIFO_EMULATION - gxstat |= 0x01000000; + gxstat |= 0x01000000; // full + gxstat |= 0x08000000; // busy #else gxstat |= 0x02000000; // this is hack (must be removed later) #endif @@ -232,7 +236,7 @@ void GFX_FIFOsend(u8 cmd, u32 param) NDS_RescheduleGXFIFO(); } -// this function used ONLY in new gxFIFO +// this function used ONLY in gxFIFO BOOL GFX_PIPErecv(u8 *cmd, u32 *param) { u32 gxstat = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600); @@ -240,7 +244,6 @@ BOOL GFX_PIPErecv(u8 *cmd, u32 *param) if (gxPIPE.size > 0) { - *cmd = gxPIPE.cmd[gxPIPE.head]; *param = gxPIPE.param[gxPIPE.head]; gxPIPE.head++; @@ -282,17 +285,25 @@ BOOL GFX_PIPErecv(u8 *cmd, u32 *param) { gxstat |= 0x02000000; if (gxstat & 0x40000000) // IRQ: less half + { setIF(0, (1<<21)); - execHardware_doAllDma(EDMAMode_GXFifo); + } + execHardware_doAllDma(EDMAMode_GXFifo); } if (gxFIFO.size == 0) // empty + { gxstat |= 0x04000000; + if (gxstat & 0x80000000) // IRQ: empty + setIF(0, (1<<21)); + } } else // FIFO empty { gxstat &= 0xF000FFFF; gxstat |= 0x06000000; + if (gxstat & 0x80000000) // IRQ: empty + setIF(0, (1<<21)); } } @@ -308,19 +319,32 @@ BOOL GFX_PIPErecv(u8 *cmd, u32 *param) return FALSE; } +extern void gfx3d_ClearStack(); void GFX_FIFOcnt(u32 val) { u32 gxstat = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600); - //INFO("GFX FIFO: write context 0x%08X (prev 0x%08X) tail %i\n", val, gxstat, gxFIFO.tail); - if (val & (1<<29)) // clear? (homebrew) + //INFO("gxFIFO: write cnt 0x%08X (prev 0x%08X) FIFO size %03i PIPE size %03i\n", val, gxstat, gxFIFO.size, gxPIPE.size); + + if (val & (1<<29)) // clear? (only in homebrew?) { GFX_PIPEclear(); GFX_FIFOclear(); return; } - T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600, gxstat); - NDS_RescheduleGXFIFO(); + if (val & (1<<15)) // projection stack pointer reset + { + gfx3d_ClearStack(); + val &= 0xFFFF5FFF; // clear reset (bit15) & stack level (bit13) + } + + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600, val); + + if (gxFIFO.size == 0) // empty + { + if (val & 0x80000000) // IRQ: empty + setIF(0, (1<<21)); + } } // ========================================================= DISP FIFO diff --git a/desmume/src/MMU.cpp b/desmume/src/MMU.cpp index 2a711a32b..5ce69b56a 100644 --- a/desmume/src/MMU.cpp +++ b/desmume/src/MMU.cpp @@ -2480,9 +2480,9 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val) return; case 0x04000600: - ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[0x600>>2] = val; GFX_FIFOcnt(val); return; + // Alpha test reference value - Parameters:1 case 0x04000340: { diff --git a/desmume/src/gfx3d.cpp b/desmume/src/gfx3d.cpp index 89c311339..8f1f9a0cc 100644 --- a/desmume/src/gfx3d.cpp +++ b/desmume/src/gfx3d.cpp @@ -1335,6 +1335,12 @@ s32 gfx3d_GetDirectionalMatrix (unsigned int index) return (s32)(mtxCurrent[2][_index]*(1<<12)); } +void gfx3d_ClearStack() +{ + MatrixStackSetStackPosition(&mtxStack[0], -5); + MatrixStackSetStackPosition(&mtxStack[3], -5); +} + void gfx3d_glAlphaFunc(u32 v) { gfx3d.alphaTestRef = v&31; @@ -1669,12 +1675,11 @@ void gfx3d_VBlankEndSignal(bool skipFrame) if (!drawPending) return; drawPending = FALSE; - if(skipFrame) - { - GFX_DELAY(392); - NDS_RescheduleGXFIFO(); - return; - } + + GFX_DELAY(392); + NDS_RescheduleGXFIFO(); + + if(skipFrame) return; //if the null 3d core is chosen, then we need to clear out the 3d buffers to keep old data from being rendered if(gpu3D == &gpu3DNull || !CommonSettings.showGpu.main) { @@ -1683,8 +1688,6 @@ void gfx3d_VBlankEndSignal(bool skipFrame) } gpu3D->NDS_3D_Render(); - GFX_DELAY(392); - NDS_RescheduleGXFIFO(); #else //if we are skipping 3d frames then the 3d rendering will get held up here. //but, as soon as we quit skipping frames, the held-up 3d frame will render @@ -1707,6 +1710,27 @@ void gfx3d_VBlankEndSignal(bool skipFrame) #ifdef USE_GEOMETRY_FIFO_EMULATION //#define _3D_LOG +// http://nocash.emubase.de/gbatek.htm#ds3dvideo +// DS 3D Geometry Commands +// Sending Commands by Ports 4000440h..40005FFh +// +// If the FIFO is full, then a wait is generated until data is removed from the FIFO, +// ie. the STR opcode gets freezed, during the wait, the bus cannot be used even by DMA, +// interrupts, or by the NDS7 CPU. + +// this is a hack +#if 1 +#define CHECKFULL() if (gxFIFO.size > 255) \ + {\ + gfx3d_execute3D();\ + gfx3d_execute3D();\ + gfx3d_execute3D();\ + gfx3d_execute3D();\ + } +#else +#define CHECKFULL() ; +#endif + static void NOPARAMS() { for (;;) @@ -1723,13 +1747,7 @@ static void NOPARAMS() case 0x15: case 0x41: { - if (gxFIFO.size > 255) - { - gfx3d_execute3D(); - gfx3d_execute3D(); - gfx3d_execute3D(); - gfx3d_execute3D(); - } + CHECKFULL(); GFX_FIFOsend(clCmd & 0xFF, 0); clCmd >>= 8; continue; @@ -1751,13 +1769,8 @@ void gfx3d_sendCommandToFIFO(u32 val) #ifdef _3D_LOG INFO("gxFIFO: send 0x%02X: val=0x%08X, pipe %02i, fifo %03i\n", clCmd & 0xFF, val, gxPIPE.tail, gxFIFO.tail); #endif - if (gxFIFO.size > 255) - { - gfx3d_execute3D(); - gfx3d_execute3D(); - gfx3d_execute3D(); - gfx3d_execute3D(); - } + + CHECKFULL(); switch (clCmd & 0xFF) { @@ -1863,13 +1876,8 @@ void gfx3d_sendCommand(u32 cmd, u32 param) #ifdef _3D_LOG INFO("gxFIFO: send 0x%02X: val=0x%08X, pipe %02i, fifo %03i (direct)\n", cmd, param, gxPIPE.tail, gxFIFO.tail); #endif - if (gxFIFO.size > 255) - { - gfx3d_execute3D(); - gfx3d_execute3D(); - gfx3d_execute3D(); - gfx3d_execute3D(); - } + + CHECKFULL(); switch (cmd) { diff --git a/desmume/src/wifi.cpp b/desmume/src/wifi.cpp index be838f524..4402bcdc5 100644 --- a/desmume/src/wifi.cpp +++ b/desmume/src/wifi.cpp @@ -225,7 +225,7 @@ WifiComInterface* wifiCom; // 3: medium logging, for debugging, shows lots of stuff // 4: high logging, for debugging, shows almost everything, may slow down // 5: highest logging, for debugging, shows everything, may slow down a lot -#define WIFI_LOGGING_LEVEL 3 +#define WIFI_LOGGING_LEVEL 0 #define WIFI_LOG_USE_LOGC 0