diff --git a/bin/GameIndex.yaml b/bin/GameIndex.yaml index 477bdc2c1ec0e..acf1af929a168 100644 --- a/bin/GameIndex.yaml +++ b/bin/GameIndex.yaml @@ -31,8 +31,6 @@ GUST-00009: region: "NTSC-J" roundModes: eeRoundMode: 0 # Fixes jump issue. - gameFixes: - - GIFFIFOHack # Fixes flickering sprites. PAPX-90203: name: "Gran Turismo 2000 [Trial]" region: "NTSC-J" @@ -2210,8 +2208,6 @@ SCES-50928: region: "PAL-M6" clampModes: vuClampMode: 2 # Fixes bad shadows. - gameFixes: - - GIFFIFOHack # Resolves random sprite/HUD corruption. SCES-50934: name: "WRC II Extreme" region: "PAL-M7" @@ -2419,8 +2415,6 @@ SCES-51618: region: "PAL-M5" clampModes: vuClampMode: 2 # Fixes bad shadows. - gameFixes: - - GIFFIFOHack # Resolves random sprite/HUD corruption. SCES-51635: name: "Brave - The Search for Spirit Dancer" region: "PAL-M5" @@ -3678,8 +3672,6 @@ SCKA-24008: region: "NTSC-K" clampModes: vuClampMode: 2 # Fixes bad shadows. - gameFixes: - - GIFFIFOHack # Resolves random sprite/HUD corruption. SCKA-30001: name: "Gran Turismo 4" region: "NTSC-K" @@ -3997,8 +3989,6 @@ SCPS-15044: region: "NTSC-J" clampModes: vuClampMode: 2 # Fixes bad shadows. - gameFixes: - - GIFFIFOHack # Resolves random sprite/HUD corruption. SCPS-15045: name: "Ka (Mosquito) - Let's Go Hawaiian" region: "NTSC-J" @@ -5077,8 +5067,6 @@ SCUS-97134: compat: 5 clampModes: vuClampMode: 2 # Fixes bad shadows. - gameFixes: - - GIFFIFOHack # Resolves random sprite/HUD corruption. SCUS-97136: name: "NCAA Final Four 2002" region: "NTSC-U" @@ -5314,8 +5302,6 @@ SCUS-97205: region: "NTSC-U" clampModes: vuClampMode: 2 # Fixes bad shadows. - gameFixes: - - GIFFIFOHack # Resolves random sprite/HUD corruption. SCUS-97206: name: "PlayStation Underground Jampack Summer 2002" region: "NTSC-U" @@ -5399,8 +5385,6 @@ SCUS-97230: region: "NTSC-U" clampModes: vuClampMode: 2 # Fixes bad shadows. - gameFixes: - - GIFFIFOHack # Resolves random sprite/HUD corruption. SCUS-97231: name: "Arc the Lad - Twilight of the Spirits" region: "NTSC-U" @@ -8786,13 +8770,9 @@ SLES-51011: SLES-51013: name: "Blade II" region: "PAL-E" - gameFixes: - - GIFFIFOHack # Fixes flickering HUD. (originally was EE Timing Hack but required since r4821) SLES-51014: name: "Blade II" region: "PAL-F" - gameFixes: - - GIFFIFOHack # Fixes flickering HUD. (originally was EE Timing Hack but required since r4821) SLES-51017: name: "Scooby-Doo! and The Night of 100 Frights" region: "PAL-E" @@ -9537,8 +9517,6 @@ SLES-51372: compat: 5 clampModes: vuClampMode: 3 # Fixes minor SPS on characters. - gameFixes: - - GIFFIFOHack SLES-51374: name: "RoboCop" region: "PAL-M5" @@ -10409,8 +10387,6 @@ SLES-51877: SLES-51879: name: "Hot Wheels World Race" region: "PAL-E" - gameFixes: - - GIFFIFOHack SLES-51881: name: "Mercedes Bens World Racing" region: "PAL-F-G" @@ -10649,8 +10625,6 @@ SLES-51989: compat: 5 clampModes: vuClampMode: 3 # Fixes minor SPS on characters. - gameFixes: - - GIFFIFOHack SLES-51991: name: "Dance UK" region: "PAL-E" @@ -10726,8 +10700,6 @@ SLES-52026: compat: 5 clampModes: vuClampMode: 3 # Fixes minor SPS on characters. - gameFixes: - - GIFFIFOHack SLES-52028: name: "Junior Sports Basketball" region: "PAL-M5" @@ -14518,7 +14490,6 @@ SLES-53904: name: "DT Racer" region: "PAL-M5" gameFixes: - - GIFFIFOHack # Fixes corrupted graphics in the menus. - VUKickstartHack # Fixes TLB misses and collision bugs. SLES-53906: name: "50cent - Bulletproof" @@ -14668,8 +14639,6 @@ SLES-53979: SLES-53982: name: "Fight Night Round 3" region: "PAL-E-F" - gameFixes: - - GIFFIFOHack # Fixes corrupt textures. SLES-53984: name: "Ice Age 2 - The Meltdown" region: "PAL-M6" @@ -15533,8 +15502,6 @@ SLES-54396: SLES-54400: name: "SpongeBob SquarePants - Creature from the Krusty Krab" region: "PAL-M7" - gameFixes: - - GIFFIFOHack # Fixes bad graphics. SLES-54402: name: "Need for Speed - Carbon [Collector's Edition]" region: "PAL-F" @@ -16803,8 +16770,6 @@ SLES-54995: name: "Puzzle Quest - Challenge of the Warlords" region: "PAL-M5" compat: 5 - gameFixes: - - GIFFIFOHack # Fixes flickering black and white sprites. SLES-54996: name: "Golden Compass, The" region: "PAL-M5" @@ -17669,8 +17634,6 @@ SLES-55443: compat: 5 roundModes: eeRoundMode: 0 # Fixes jump issue. - gameFixes: - - GIFFIFOHack # Fixes flickering sprites. SLES-55444: name: "Ar tonelico II: Melody of Metafalica" region: "PAL-E" @@ -17876,8 +17839,6 @@ SLES-55576: SLES-55577: name: "DJ Hero" region: "PAL-M5" - gameFixes: - - GIFFIFOHack SLES-55578: name: "Band Hero" region: "PAL-M5" @@ -18908,8 +18869,6 @@ SLPM-20436: SLPM-55005: name: "Mana Khemia 2: Ochita Gakuen to Renkinjutsushi Tachi" region: "NTSC-J" - gameFixes: - - GIFFIFOHack # Fixes flickering sprites. SLPM-55008: name: "Sengoku Basara X" region: "NTSC-J" @@ -18954,8 +18913,6 @@ SLPM-55110: SLPM-55114: name: "Mana Khemia 2: Ochita Gakuen to Renkinjutsushi Tachi" region: "NTSC-J" - gameFixes: - - GIFFIFOHack # Fixes flickering sprites. SLPM-55118: name: "Galaxy Angel II - Eigou Kaiki no Koku [Disc1of2]" region: "NTSC-J" @@ -26303,8 +26260,6 @@ SLPM-66693: SLPM-66694: name: "Spongebob" region: "NTSC-J" - gameFixes: - - GIFFIFOHack # Fixes bad graphics. SLPM-66695: name: "Kono Aozora ni Yakusoku o - Melody of the Sun and Sea" region: "NTSC-J" @@ -33407,8 +33362,6 @@ SLUS-20360: name: "Blade II" region: "NTSC-U" compat: 5 - gameFixes: - - GIFFIFOHack # Fixes flickering HUD. (originally was EE Timing Hack but required since r4821) SLUS-20361: name: "Rally Fusion - Race of Champions" region: "NTSC-U" @@ -34666,8 +34619,6 @@ SLUS-20647: compat: 5 clampModes: vuClampMode: 3 # Fixes minor SPS on characters. - gameFixes: - - GIFFIFOHack SLUS-20648: name: "NBA Jam 2004" region: "NTSC-U" @@ -35018,8 +34969,6 @@ SLUS-20737: name: "Hot Wheels - World Race" region: "NTSC-U" compat: 5 - gameFixes: - - GIFFIFOHack SLUS-20738: name: "Van Helsing" region: "NTSC-U" @@ -36564,7 +36513,6 @@ SLUS-21095: region: "NTSC-U" compat: 5 gameFixes: - - GIFFIFOHack # Fixes corrupted graphics in the menus. - VUKickstartHack # Fixes TLB misses and collision bugs. SLUS-21096: name: "Ape Escape - Pumped & Primed" @@ -37880,8 +37828,6 @@ SLUS-21383: name: "Fight Night - Round 3" region: "NTSC-U" compat: 5 - gameFixes: - - GIFFIFOHack # Fixes corrupt textures. SLUS-21384: name: "Cabela's Alaskan Adventures" region: "NTSC-U" @@ -37917,8 +37863,6 @@ SLUS-21391: name: "SpongeBob SquarePants - Creature from the Krusty Krab" region: "NTSC-U" compat: 5 - gameFixes: - - GIFFIFOHack # Fixes bad graphics. SLUS-21392: name: "Shrek Smash and Crash" region: "NTSC-U" @@ -39083,8 +39027,6 @@ SLUS-21692: name: "Puzzle Quest - Challenge of the Warlords" region: "NTSC-U" compat: 5 - gameFixes: - - GIFFIFOHack # Fixes flickering black and white sprites. SLUS-21693: name: "7 Wonders of the Ancient World" region: "NTSC-U" @@ -39271,8 +39213,6 @@ SLUS-21735: compat: 5 roundModes: eeRoundMode: 0 # Fixes jump issue. - gameFixes: - - GIFFIFOHack # Fixes flickering sprites. SLUS-21736: name: "Wall-E" region: "NTSC-U" @@ -39878,8 +39818,6 @@ SLUS-21890: name: "Mana Khemia 2: Fall Of Alchemy" region: "NTSC-U" compat: 5 - gameFixes: - - GIFFIFOHack # Fixes flickering sprites. SLUS-21891: name: "G-Force" region: "NTSC-U" @@ -39952,8 +39890,6 @@ SLUS-21908: SLUS-21909: name: "DJ Hero" region: "NTSC-U" - gameFixes: - - GIFFIFOHack SLUS-21910: name: "Marvel Super Hero Squad" region: "NTSC-U" diff --git a/pcsx2/FiFo.cpp b/pcsx2/FiFo.cpp index 14b4836fdff7b..39aa782ac60b4 100644 --- a/pcsx2/FiFo.cpp +++ b/pcsx2/FiFo.cpp @@ -125,10 +125,10 @@ void __fastcall WriteFIFO_VIF1(const mem128_t *value) void __fastcall WriteFIFO_GIF(const mem128_t *value) { GUNIT_LOG("WriteFIFO_GIF()"); - if (CHECK_GIFFIFOHACK) { - gif_fifo.write((u32*)value, 1); - - gif_fifo.read(true); + if ((!gifUnit.CanDoPath3() || gif_fifo.fifoSize > 0)) { + //DevCon.Warning("GIF FIFO HW Write"); + gif_fifo.write_fifo((u32*)value, 1); + gif_fifo.read_fifo(); } else { gifUnit.TransferGSPacketData(GIF_TRANS_FIFO, (u8*)value, 16); diff --git a/pcsx2/Gif.cpp b/pcsx2/Gif.cpp index c5d83f1dc56a5..e987ad5d7e97c 100644 --- a/pcsx2/Gif.cpp +++ b/pcsx2/Gif.cpp @@ -57,12 +57,24 @@ static __fi void CalculateFIFOCSR() { } } + +bool CheckPaths() { + // Can't do Path 3, so try dma again later... + if (!gifUnit.CanDoPath3()) { + if (!gifUnit.Path3Masked()) + { + //DevCon.Warning("Path3 stalled APATH %x PSE %x DIR %x Signal %x", gifRegs.stat.APATH, gifRegs.stat.PSE, gifRegs.stat.DIR, gifUnit.gsSIGNAL.queued); + GifDMAInt(128); + } + return false; + } + return true; +} + void GIF_Fifo::init() { - readpos = 0; - writepos = 0; memzero(data); - memzero(readdata); + fifoSize = 0; gifRegs.stat.FQC = 0; CSRreg.FIFO = CSR_FIFO_EMPTY; gif.gifstate = GIF_STATE_READY; @@ -71,73 +83,81 @@ void GIF_Fifo::init() gif.gscycles = 0; gif.prevcycles = 0; gif.mfifocycles = 0; - gif.gifqwc = 0; } -int GIF_Fifo::write(u32* pMem, int size) +int GIF_Fifo::write_fifo(u32* pMem, int size) { - if (gifRegs.stat.FQC == 16) { - //DevCon.Warning("Full"); + if (fifoSize == 16) { + //GIF_LOG("GIF FIFO Full"); return 0; } - int transsize; - int firsttrans = std::min(size, 16 - (int)gifRegs.stat.FQC); - gifRegs.stat.FQC += firsttrans; - transsize = firsttrans; - - - while (transsize-- > 0) - { - CopyQWC(&data[writepos], pMem); - writepos = (writepos + 4) & 63; - pMem += 4; - } - + int transferSize = std::min(size, 16 - (int)fifoSize); + + int writePos = fifoSize * 4; + + GIF_LOG("GIF FIFO Adding %d QW to GIF FIFO at offset %d FIFO now contains %d QW", transferSize, writePos, fifoSize); + + memcpy(&data[writePos], pMem, transferSize * 16); + + fifoSize += transferSize; + gifRegs.stat.FQC = fifoSize; CalculateFIFOCSR(); - return firsttrans; + + return transferSize; } -int GIF_Fifo::read(bool calledFromDMA) +int GIF_Fifo::read_fifo() { - - if (!gifUnit.CanDoPath3() || gifRegs.stat.FQC == 0) + if (!fifoSize || !gifUnit.CanDoPath3()) { - //DevCon.Warning("Path3 not masked"); - if (gifch.chcr.STR == true && !(cpuRegs.interrupt & (1 << DMAC_GIF)) && calledFromDMA == false) { - GifDMAInt(16); + gifRegs.stat.FQC = fifoSize; + CalculateFIFOCSR(); + if (fifoSize) + { + GIF_LOG("GIF FIFO Can't read, GIF paused/busy. Waiting"); + GifDMAInt(128); } - //DevCon.Warning("P3 Masked"); return 0; } - int valueWritePos = 0; - uint sizeRead; - uint fifoSize = gifRegs.stat.FQC; - int oldReadPos = readpos; + int readpos = 0; + int sizeRead = 0; - while (gifRegs.stat.FQC) { - CopyQWC(&readdata[valueWritePos], &data[readpos]); - readpos = (readpos + 4) & 63; - valueWritePos = (valueWritePos + 4) & 63; - gifRegs.stat.FQC--; - } + sizeRead = gifUnit.TransferGSPacketData(GIF_TRANS_DMA, (u8*)&data, fifoSize * 16) / 16; //returns the size actually read - sizeRead = gifUnit.TransferGSPacketData(GIF_TRANS_DMA, (u8*)&readdata[0], fifoSize * 16) / 16; //returns the size actually read + GIF_LOG("GIF FIFO Read %d QW from FIFO Current Size %d", sizeRead, fifoSize); if (sizeRead < fifoSize) { - readpos = (oldReadPos + (sizeRead * 4)) & 63; //if we read less than what was in the fifo, move the read position back - gifRegs.stat.FQC = fifoSize - sizeRead; + if (sizeRead > 0) + { + int copyAmount = fifoSize - sizeRead; + readpos = sizeRead * 4; + + for (int i = 0; i < copyAmount; i++) + CopyQWC(&data[i * 4], &data[readpos + (i * 4)]); + + fifoSize = copyAmount; + + GIF_LOG("GIF FIFO rearranged to now only contain %d QW", fifoSize); + } + else + { + GIF_LOG("GIF FIFO not read"); + } } - - if (calledFromDMA == false) { - GifDMAInt(sizeRead * BIAS); + else + { + GIF_LOG("GIF FIFO now empty"); + fifoSize = 0; } + gifRegs.stat.FQC = fifoSize; CalculateFIFOCSR(); - return gifRegs.stat.FQC; + + return sizeRead; } void incGifChAddr(u32 qwc) { @@ -161,7 +181,7 @@ __fi void gifCheckPathStatus() { } } - //Required for Path3 Masking timing! + // Required for Path3 Masking timing! if (gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_WAIT) gifUnit.gifPath[GIF_PATH_3].state = GIF_PATH_IDLE; } @@ -175,143 +195,132 @@ __fi void gifInterrupt() { if(vif1Regs.stat.VGW) { - //Check if VIF is in a cycle or is currently "idle" waiting for GIF to come back. + // Check if VIF is in a cycle or is currently "idle" waiting for GIF to come back. if(!(cpuRegs.interrupt & (1< 0 || gif.gspath3done == false) { - if (!gifUnit.Path3Masked()) { - GifDMAInt(128); - } - return; - } - } - } } - if (gifUnit.gsSIGNAL.queued) { GIF_LOG("Path 3 Paused"); GifDMAInt(128); - return; + if(gif_fifo.fifoSize == 16) + return; } - gifCheckPathStatus(); - - //Double check as we might have read the fifo as it's ending the DMA - if (gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_IDLE) + // If there's something in the FIFO and we can do PATH3, empty the FIFO. + if (gif_fifo.fifoSize > 0) { - if (vif1Regs.stat.VGW) + const int readSize = gif_fifo.read_fifo(); + + if (readSize) + GifDMAInt(readSize * BIAS); + + gifCheckPathStatus(); + // Double check as we might have read the fifo as it's ending the DMA + if (gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_IDLE) { - //Check if VIF is in a cycle or is currently "idle" waiting for GIF to come back. - if (!(cpuRegs.interrupt & (1 << DMAC_VIF1))) { - CPU_INT(DMAC_VIF1, 1); + if (vif1Regs.stat.VGW) + { + // Check if VIF is in a cycle or is currently "idle" waiting for GIF to come back. + if (!(cpuRegs.interrupt & (1 << DMAC_VIF1))) { + CPU_INT(DMAC_VIF1, 1); + } } } + + if (((gifch.qwc > 0) || (!gif.gspath3done)) && gif_fifo.fifoSize) + return; } - + if (!(gifch.chcr.STR)) return; if ((gifch.qwc > 0) || (!gif.gspath3done)) { if (!dmacRegs.ctrl.DMAE) { Console.Warning("gs dma masked, re-scheduling..."); - // re-raise the int shortly in the future + // Re-raise the int shortly in the future GifDMAInt( 64 ); return; } GIFdma(); - + return; } - - - if (!CHECK_GIFFIFOHACK) - { - gifRegs.stat.FQC = 0; - clearFIFOstuff(false); - } gif.gscycles = 0; gifch.chcr.STR = false; - + gifRegs.stat.FQC = gif_fifo.fifoSize; + CalculateFIFOCSR(); hwDmacIrq(DMAC_GIF); + + if(gif_fifo.fifoSize) + GifDMAInt(8 * BIAS); GIF_LOG("GIF DMA End QWC in fifo %x APATH = %x OPH = %x state = %x", gifRegs.stat.FQC, gifRegs.stat.APATH, gifRegs.stat.OPH, gifUnit.gifPath[GIF_PATH_3].state); } static u32 WRITERING_DMA(u32 *pMem, u32 qwc) { + u32 originalQwc = qwc; + if (gifRegs.stat.IMT) { - //Splitting by 8qw can be really slow, so on bigger packets be less picky. - //Some games like Wallace & Gromit like smaller packets to be split correctly, hopefully with little impact on speed. - //68 works for W&G but 128 is more of a safe point. + // Splitting by 8qw can be really slow, so on bigger packets be less picky. + // Some games like Wallace & Gromit like smaller packets to be split correctly, hopefully with little impact on speed. + // 68 works for W&G but 128 is more of a safe point. if (qwc > 128) qwc = std::min(qwc, 1024u); else qwc = std::min(qwc, 8u); } + uint size; - if (CHECK_GIFFIFOHACK) { - size = gif_fifo.write(pMem, qwc); - } - else { - size = gifUnit.TransferGSPacketData(GIF_TRANS_DMA, (u8*)pMem, qwc * 16) / 16; + + if (CheckPaths() == false || ((qwc < 8 || gif_fifo.fifoSize > 0) && CHECK_GIFFIFOHACK)) + { + if (gif_fifo.fifoSize < 16) + { + size = gif_fifo.write_fifo((u32*)pMem, originalQwc); // Use original QWC here, the intermediate mode is for the GIF unit, not DMA + incGifChAddr(size); + return size; + } + return 4; // Arbitrary value, probably won't schedule a DMA anwyay since the FIFO is full and GIF is paused } + + size = gifUnit.TransferGSPacketData(GIF_TRANS_DMA, (u8*)pMem, qwc * 16) / 16; incGifChAddr(size); return size; } -int _GIFchain() -{ - tDMA_TAG *pMem; +static __fi void GIFchain() { + tDMA_TAG* pMem; pMem = dmaGetAddr(gifch.madr, false); if (pMem == NULL) { - //must increment madr and clear qwc, else it loops + // Must increment madr and clear qwc, else it loops gifch.madr += gifch.qwc * 16; gifch.qwc = 0; Console.Warning("Hackfix - NULL GIFchain"); - return -1; + return; } - return WRITERING_DMA((u32*)pMem, gifch.qwc); -} + int transferred= WRITERING_DMA((u32*)pMem, gifch.qwc); + gif.gscycles += transferred * BIAS; -static __fi void GIFchain() { - // qwc check now done outside this function - // Voodoocycles - // >> 2 so Drakan and Tekken 5 don't mess up in some PATH3 transfer. Cycles to interrupt were getting huge.. - /*if (gifch.qwc)*/ - gif.gscycles+= _GIFchain() * BIAS; /* guessing */ + if (!gifUnit.Path3Masked() || (gif_fifo.fifoSize < 16)) + GifDMAInt(gif.gscycles); } static __fi bool checkTieBit(tDMA_TAG* &ptag) @@ -326,12 +335,12 @@ static __fi bool checkTieBit(tDMA_TAG* &ptag) static __fi tDMA_TAG* ReadTag() { - tDMA_TAG* ptag = dmaGetAddr(gifch.tadr, false); //Set memory pointer to TADR + tDMA_TAG* ptag = dmaGetAddr(gifch.tadr, false); // Set memory pointer to TADR if (!(gifch.transfer("Gif", ptag))) return NULL; - gifch.madr = ptag[1]._u32; //MADR = ADDR field + SPR - gif.gscycles += 2; // Add 1 cycles from the QW read for the tag + gifch.madr = ptag[1]._u32; // MADR = ADDR field + SPR + gif.gscycles += 2; // Add 1 cycles from the QW read for the tag gif.gspath3done = hwDmacSrcChainWithStack(gifch, ptag->ID); return ptag; @@ -339,7 +348,7 @@ static __fi tDMA_TAG* ReadTag() static __fi tDMA_TAG* ReadTag2() { - tDMA_TAG* ptag = dmaGetAddr(gifch.tadr, false); //Set memory pointer to TADR + tDMA_TAG* ptag = dmaGetAddr(gifch.tadr, false); // Set memory pointer to TADR gifch.unsafeTransfer(ptag); gifch.madr = ptag[1]._u32; @@ -348,28 +357,13 @@ static __fi tDMA_TAG* ReadTag2() return ptag; } -bool CheckPaths() { - // Can't do Path 3, so try dma again later... - if (!CHECK_GIFFIFOHACK) { - if (!gifUnit.CanDoPath3()) { - if (!gifUnit.Path3Masked()) - { - GIF_LOG("Path3 stalled"); - GifDMAInt(128); - } - return false; - } - } - return true; -} - void GIFdma() { while (gifch.qwc > 0 || !gif.gspath3done) { tDMA_TAG* ptag; gif.gscycles = gif.prevcycles; - if (gifRegs.ctrl.PSE) { // temporarily stop + if (gifRegs.ctrl.PSE) { // Temporarily stop Console.WriteLn("Gif dma temp paused? (non MFIFO GIF)"); GifDMAInt(16); return; @@ -392,7 +386,9 @@ void GIFdma() if (ptag == NULL) return; //DevCon.Warning("GIF Reading Tag MSK = %x", vif1Regs.mskpath3); GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gifch.qwc, ptag->ID, gifch.madr, gifch.tadr); - if (!CHECK_GIFFIFOHACK)gifRegs.stat.FQC = std::min((u32)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3] + gifRegs.stat.FQC = std::min((u32)0x10, gifch.qwc); + CalculateFIFOCSR(); + if (dmacRegs.ctrl.STD == STD_GIF) { // there are still bugs, need to also check if gifch.madr +16*qwc >= stadr, if not, stall @@ -418,48 +414,28 @@ void GIFdma() Console.WriteLn("GIF DMA Stall in Normal mode not implemented - Report which game to PCSX2 Team"); } - - if (!CHECK_GIFFIFOHACK) { - gifRegs.stat.FQC = std::min((u32)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3] - clearFIFOstuff(true); - } - // Transfer Dn_QWC from Dn_MADR to GIF if (gifch.qwc > 0) // Normal Mode { - if (CheckPaths() == false) return; - - GIFchain(); //Transfers the data set by the switch - //if (gscycles < 8) DevCon.Warning("GSCycles = %d", gscycles); - GifDMAInt(gif.gscycles); + GIFchain(); // Transfers the data set by the switch return; } } - //QWC == 0 && gspath3done == true - End of DMA gif.prevcycles = 0; - //if (gscycles < 8) DevCon.Warning("1 GSCycles = %d", gscycles); GifDMAInt(16); } void dmaGIF() { - //We used to add wait time for the buffer to fill here, fixing some timing problems in path 3 masking - //It takes the time of 24 QW for the BUS to become ready - The Punisher And Streetball - //DevCon.Warning("dmaGIFstart chcr = %lx, madr = %lx, qwc = %lx\n tadr = %lx, asr0 = %lx, asr1 = %lx", gifch.chcr._u32, gifch.madr, gifch.qwc, gifch.tadr, gifch.asr0, gifch.asr1); + // DevCon.Warning("dmaGIFstart chcr = %lx, madr = %lx, qwc = %lx\n tadr = %lx, asr0 = %lx, asr1 = %lx", gifch.chcr._u32, gifch.madr, gifch.qwc, gifch.tadr, gifch.asr0, gifch.asr1); gif.gspath3done = false; // For some reason this doesn't clear? So when the system starts the thread, we will clear it :) - if (!CHECK_GIFFIFOHACK) { - gifRegs.stat.FQC |= 0x10; // hack ;) - clearFIFOstuff(true); - } - - if (gifch.chcr.MOD == NORMAL_MODE) { //Else it really is a normal transfer and we want to quit, else it gets confused with chains + if (gifch.chcr.MOD == NORMAL_MODE) { // Else it really is a normal transfer and we want to quit, else it gets confused with chains gif.gspath3done = true; } - if(gifch.chcr.MOD == CHAIN_MODE && gifch.qwc > 0) { //DevCon.Warning(L"GIF QWC on Chain " + gifch.chcr.desc()); if ((gifch.chcr.tag().ID == TAG_REFE) || (gifch.chcr.tag().ID == TAG_END) || (gifch.chcr.tag().IRQ && gifch.chcr.TIE)) { @@ -475,19 +451,19 @@ static u32 QWCinGIFMFIFO(u32 DrainADDR) u32 ret; SPR_LOG("GIF MFIFO Requesting %x QWC from the MFIFO Base %x, SPR MADR %x Drain %x", gifch.qwc, dmacRegs.rbor.ADDR, spr0ch.madr, DrainADDR); - //Calculate what we have in the fifo. + // Calculate what we have in the fifo. if (DrainADDR <= spr0ch.madr) { - //Drain is below the write position, calculate the difference between them + // Drain is below the write position, calculate the difference between them ret = (spr0ch.madr - DrainADDR) >> 4; } else { u32 limit = dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16; - //Drain is higher than SPR so it has looped round, - //calculate from base to the SPR tag addr and what is left in the top of the ring + // Drain is higher than SPR so it has looped round, + // calculate from base to the SPR tag addr and what is left in the top of the ring ret = ((spr0ch.madr - dmacRegs.rbor.ADDR) + (limit - DrainADDR)) >> 4; } if (ret == 0) - gif.gifstate |= GIF_STATE_EMPTY; + gif.gifstate = GIF_STATE_EMPTY; SPR_LOG("%x Available of the %x requested", ret, gifch.qwc); return ret; @@ -496,9 +472,9 @@ static u32 QWCinGIFMFIFO(u32 DrainADDR) static __fi bool mfifoGIFrbTransfer() { u32 qwc = std::min(QWCinGIFMFIFO(gifch.madr), gifch.qwc); - if (qwc == 0) { - DevCon.Warning("GIF FIFO EMPTY before transfer (how?)"); - } + + if (qwc == 0) // Either gifch.qwc is 0 (shouldn't get here) or the FIFO is empty. + return true; u8* src = (u8*)PSM(gifch.madr); if (src == NULL) return false; @@ -508,84 +484,76 @@ static __fi bool mfifoGIFrbTransfer() u32 firstTransQWC = needWrap ? MFIFOUntilEnd : qwc; u32 transferred; - if (!CHECK_GIFFIFOHACK) - { - transferred = gifUnit.TransferGSPacketData(GIF_TRANS_DMA, src, firstTransQWC * 16) / 16; // First part - } - else - { - transferred = gif_fifo.write((u32*)src, firstTransQWC); - } - - incGifChAddr(transferred); + transferred = WRITERING_DMA((u32*)src, firstTransQWC); // First part gifch.madr = dmacRegs.rbor.ADDR + (gifch.madr & dmacRegs.rbsr.RMSK); gifch.tadr = dmacRegs.rbor.ADDR + (gifch.tadr & dmacRegs.rbsr.RMSK); - if (needWrap && transferred == MFIFOUntilEnd) - { // Need to do second transfer to wrap around + if (needWrap && transferred == MFIFOUntilEnd) + { + // Need to do second transfer to wrap around u32 transferred2; uint secondTransQWC = qwc - MFIFOUntilEnd; src = (u8*)PSM(dmacRegs.rbor.ADDR); if (src == NULL) return false; - if (!CHECK_GIFFIFOHACK) { - transferred2 = gifUnit.TransferGSPacketData(GIF_TRANS_DMA, src, secondTransQWC * 16) / 16; // Second part - } - else { - transferred2 = gif_fifo.write((u32*)src, secondTransQWC); - } + transferred2 = WRITERING_DMA((u32*)src, secondTransQWC); // Second part - incGifChAddr(transferred2); - gif.mfifocycles += (transferred2 + transferred) * 2; // guessing - } - else - { - gif.mfifocycles += transferred * 2; // guessing + gif.mfifocycles += (transferred2 + transferred) * 2; } + else + gif.mfifocycles += transferred * 2; return true; } -static __fi bool mfifoGIFchain() +static __fi void mfifoGIFchain() { - /* Is QWC = 0? if so there is nothing to transfer */ - if (gifch.qwc == 0) return true; + // Is QWC = 0? if so there is nothing to transfer + if (gifch.qwc == 0) + { + gif.mfifocycles += 4; + return; + } if ((gifch.madr & ~dmacRegs.rbsr.RMSK) == dmacRegs.rbor.ADDR) { - bool ret = true; - if (QWCinGIFMFIFO(gifch.madr) == 0) { SPR_LOG("GIF FIFO EMPTY before transfer"); gif.gifstate = GIF_STATE_EMPTY; gif.mfifocycles += 4; - if (CHECK_GIFFIFOHACK) - GifDMAInt(128); - return true; + return; } - if (!mfifoGIFrbTransfer()) ret = false; + if (!mfifoGIFrbTransfer()) + { + gif.mfifocycles += 4; + gifch.qwc = 0; + gif.gspath3done = true; + return; + } - //This ends up being done more often but it's safer :P - //Make sure we wrap the addresses, dont want it being stuck outside the ring when reading from the ring! + // This ends up being done more often but it's safer :P + // Make sure we wrap the addresses, dont want it being stuck outside the ring when reading from the ring! gifch.madr = dmacRegs.rbor.ADDR + (gifch.madr & dmacRegs.rbsr.RMSK); gifch.tadr = gifch.madr; - - return ret; } else { - int mfifoqwc; SPR_LOG("Non-MFIFO Location transfer doing %x Total QWC", gifch.qwc); tDMA_TAG *pMem = dmaGetAddr(gifch.madr, false); - if (pMem == NULL) return false; + if (pMem == NULL) + { + gif.mfifocycles += 4; + gifch.qwc = 0; + gif.gspath3done = true; + return; + } - mfifoqwc = WRITERING_DMA((u32*)pMem, gifch.qwc); - gif.mfifocycles += (mfifoqwc) * 2; /* guessing */ + gif.mfifocycles += WRITERING_DMA((u32*)pMem, gifch.qwc) * 2; } - return true; + return; } static u32 qwctag(u32 mask) { @@ -595,25 +563,25 @@ static u32 qwctag(u32 mask) { void mfifoGifMaskMem(int id) { switch (id) { - //These five transfer data following the tag, need to check its within the buffer (Front Mission 4) + // These five transfer data following the tag, need to check its within the buffer (Front Mission 4) case TAG_CNT: case TAG_NEXT: case TAG_CALL: case TAG_RET: case TAG_END: - if(gifch.madr < dmacRegs.rbor.ADDR) //probably not needed but we will check anyway. + if(gifch.madr < dmacRegs.rbor.ADDR) // Probably not needed but we will check anyway. { SPR_LOG("GIF MFIFO MADR below bottom of ring buffer, wrapping GIF MADR = %x Ring Bottom %x", gifch.madr, dmacRegs.rbor.ADDR); gifch.madr = qwctag(gifch.madr); } else - if(gifch.madr > (dmacRegs.rbor.ADDR + (u32)dmacRegs.rbsr.RMSK)) //Usual scenario is the tag is near the end (Front Mission 4) + if(gifch.madr > (dmacRegs.rbor.ADDR + (u32)dmacRegs.rbsr.RMSK)) // Usual scenario is the tag is near the end (Front Mission 4) { SPR_LOG("GIF MFIFO MADR outside top of ring buffer, wrapping GIF MADR = %x Ring Top %x", gifch.madr, (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK)+16); gifch.madr = qwctag(gifch.madr); } break; default: - //Do nothing as the MADR could be outside + // Do nothing as the MADR could be outside break; } } @@ -622,9 +590,8 @@ void mfifoGIFtransfer() { tDMA_TAG *ptag; gif.mfifocycles = 0; - - if (gifRegs.ctrl.PSE) { // temporarily stop + if (gifRegs.ctrl.PSE) { // Temporarily stop Console.WriteLn("Gif dma temp paused?"); CPU_INT(DMAC_MFIFO_GIF, 16); return; @@ -637,8 +604,6 @@ void mfifoGIFtransfer() SPR_LOG("GIF FIFO EMPTY before tag read"); gif.gifstate = GIF_STATE_EMPTY; GifDMAInt(4); - if (CHECK_GIFFIFOHACK) - GifDMAInt(128); return; } @@ -646,6 +611,9 @@ void mfifoGIFtransfer() gifch.unsafeTransfer(ptag); gifch.madr = ptag[1]._u32; + gifRegs.stat.FQC = std::min((u32)0x10, gifch.qwc); + CalculateFIFOCSR(); + gif.mfifocycles += 2; GIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx mfifo qwc = %x spr0 madr = %x", @@ -667,12 +635,8 @@ void mfifoGIFtransfer() } } - if (!mfifoGIFchain()) { - Console.WriteLn("mfifoGIF dmaChain error size=%d, madr=%lx, tadr=%lx", gifch.qwc, gifch.madr, gifch.tadr); - gif.gspath3done = true; - gifch.qwc = 0; //Sanity - } - + mfifoGIFchain(); + GifDMAInt(std::max(gif.mfifocycles, (u32)4)); SPR_LOG("mfifoGIFtransfer end %x madr %x, tadr %x", gifch.chcr._u32, gifch.madr, gifch.tadr); @@ -680,7 +644,7 @@ void mfifoGIFtransfer() void gifMFIFOInterrupt() { - GIF_LOG("gifMFIFOInterrupt"); + //DevCon.Warning("gifMFIFOInterrupt"); gif.mfifocycles = 0; if (dmacRegs.ctrl.MFD != MFD_GIF) { // GIF not in MFIFO anymore, come out. @@ -695,19 +659,18 @@ void gifMFIFOInterrupt() { if (vif1Regs.stat.VGW) { - //Check if VIF is in a cycle or is currently "idle" waiting for GIF to come back. + // Check if VIF is in a cycle or is currently "idle" waiting for GIF to come back. if (!(cpuRegs.interrupt & (1 << DMAC_VIF1))) CPU_INT(DMAC_VIF1, 1); - //Make sure it loops if the GIF packet is empty to prepare for the next packet - //or end if it was the end of a packet. - //This must trigger after VIF retriggers as VIf might instantly mask Path3 + // Make sure it loops if the GIF packet is empty to prepare for the next packet + // or end if it was the end of a packet. + // This must trigger after VIF retriggers as VIf might instantly mask Path3 if (!gifUnit.Path3Masked() || gifch.qwc == 0) { GifDMAInt(16); } return; } - } if (gifUnit.gsSIGNAL.queued) { @@ -715,40 +678,19 @@ void gifMFIFOInterrupt() return; } - if (CHECK_GIFFIFOHACK) - { - if (int amtRead = gif_fifo.read(true)) - { - if (!gifUnit.Path3Masked() || gifRegs.stat.FQC < 16) { - GifDMAInt(amtRead * BIAS); - return; - } - } - else { - if (!gifUnit.CanDoPath3() && gifRegs.stat.FQC == 16) - { - if (gifch.qwc > 0 || gif.gspath3done == false) { - if (!gifUnit.Path3Masked()) { - GifDMAInt(128); - } - return; - } - } - } - } gifCheckPathStatus(); if (gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_IDLE) { if (vif1Regs.stat.VGW) { - //Check if VIF is in a cycle or is currently "idle" waiting for GIF to come back. + // Check if VIF is in a cycle or is currently "idle" waiting for GIF to come back. if (!(cpuRegs.interrupt & (1 << DMAC_VIF1))) CPU_INT(DMAC_VIF1, 1); - //Make sure it loops if the GIF packet is empty to prepare for the next packet - //or end if it was the end of a packet. - //This must trigger after VIF retriggers as VIf might instantly mask Path3 + // Make sure it loops if the GIF packet is empty to prepare for the next packet + // or end if it was the end of a packet. + // This must trigger after VIF retriggers as VIf might instantly mask Path3 if (!gifUnit.Path3Masked() || gifch.qwc == 0) { GifDMAInt(16); } @@ -756,41 +698,58 @@ void gifMFIFOInterrupt() } } - if (!gifch.chcr.STR) { - Console.WriteLn("WTF GIFMFIFO"); - cpuRegs.interrupt &= ~(1 << 11); - return; + // If there's something in the FIFO and we can do PATH3, empty the FIFO. + if (gif_fifo.fifoSize > 0) + { + const int readSize = gif_fifo.read_fifo(); + + if (readSize) + GifDMAInt(readSize * BIAS); + + gifCheckPathStatus(); + // Double check as we might have read the fifo as it's ending the DMA + if (gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_IDLE) + { + if (vif1Regs.stat.VGW) + { + //Check if VIF is in a cycle or is currently "idle" waiting for GIF to come back. + if (!(cpuRegs.interrupt & (1 << DMAC_VIF1))) { + CPU_INT(DMAC_VIF1, 1); + } + } + } + + if (((gifch.qwc > 0) || (!gif.gspath3done)) && gif_fifo.fifoSize) + return; } - if ((gif.gifstate & GIF_STATE_EMPTY)) { - FireMFIFOEmpty(); - if (CHECK_GIFFIFOHACK) - GifDMAInt(128); + if (!gifch.chcr.STR) return; + + if (spr0ch.madr == gifch.tadr || (gif.gifstate & GIF_STATE_EMPTY)) { + gif.gifstate = GIF_STATE_EMPTY; // In case of madr = tadr we need to set it + FireMFIFOEmpty(); + + if (gifch.qwc > 0 || !gif.gspath3done) + return; } if (gifch.qwc > 0 || !gif.gspath3done) { - if (!CheckPaths()) return; mfifoGIFtransfer(); return; } - if (!CHECK_GIFFIFOHACK) - { - gifRegs.stat.FQC = 0; - clearFIFOstuff(false); - } - - if (spr0ch.madr == gifch.tadr) { - FireMFIFOEmpty(); - } - gif.gscycles = 0; gifch.chcr.STR = false; gif.gifstate = GIF_STATE_READY; + gifRegs.stat.FQC = gif_fifo.fifoSize; + CalculateFIFOCSR(); hwDmacIrq(DMAC_GIF); + + if (gif_fifo.fifoSize) + GifDMAInt(8 * BIAS); DMA_LOG("GIF MFIFO DMA End"); } diff --git a/pcsx2/Gif.h b/pcsx2/Gif.h index 35d81927a2033..0657416f051ea 100644 --- a/pcsx2/Gif.h +++ b/pcsx2/Gif.h @@ -80,11 +80,10 @@ extern __aligned16 gifStruct gif; struct GIF_Fifo { unsigned int data[64]; //16 QW FIFO - unsigned int readdata[64]; //16 QW Inline for reading - int readpos, writepos; + unsigned int fifoSize; - int write(u32* pMem, int size); - int read(bool calledFromDMA = false); + int write_fifo(u32* pMem, int size); + int read_fifo(); void init(); }; diff --git a/pcsx2/Gif_Unit.h b/pcsx2/Gif_Unit.h index e0ebc8f4d6cc5..25653c95826ef 100644 --- a/pcsx2/Gif_Unit.h +++ b/pcsx2/Gif_Unit.h @@ -538,6 +538,7 @@ struct Gif_Unit gifRegs.stat.reset(); gifRegs.ctrl.reset(); gifRegs.mode.reset(); + gif_fifo.init(); } // Adds a finished GS Packet to the MTGS ring buffer diff --git a/pcsx2/Hw.cpp b/pcsx2/Hw.cpp index 6ec0fe1f0d211..a30ca438ea309 100644 --- a/pcsx2/Hw.cpp +++ b/pcsx2/Hw.cpp @@ -216,12 +216,6 @@ __ri void hwMFIFOResume(u32 transferred) { CPU_INT(DMAC_MFIFO_GIF, transferred * BIAS); gif.gifstate = GIF_STATE_READY; } - if (!CHECK_GIFFIFOHACK) - { - gifRegs.stat.FQC = 16; - //GIF FIFO - clearFIFOstuff(true); - } break; } default: diff --git a/pcsx2/HwWrite.cpp b/pcsx2/HwWrite.cpp index 0f2a459fd6b1a..d7c88c15bf8bc 100644 --- a/pcsx2/HwWrite.cpp +++ b/pcsx2/HwWrite.cpp @@ -111,9 +111,8 @@ void __fastcall _hwWrite32( u32 mem, u32 value ) icase(GIF_MODE) { gifRegs.mode.write(value); - //Need to kickstart the GIF if the M3R mask comes off - if (gifRegs.stat.M3R == 1 && gifRegs.mode.M3R == 0 && gifch.chcr.STR) + if (gifRegs.stat.M3R == 1 && gifRegs.mode.M3R == 0 && (gifch.chcr.STR || gif_fifo.fifoSize)) { DevCon.Warning("GIF Mode cancelling P3 Disable"); CPU_INT(DMAC_GIF, 8); diff --git a/pcsx2/SPR.cpp b/pcsx2/SPR.cpp index c568669090fd4..0b516ffe0915e 100644 --- a/pcsx2/SPR.cpp +++ b/pcsx2/SPR.cpp @@ -313,12 +313,13 @@ void SPRFROMinterrupt() spr0ch.madr = dmacRegs.rbor.ADDR + (spr0ch.madr & dmacRegs.rbsr.RMSK); //Console.WriteLn("mfifoGIFtransfer %x madr %x, tadr %x", gif->chcr._u32, gif->madr, gif->tadr); hwMFIFOResume(mfifotransferred); - mfifotransferred = 0; break; } default: break; } + + mfifotransferred = 0; } return; diff --git a/pcsx2/SaveState.h b/pcsx2/SaveState.h index d1c0302bffb1f..5a63fec07d38f 100644 --- a/pcsx2/SaveState.h +++ b/pcsx2/SaveState.h @@ -31,7 +31,7 @@ enum class FreezeAction // the lower 16 bit value. IF the change is breaking of all compatibility with old // states, increment the upper 16 bit value, and clear the lower 16 bits to 0. -static const u32 g_SaveVersion = (0x9A21 << 16) | 0x0000; +static const u32 g_SaveVersion = (0x9A22 << 16) | 0x0000; // the freezing data between submodules and core // an interesting thing to note is that this dates back from before plugin diff --git a/pcsx2/Vif.cpp b/pcsx2/Vif.cpp index a6eebfc8de938..9947993cb7237 100644 --- a/pcsx2/Vif.cpp +++ b/pcsx2/Vif.cpp @@ -222,14 +222,14 @@ __fi void vif1FBRST(u32 value) { case MFD_VIF1: //Console.WriteLn("MFIFO Stall"); //MFIFO active and not empty - if(vif1ch.chcr.STR) CPU_INT(DMAC_MFIFO_VIF, 0); + if(vif1ch.chcr.STR && !vif1Regs.stat.test(VIF1_STAT_FDR)) CPU_INT(DMAC_MFIFO_VIF, 0); break; case NO_MFD: case MFD_RESERVED: case MFD_GIF: // Wonder if this should be with VIF? // Gets the timing right - Flatout - if(vif1ch.chcr.STR) CPU_INT(DMAC_VIF1, 0); + if(vif1ch.chcr.STR && !vif1Regs.stat.test(VIF1_STAT_FDR)) CPU_INT(DMAC_VIF1, 0); break; } @@ -256,6 +256,8 @@ __fi void vif1STAT(u32 value) { //position, as we clear it and set it to the end well before the interrupt, the game assumes it's finished, //then proceeds to reverse the dma before we have even done it ourselves. So lets just make sure VIF is ready :) if (vif1ch.qwc > 0 || isStalled == false){ + vif1ch.qwc = 0; + hwDmacIrq(DMAC_VIF1); vif1ch.chcr.STR = false; cpuRegs.interrupt &= ~((1 << DMAC_VIF1) | (1 << DMAC_MFIFO_VIF)); } diff --git a/pcsx2/Vif1_Dma.cpp b/pcsx2/Vif1_Dma.cpp index dfc5859833c1a..dd2d0248b61ee 100644 --- a/pcsx2/Vif1_Dma.cpp +++ b/pcsx2/Vif1_Dma.cpp @@ -288,7 +288,7 @@ __fi void vif1Interrupt() g_vif1Cycles = 0; - if( gifRegs.stat.APATH == 2 && gifUnit.gifPath[GIF_PATH_2].isDone()) + if( gifRegs.stat.APATH == 2 && gifUnit.gifPath[GIF_PATH_2].isDone()) { gifRegs.stat.APATH = 0; gifRegs.stat.OPH = 0; @@ -427,7 +427,7 @@ __fi void vif1Interrupt() vif1.irqoffset.enabled = false; if(vif1.queued_program) vifExecQueue(1); g_vif1Cycles = 0; - DMA_LOG("VIF1 DMA End"); + VIF_LOG("VIF1 DMA End"); hwDmacIrq(DMAC_VIF1); } diff --git a/pcsx2/Vif_Codes.cpp b/pcsx2/Vif_Codes.cpp index f389fa2c5ed87..fdde320f4d3a9 100644 --- a/pcsx2/Vif_Codes.cpp +++ b/pcsx2/Vif_Codes.cpp @@ -422,14 +422,13 @@ vifOp(vifCode_MSCNT) { // ToDo: FixMe vifOp(vifCode_MskPath3) { vif1Only(); - pass1 { + pass1 { vif1Regs.mskpath3 = (vif1Regs.code >> 15) & 0x1; gifRegs.stat.M3P = (vif1Regs.code >> 15) & 0x1; GUNIT_LOG("Vif1 - MskPath3 [p3 = %s]", vif1Regs.mskpath3 ? "masked" : "enabled"); if(!vif1Regs.mskpath3) { - GUNIT_WARN("Path3 triggering!"); - if(CHECK_GIFFIFOHACK)gif_fifo.read(false); - else gifInterrupt(); + GUNIT_WARN("VIF MSKPATH3 off Path3 triggering!"); + gifInterrupt(); } vif1.cmd = 0; vif1.pass = 0; diff --git a/pcsx2/gui/Panels/GameFixesPanel.cpp b/pcsx2/gui/Panels/GameFixesPanel.cpp index 203dd07c5850c..ce441e61075c6 100644 --- a/pcsx2/gui/Panels/GameFixesPanel.cpp +++ b/pcsx2/gui/Panels/GameFixesPanel.cpp @@ -81,7 +81,7 @@ Panels::GameFixesPanel::GameFixesPanel( wxWindow* parent ) wxEmptyString }, { - _("Enable the GIF FIFO (slower but needed for Hotwheels, Wallace and Gromit, DJ Hero)"), + _("Force GIF PATH3 transfers through FIFO (Fifa Street 2)"), wxEmptyString }, {