EE: Implement Instant DMA hack for some cache problematic games

Bump savestate version for new dma stall flag

[SAVEVERSION+]
This commit is contained in:
refractionpcsx2 2022-11-06 18:48:35 +00:00
parent b8c7ac4529
commit 5321ca913e
18 changed files with 113 additions and 15 deletions

View File

@ -28,6 +28,7 @@ allowed_game_fixes = [
"SkipMPEGHack",
"OPHFlagHack",
"EETimingHack",
"InstantDMAHack",
"DMABusyHack",
"GIFFIFOHack",
"VIFFIFOHack",

View File

@ -10650,6 +10650,8 @@ SLES-50713:
SLES-50714:
name: "Defender"
region: "PAL-M5"
gameFixes:
- InstantDMAHack # Fixes bad UI positioning.
SLES-50715:
name: "Gravity Games Bike Street - Vertical Dirt"
region: "PAL-M5"
@ -25006,6 +25008,8 @@ SLPM-62285:
SLPM-62287:
name: "Fire Pro Wrestling Z [Limited Edition]"
region: "NTSC-J"
gameFixes:
- InstantDMAHack # Fixes bad ring/UI textures.
SLPM-62288:
name: "pop'n music Best Hits!"
region: "NTSC-J"
@ -25148,6 +25152,8 @@ SLPM-62342:
name: "Fire Pro Wrestling Z"
region: "NTSC-J"
compat: 5
gameFixes:
- InstantDMAHack # Fixes bad ring/UI textures.
SLPM-62343:
name: "Simple 2000 Series Vol. 34 - The Renai Horror Adventure - Hyouryuu Shoujo"
region: "NTSC-J"
@ -39973,6 +39979,8 @@ SLUS-20191:
name: "Defender"
region: "NTSC-U"
compat: 5
gameFixes:
- InstantDMAHack # Fixes bad UI positioning.
SLUS-20194:
name: "Grandia II"
region: "NTSC-U"

View File

@ -38,6 +38,7 @@ GameFixSettingsWidget::GameFixSettingsWidget(SettingsDialog* dialog, QWidget* pa
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.SkipMPEGHack, "EmuCore/Gamefixes", "SkipMPEGHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.OPHFlagHack, "EmuCore/Gamefixes", "OPHFlagHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.EETimingHack, "EmuCore/Gamefixes", "EETimingHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.InstantDMAHack, "EmuCore/Gamefixes", "InstantDMAHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.DMABusyHack, "EmuCore/Gamefixes", "DMABusyHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.GIFFIFOHack, "EmuCore/Gamefixes", "GIFFIFOHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.VIFFIFOHack, "EmuCore/Gamefixes", "VIFFIFOHack", false);

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>648</width>
<height>481</height>
<width>676</width>
<height>535</height>
</rect>
</property>
<property name="windowTitle">
@ -71,6 +71,13 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="InstantDMAHack">
<property name="text">
<string>Instant DMA Hack (Good for cache emulation problems)</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="OPHFlagHack">
<property name="text">

View File

@ -35,6 +35,7 @@ enum GamefixId
Fix_SkipMpeg,
Fix_OPHFlag,
Fix_EETiming,
Fix_InstantDMA,
Fix_DMABusy,
Fix_GIFFIFO,
Fix_VIFFIFO,
@ -836,6 +837,7 @@ struct Pcsx2Config
SkipMPEGHack : 1, // Skips MPEG videos (Katamari and other games need this)
OPHFlagHack : 1, // Bleach Blade Battlers
EETimingHack : 1, // General purpose timing hack.
InstantDMAHack : 1, // Instantly complete DMA's if possible, good for cache emulation problems.
DMABusyHack : 1, // Denies writes to the DMAC when it's busy. This is correct behaviour but bad timing can cause problems.
GIFFIFOHack : 1, // Enabled the GIF FIFO (more correct but slower)
VIFFIFOHack : 1, // Pretends to fill the non-existant VIF FIFO Buffer.
@ -1153,6 +1155,7 @@ namespace EmuFolders
#define CHECK_FPUNEGDIVHACK (EmuConfig.Gamefixes.FpuNegDivHack) // Special Fix for Gundam games messed up camera-view.
#define CHECK_XGKICKHACK (EmuConfig.Gamefixes.XgKickHack) // Special Fix for Erementar Gerad, adds more delay to VU XGkick instructions. Corrects the color of some graphics.
#define CHECK_EETIMINGHACK (EmuConfig.Gamefixes.EETimingHack) // Fix all scheduled events to happen in 1 cycle.
#define CHECK_INSTANTDMAHACK (EmuConfig.Gamefixes.InstantDMAHack) // Attempt to finish DMA's instantly, useful for games which rely on cache emulation.
#define CHECK_SKIPMPEGHACK (EmuConfig.Gamefixes.SkipMPEGHack) // Finds sceMpegIsEnd pattern to tell the game the mpeg is finished (Katamari and a lot of games need this)
#define CHECK_OPHFLAGHACK (EmuConfig.Gamefixes.OPHFlagHack) // Bleach Blade Battlers
#define CHECK_DMABUSYHACK (EmuConfig.Gamefixes.DMABusyHack) // Denies writes to the DMAC when it's busy. This is correct behaviour but bad timing can cause problems.

View File

@ -3844,6 +3844,9 @@ void FullscreenUI::DrawGameFixesSettingsPage()
DrawToggleSetting(bsi, "EE Timing Hack",
"Known to affect following games: Digital Devil Saga (Fixes FMV and crashes), SSX (Fixes bad graphics and crashes).",
"EmuCore/Gamefixes", "EETimingHack", false);
DrawToggleSetting(bsi, "Instant DMA Hack",
"Known to affect following games: Fire Pro Wrestling Z (Bad ring graphics).",
"EmuCore/Gamefixes", "InstantDMAHack", false);
DrawToggleSetting(bsi, "Handle DMAC writes when it is busy.",
"Known to affect following games: Mana Khemia 1 (Going \"off campus\"), Metal Saga (Intro FMV), Pilot Down Behind Enemy Lines.",
"EmuCore/Gamefixes", "DMABusyHack", false);

View File

@ -250,6 +250,7 @@ __fi void gifInterrupt()
{
GifDMAInt(16);
}
CPU_SET_DMASTALL(DMAC_GIF, gifUnit.Path3Masked() || !gifUnit.CanDoPath3());
return;
}
}
@ -265,6 +266,7 @@ __fi void gifInterrupt()
{
GIF_LOG("Path 3 Paused");
GifDMAInt(128);
CPU_SET_DMASTALL(DMAC_GIF, true);
if (gif_fifo.fifoSize == 16)
return;
}
@ -282,7 +284,10 @@ __fi void gifInterrupt()
// If we just read from the fifo, we want to loop and not read more DMA
// If there is no DMA data waiting and the DMA is active, let the DMA progress until there is
if ((!CheckPaths() && gif_fifo.fifoSize == 16) || readSize)
{
CPU_SET_DMASTALL(DMAC_GIF, gifUnit.Path3Masked() || !gifUnit.CanDoPath3());
return;
}
}
if (!(gifch.chcr.STR))
@ -295,6 +300,7 @@ __fi void gifInterrupt()
Console.Warning("gs dma masked, re-scheduling...");
// Re-raise the int shortly in the future
GifDMAInt(64);
CPU_SET_DMASTALL(DMAC_GIF, true);
return;
}
GIFdma();
@ -459,6 +465,7 @@ void GIFdma()
hwDmacIrq(DMAC_STALL_SIS);
GifDMAInt(128);
gif.gscycles = 0;
CPU_SET_DMASTALL(DMAC_GIF, true);
return;
}
}
@ -474,6 +481,7 @@ void GIFdma()
if (gifch.qwc > 0) // Normal Mode
{
GIFchain(); // Transfers the data set by the switch
CPU_SET_DMASTALL(DMAC_GIF, gifUnit.Path3Masked() || !gifUnit.CanDoPath3());
return;
}
}
@ -487,7 +495,7 @@ void dmaGIF()
// 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 :)
CPU_SET_DMASTALL(DMAC_GIF, false);
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;
@ -722,6 +730,7 @@ void gifMFIFOInterrupt()
{ // GIF not in MFIFO anymore, come out.
DevCon.WriteLn("GIF Leaving MFIFO - Report if any errors");
gifInterrupt();
CPU_SET_DMASTALL(DMAC_GIF, true);
return;
}
@ -742,6 +751,7 @@ void gifMFIFOInterrupt()
{
GifDMAInt(16);
}
CPU_SET_DMASTALL(DMAC_GIF, gifUnit.Path3Masked() || !gifUnit.CanDoPath3());
return;
}
}
@ -749,6 +759,7 @@ void gifMFIFOInterrupt()
if (gifUnit.gsSIGNAL.queued)
{
GifDMAInt(128);
CPU_SET_DMASTALL(DMAC_GIF, true);
return;
}
@ -765,7 +776,10 @@ void gifMFIFOInterrupt()
// If we just read from the fifo, we want to loop and not read more DMA
// If there is no DMA data waiting and the DMA is active, let the DMA progress until there is
if ((!CheckPaths() && gif_fifo.fifoSize == 16) || readSize)
{
CPU_SET_DMASTALL(DMAC_GIF, gifUnit.Path3Masked() || !gifUnit.CanDoPath3());
return;
}
}
if (!gifch.chcr.STR)
@ -777,12 +791,16 @@ void gifMFIFOInterrupt()
FireMFIFOEmpty();
if (gifch.qwc > 0 || !gif.gspath3done)
{
CPU_SET_DMASTALL(DMAC_GIF, true);
return;
}
}
if (gifch.qwc > 0 || !gif.gspath3done)
{
mfifoGIFtransfer();
CPU_SET_DMASTALL(DMAC_GIF, gifUnit.Path3Masked() || !gifUnit.CanDoPath3());
return;
}
@ -793,7 +811,7 @@ void gifMFIFOInterrupt()
gifRegs.stat.FQC = gif_fifo.fifoSize;
CalculateFIFOCSR();
hwDmacIrq(DMAC_GIF);
CPU_SET_DMASTALL(DMAC_GIF, false);
if (gif_fifo.fifoSize)
GifDMAInt(8 * BIAS);
DMA_LOG("GIF MFIFO DMA End");

View File

@ -74,6 +74,7 @@ void IPU1dma()
//if we don't, we risk causing the data to go out of sync with the fifo and we end up losing some!
//This is true for Dragons Quest 8 and probably others which suspend the DMA.
DevCon.Warning("IPU1 running when IPU1 DMA disabled! CHCR %x QWC %x", ipu1ch.chcr._u32, ipu1ch.qwc);
CPU_SET_DMASTALL(DMAC_TO_IPU, true);
return;
}
@ -81,6 +82,7 @@ void IPU1dma()
{
// IPU isn't expecting any data, so put it in to wait mode.
cpuRegs.eCycle[4] = 0x9999;
CPU_SET_DMASTALL(DMAC_TO_IPU, true);
return;
}
@ -133,6 +135,7 @@ void IPU1dma()
if (!(IPU1Status.DMAFinished && !IPU1Status.InProgress))
{
cpuRegs.eCycle[4] = 0x9999;//IPU_INT_TO(2048);
CPU_SET_DMASTALL(DMAC_TO_IPU, true);
}
else
{
@ -156,6 +159,7 @@ void IPU0dma()
{
if(!CommandExecuteQueued)
IPUProcessInterrupt();
CPU_SET_DMASTALL(DMAC_FROM_IPU, true);
return;
}
@ -194,6 +198,7 @@ void IPU0dma()
if (ipuRegs.ctrl.BUSY && !CommandExecuteQueued)
{
CommandExecuteQueued = true;
CPU_SET_DMASTALL(DMAC_FROM_IPU, true);
CPU_INT(IPU_PROCESS, 4);
}
}
@ -205,6 +210,7 @@ __fi void dmaIPU0() // fromIPU
if (dmacRegs.ctrl.STS == STS_fromIPU) // STS == fromIPU - Initial settings
dmacRegs.stadr.ADDR = ipu0ch.madr;
CPU_SET_DMASTALL(DMAC_FROM_IPU, false);
// Note: This should probably be a very small value, however anything lower than this will break Mana Khemia
// This is because the game sends bad DMA information, starts an IDEC, then sets it to the correct values
// but because our IPU is too quick, it messes up the sync between the DMA and IPU.
@ -230,6 +236,7 @@ __fi void dmaIPU0() // fromIPU
__fi void dmaIPU1() // toIPU
{
IPU_LOG("IPU1DMAStart QWC %x, MADR %x, CHCR %x, TADR %x", ipu1ch.qwc, ipu1ch.madr, ipu1ch.chcr._u32, ipu1ch.tadr);
CPU_SET_DMASTALL(DMAC_TO_IPU, false);
if (ipu1ch.chcr.MOD == CHAIN_MODE) //Chain Mode
{
@ -289,6 +296,7 @@ void ipu0Interrupt()
ipu0ch.chcr.STR = false;
hwDmacIrq(DMAC_FROM_IPU);
CPU_SET_DMASTALL(DMAC_FROM_IPU, false);
DMA_LOG("IPU0 DMA End");
}
@ -305,4 +313,5 @@ __fi void ipu1Interrupt()
DMA_LOG("IPU1 DMA End");
ipu1ch.chcr.STR = false;
hwDmacIrq(DMAC_TO_IPU);
CPU_SET_DMASTALL(DMAC_TO_IPU, false);
}

View File

@ -858,6 +858,7 @@ static const char* const tbl_GamefixNames[] =
"SkipMPEG",
"OPHFlag",
"EETiming",
"InstantDMA",
"DMABusy",
"GIFFIFO",
"VIFFIFO",
@ -897,6 +898,7 @@ void Pcsx2Config::GamefixOptions::Set(GamefixId id, bool enabled)
case Fix_FpuNegDiv: FpuNegDivHack = enabled; break;
case Fix_XGKick: XgKickHack = enabled; break;
case Fix_EETiming: EETimingHack = enabled; break;
case Fix_InstantDMA: InstantDMAHack = enabled; break;
case Fix_SoftwareRendererFMV: SoftwareRendererFMVHack = enabled; break;
case Fix_SkipMpeg: SkipMPEGHack = enabled; break;
case Fix_OPHFlag: OPHFlagHack = enabled; break;
@ -923,6 +925,7 @@ bool Pcsx2Config::GamefixOptions::Get(GamefixId id) const
case Fix_FpuNegDiv: return FpuNegDivHack;
case Fix_XGKick: return XgKickHack;
case Fix_EETiming: return EETimingHack;
case Fix_InstantDMA: return InstantDMAHack;
case Fix_SoftwareRendererFMV: return SoftwareRendererFMVHack;
case Fix_SkipMpeg: return SkipMPEGHack;
case Fix_OPHFlag: return OPHFlagHack;
@ -949,6 +952,7 @@ void Pcsx2Config::GamefixOptions::LoadSave(SettingsWrapper& wrap)
SettingsWrapBitBool(FpuNegDivHack);
SettingsWrapBitBool(XgKickHack);
SettingsWrapBitBool(EETimingHack);
SettingsWrapBitBool(InstantDMAHack);
SettingsWrapBitBool(SoftwareRendererFMVHack);
SettingsWrapBitBool(SkipMPEGHack);
SettingsWrapBitBool(OPHFlagHack);

View File

@ -281,13 +281,14 @@ __fi void cpuClearInt( uint i )
{
pxAssume( i < 32 );
cpuRegs.interrupt &= ~(1 << i);
cpuRegs.dmastall &= ~(1 << i);
}
static __fi void TESTINT( u8 n, void (*callback)() )
{
if( !(cpuRegs.interrupt & (1 << n)) ) return;
if(!g_GameStarted || cpuTestCycle( cpuRegs.sCycle[n], cpuRegs.eCycle[n] ) )
if(!g_GameStarted || CHECK_INSTANTDMAHACK || cpuTestCycle( cpuRegs.sCycle[n], cpuRegs.eCycle[n] ) )
{
cpuClearInt( n );
callback();
@ -298,12 +299,13 @@ static __fi void TESTINT( u8 n, void (*callback)() )
// [TODO] move this function to Dmac.cpp, and remove most of the DMAC-related headers from
// being included into R5900.cpp.
static __fi void _cpuTestInterrupts()
static __fi bool _cpuTestInterrupts()
{
if (!dmacRegs.ctrl.DMAE || (psHu8(DMAC_ENABLER+2) & 1))
{
//Console.Write("DMAC Disabled or suspended");
return;
return false;
}
/* These are 'pcsx2 interrupts', they handle asynchronous stuff
that depends on the cycle timings */
@ -335,6 +337,11 @@ static __fi void _cpuTestInterrupts()
TESTINT(VIF_VU0_FINISH, vif0VUFinish);
TESTINT(VIF_VU1_FINISH, vif1VUFinish);
}
if ((cpuRegs.interrupt & 0x1FFFF) & ~cpuRegs.dmastall)
return true;
else
return false;
}
static __fi void _cpuTestTIMR()
@ -420,10 +427,10 @@ __fi void _cpuEventTest_Shared()
// where a DMA buffer is overwritten without waiting for the transfer to end, which causes the fonts to get all messed up
// so to fix it, we run all the DMA's instantly when in the BIOS.
// Only use the lower 17 bits of the cpuRegs.interrupt as the upper bits are for VU0/1 sync which can't be done in a tight loop
if (!g_GameStarted && dmacRegs.ctrl.DMAE && !(psHu8(DMAC_ENABLER + 2) & 1) && (cpuRegs.interrupt & 0x1FFFF))
if ((!g_GameStarted || CHECK_INSTANTDMAHACK) && dmacRegs.ctrl.DMAE && !(psHu8(DMAC_ENABLER + 2) & 1) && (cpuRegs.interrupt & 0x1FFFF))
{
while(cpuRegs.interrupt & 0x1FFFF)
_cpuTestInterrupts();
while((cpuRegs.interrupt & 0x1FFFF) && _cpuTestInterrupts())
;
}
else
_cpuTestInterrupts();
@ -531,6 +538,14 @@ __fi void cpuTestHwInts() {
cpuTestTIMRInts();
}
__fi void CPU_SET_DMASTALL(EE_EventType n, bool set)
{
if (set)
cpuRegs.dmastall |= 1 << n;
else
cpuRegs.dmastall &= ~(1 << n);
}
__fi void CPU_INT( EE_EventType n, s32 ecycle)
{
// EE events happen 8 cycles in the future instead of whatever was requested.

View File

@ -174,6 +174,7 @@ struct cpuRegisters {
int branch;
int opmode; // operating mode
u32 tempcycles;
u32 dmastall;
};
// used for optimization
@ -417,6 +418,7 @@ enum EE_EventType
};
extern void CPU_INT( EE_EventType n, s32 ecycle );
extern void CPU_SET_DMASTALL(EE_EventType n, bool set);
extern uint intcInterrupt();
extern uint dmacInterrupt();

View File

@ -33,7 +33,7 @@ enum class FreezeAction
// [SAVEVERSION+]
// This informs the auto updater that the users savestates will be invalidated.
static const u32 g_SaveVersion = (0x9A2E << 16) | 0x0000;
static const u32 g_SaveVersion = (0x9A2F << 16) | 0x0000;
// the freezing data between submodules and core

View File

@ -167,7 +167,7 @@ static __fi void EndEE()
SIF_LOG("SIF0 EE: cycles = 0");
sif0.ee.cycles = 1;
}
CPU_SET_DMASTALL(DMAC_SIF0, false);
CPU_INT(DMAC_SIF0, sif0.ee.cycles*BIAS);
}
@ -377,6 +377,7 @@ __fi void dmaSIF0()
// (as it should always be at the beginning of a DMA). using "if iop is busy" flags breaks Tom Clancy Rainbow Six.
// Legend of Legaia doesn't throw a warning either :)
sif0.ee.end = false;
CPU_SET_DMASTALL(DMAC_SIF0, false);
SIF0Dma();
}

