mirror of https://github.com/PCSX2/pcsx2.git
EE: Implement Instant DMA hack for some cache problematic games
Bump savestate version for new dma stall flag [SAVEVERSION+]
This commit is contained in:
parent
b8c7ac4529
commit
5321ca913e
|
@ -28,6 +28,7 @@ allowed_game_fixes = [
|
|||
"SkipMPEGHack",
|
||||
"OPHFlagHack",
|
||||
"EETimingHack",
|
||||
"InstantDMAHack",
|
||||
"DMABusyHack",
|
||||
"GIFFIFOHack",
|
||||
"VIFFIFOHack",
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue