diff --git a/bin/GameIndex.yaml b/bin/GameIndex.yaml index 2f3d0dcea0..8527329887 100644 --- a/bin/GameIndex.yaml +++ b/bin/GameIndex.yaml @@ -12071,16 +12071,10 @@ SLES-53098: SLES-53099: name: "Pilot Down - Behind Enemy Lines" region: "PAL-M5" + gameFixes: + - DMABusyHack # Game has weird DMA handling, this allows required DMA's to finish. roundModes: vuRoundMode: 0 - patches: - 53BB63A0: - content: |- - author=kozarovv - // Patch allow sending VU1 mpg successfully. This fix missing graphic. Thanks to PSI for figuring what is wrong. - // Game need at least -2 EE cyclerate + MTVU on my pc to get full speed. - // To fix shadows set VU rounding to nearest - thx Atomic83 - patch=1,EE,00426140,word,00000000 SLES-53100: name: "Scooby Doo! Unmasked" region: "PAL-M4" diff --git a/pcsx2/ps2/LegacyDmac.cpp b/pcsx2/ps2/LegacyDmac.cpp index c2927d7339..ae819cd21b 100644 --- a/pcsx2/ps2/LegacyDmac.cpp +++ b/pcsx2/ps2/LegacyDmac.cpp @@ -316,6 +316,53 @@ __fi u32 dmacRead32( u32 mem ) template< uint page > __fi bool dmacWrite32( u32 mem, mem32_t& value ) { + // DMA Writes are invalid to everything except the STR on CHCR when it is busy + // However this isn't completely confirmed and this might vary depending on if + // using chain or normal modes, DMA's may be handled internally. + // Metal Saga requires the QWC during IPU_FROM to be written but not MADR + // similar happens with Mana Khemia. + // In other cases such as Pilot Down Behind Enemy Lines, it seems to expect the DMA + // to have finished before it writes the new information, otherwise the game breaks. + if (CHECK_DMABUSYHACK && (mem & 0xf0) && mem >= 0x10008000 && mem <= 0x1000E000) + { + if ((psHu32(mem & ~0xff) & 0x100) && dmacRegs.ctrl.DMAE && !psHu8(DMAC_ENABLER + 2)) + { + DevCon.Warning("Gamefix: Write to DMA addr %x while STR is busy!", mem); + while (psHu32(mem & ~0xff) & 0x100) + { + switch ((mem >> 8) & 0xFF) + { + case 0x80: // VIF0 + vif0Interrupt(); + break; + case 0x90: // VIF1 + vif1Interrupt(); + break; + case 0xA0: // GIF + gifInterrupt(); + break; + case 0xB0: // IPUFROM + [[fallthrough]]; + case 0xB4: // IPUTO + if ((mem & 0xff) == 0x20) + goto allow_write; // I'm so sorry + else + return false; + break; + case 0xD0: // SPRFROM + SPRFROMinterrupt(); + break; + case 0xD4: // SPRTO + SPRTOinterrupt(); + break; + default: + return false; + } + } + } + allow_write:; + } + iswitch(mem) { icase(D0_CHCR) // dma0 - vif0 { @@ -579,17 +626,6 @@ __fi bool dmacWrite32( u32 mem, mem32_t& value ) } } - // DMA Writes are invalid to everything except the STR on CHCR when it is busy - // There's timing problems with many games. Gamefix time! - if( CHECK_DMABUSYHACK && (mem & 0xf0) ) - { - if((psHu32(mem & ~0xff) & 0x100) && dmacRegs.ctrl.DMAE && !psHu8(DMAC_ENABLER+2)) - { - DevCon.Warning("Gamefix: Write to DMA addr %x while STR is busy! Ignoring", mem); - return false; - } - } - // fall-through: use the default writeback provided by caller. return true; }