View File

@ -154,7 +154,7 @@ static __fi void EndEE()
sif1.ee.cycles = 1;
}
CPU_SET_DMASTALL(DMAC_SIF1, false);
CPU_INT(DMAC_SIF1, /*std::min((int)(*/sif1.ee.cycles*BIAS/*), 384)*/);
}
@ -225,6 +225,7 @@ static __fi void HandleEETransfer()
{
hwDmacIrq(DMAC_STALL_SIS);
sif1_dma_stall = true;
CPU_SET_DMASTALL(DMAC_SIF1, true);
return;
}
}
@ -341,7 +342,7 @@ __fi void dmaSIF1()
psHu32(SBUS_F240) |= 0x4000;
sif1.ee.busy = true;
CPU_SET_DMASTALL(DMAC_SIF1, false);
// Okay, this here is needed currently (r3644).
// FFX battles in the thunder plains map die otherwise, Phantasy Star 4 as well
// These 2 games could be made playable again by increasing the time the EE or the IOP run,

View File

@ -139,6 +139,7 @@ __fi void vif0VUFinish()
if (VU0.VI[REG_VPU_STAT].UL & 0x5)
{
CPU_INT(VIF_VU0_FINISH, 128);
CPU_SET_DMASTALL(VIF_VU0_FINISH, true);
return;
}
@ -150,6 +151,7 @@ __fi void vif0VUFinish()
_cycles = VU0.cycle - _cycles;
//DevCon.Warning("Finishing VU0 %d cycles", _cycles);
CPU_INT(VIF_VU0_FINISH, _cycles * BIAS);
CPU_SET_DMASTALL(VIF_VU0_FINISH, true);
return;
}
vif0Regs.stat.VEW = false;
@ -177,6 +179,7 @@ __fi void vif0Interrupt()
if(vif0.waitforvu)
{
CPU_INT(VIF_VU0_FINISH, 16);
CPU_SET_DMASTALL(DMAC_VIF0, true);
return;
}
if (vif0Regs.stat.VGW)
@ -208,6 +211,7 @@ __fi void vif0Interrupt()
{
vif0Regs.stat.VPS = VPS_DECODING; //If there's more data you need to say it's decoding the next VIF CMD (Onimusha - Blade Warriors)
VIF_LOG("VIF0 Stalled");
CPU_SET_DMASTALL(DMAC_VIF0, true);
return;
}
}
@ -266,6 +270,7 @@ __fi void vif0Interrupt()
if(vif0.queued_program) vifExecQueue(0);
g_vif0Cycles = 0;
hwDmacIrq(DMAC_VIF0);
CPU_SET_DMASTALL(DMAC_VIF0, false);
vif0Regs.stat.FQC = 0;
DMA_LOG("VIF0 DMA End");
}
@ -278,6 +283,7 @@ void dmaVIF0()
vif0ch.tadr, vif0ch.asr0, vif0ch.asr1);
g_vif0Cycles = 0;
CPU_SET_DMASTALL(DMAC_VIF0, false);
if (vif0ch.qwc > 0) // Normal Mode
{

View File

@ -237,6 +237,7 @@ __fi void vif1VUFinish()
CPU_INT(VIF_VU1_FINISH, cpuGetCycles(VU_MTVU_BUSY));
else
CPU_INT(VIF_VU1_FINISH, 128);
CPU_SET_DMASTALL(VIF_VU1_FINISH, true);
return;
}
@ -249,6 +250,7 @@ __fi void vif1VUFinish()
CPU_INT(VIF_VU1_FINISH, cpuGetCycles(VU_MTVU_BUSY));
else
CPU_INT(VIF_VU1_FINISH, VU1.cycle - _cycles);
CPU_SET_DMASTALL(VIF_VU1_FINISH, true);
return;
}
@ -322,11 +324,15 @@ __fi void vif1Interrupt()
//DevCon.Warning("Waiting on VU1");
//CPU_INT(DMAC_VIF1, 16);
CPU_INT(VIF_VU1_FINISH, std::max(16, cpuGetCycles(VU_MTVU_BUSY)));
CPU_SET_DMASTALL(DMAC_VIF1, true);
return;
}
if (vif1Regs.stat.VGW)
{
CPU_SET_DMASTALL(DMAC_VIF1, true);
return;
}
if (!vif1ch.chcr.STR)
Console.WriteLn("Vif1 running when CHCR == %x", vif1ch.chcr._u32);
@ -357,6 +363,7 @@ __fi void vif1Interrupt()
{
vif1Regs.stat.VPS = VPS_DECODING; //If there's more data you need to say it's decoding the next VIF CMD (Onimusha - Blade Warriors)
VIF_LOG("VIF1 Stalled");
CPU_SET_DMASTALL(DMAC_VIF1, true);
return;
}
}
@ -429,6 +436,7 @@ __fi void vif1Interrupt()
{
DevCon.WriteLn("VIF1 looping on stall at end\n");
CPU_INT(DMAC_VIF1, 0);
CPU_SET_DMASTALL(DMAC_VIF1, true);
return; //Dont want to end if vif is stalled.
}
#ifdef PCSX2_DEVBUILD
@ -455,6 +463,7 @@ __fi void vif1Interrupt()
g_vif1Cycles = 0;
VIF_LOG("VIF1 DMA End");
hwDmacIrq(DMAC_VIF1);
CPU_SET_DMASTALL(DMAC_VIF1, false);
}
void dmaVIF1()
@ -466,6 +475,7 @@ void dmaVIF1()
g_vif1Cycles = 0;
vif1.inprogress = 0;
CPU_SET_DMASTALL(DMAC_VIF1, false);
if (vif1ch.qwc > 0) // Normal Mode
{

View File

@ -300,6 +300,7 @@ void vifMFIFOInterrupt()
{
GUNIT_WARN("vifMFIFOInterrupt() - Waiting for Path 2 to be ready");
CPU_INT(DMAC_MFIFO_VIF, 128);
CPU_SET_DMASTALL(DMAC_VIF1, true);
return;
}
}
@ -307,6 +308,7 @@ void vifMFIFOInterrupt()
{
//DevCon.Warning("Waiting on VU1 MFIFO");
CPU_INT(VIF_VU1_FINISH, std::max(16, cpuGetCycles(VU_MTVU_BUSY)));
CPU_SET_DMASTALL(DMAC_VIF1, true);
return;
}
@ -339,6 +341,7 @@ void vifMFIFOInterrupt()
{
vif1Regs.stat.VPS = VPS_DECODING; //If there's more data you need to say it's decoding the next VIF CMD (Onimusha - Blade Warriors)
VIF_LOG("VIF1 MFIFO Stalled");
CPU_SET_DMASTALL(DMAC_VIF1, true);
return;
}
}
@ -358,6 +361,7 @@ void vifMFIFOInterrupt()
if (vif1.inprogress & 0x10)
{
FireMFIFOEmpty();
CPU_SET_DMASTALL(DMAC_VIF1, true);
return;
}
@ -408,6 +412,6 @@ void vifMFIFOInterrupt()
vif1ch.chcr.STR = false;
hwDmacIrq(DMAC_VIF1);
DMA_LOG("VIF1 MFIFO DMA End");
CPU_SET_DMASTALL(DMAC_VIF1, false);
vif1Regs.stat.FQC = 0;
}

View File

@ -66,6 +66,11 @@ Panels::GameFixesPanel::GameFixesPanel( wxWindow* parent )
pxEt(L"Known to affect following games:\n * Digital Devil Saga (Fixes FMV and crashes)\n * SSX (Fixes bad graphics and crashes)\n * Resident Evil: Dead Aim (Causes garbled textures)"
)
},
{
_("Instant DMA hack. Try if all else fails."),
pxEt(L"Known to affect following games:\n * Fire Pro Wrestling Z (Bad ring graphics)"
)
},
{
_("Handle DMAC writes when it is busy."),
pxEt( L"Known to affect following games:\n * Mana Khemia 1 (Going \"off campus\"), Metal Saga (Intro FMV), Pilot Down Behind Enemy Lines\n"