mirror of https://github.com/PCSX2/pcsx2.git
-Rewrote the DMA checking functions as per the manual specs so certain situations can alter the DMA's while busy.
-Improved DMA Queuing slightly, less "all over the place" code. -Jiggled some IPU bits around to clean up some clutter. -Added the FFX and Digital Devil Saga video fixes as a Gamefix for now. Due to the delay involved, this causes other videos to terminate early, so now disabled by default. -Added a load of logging for hardware in dev builds (also now label more correctly) and some bits for debugging IPU easier. Some are commented out, but can be enabled for testing. -Made a small clarification in VIF git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2875 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
36c9d63495
commit
f01e10fc9a
|
@ -430,7 +430,8 @@ struct Pcsx2Config
|
|||
FpuCompareHack :1, // Digimon Rumble Arena 2, fixes spinning/hanging on intro-menu.
|
||||
FpuMulHack :1, // Tales of Destiny hangs.
|
||||
FpuNegDivHack :1, // Gundam games messed up camera-view.
|
||||
XgKickHack :1; // Erementar Gerad, adds more delay to VU XGkick instructions. Corrects the color of some graphics, but breaks Tri-ace games and others.
|
||||
XgKickHack :1, // Erementar Gerad, adds more delay to VU XGkick instructions. Corrects the color of some graphics, but breaks Tri-ace games and others.
|
||||
IPUWaitHack :1;
|
||||
BITFIELD_END
|
||||
|
||||
// all gamefixes are disabled by default.
|
||||
|
@ -555,7 +556,7 @@ TraceLogFilters& SetTraceConfig();
|
|||
#define CHECK_IOPREC (EmuConfig.Cpu.Recompiler.EnableIOP && GetSysCoreAlloc().IsRecAvailable_IOP())
|
||||
|
||||
//------------ SPECIAL GAME FIXES!!! ---------------
|
||||
#define NUM_OF_GAME_FIXES 6
|
||||
#define NUM_OF_GAME_FIXES 7
|
||||
|
||||
#define CHECK_VUADDSUBHACK (EmuConfig.Gamefixes.VuAddSubHack) // Special Fix for Tri-ace games, they use an encryption algorithm that requires VU addi opcode to be bit-accurate.
|
||||
#define CHECK_FPUCOMPAREHACK (EmuConfig.Gamefixes.FpuCompareHack) // Special Fix for Digimon Rumble Arena 2, fixes spinning/hanging on intro-menu.
|
||||
|
@ -563,6 +564,7 @@ TraceLogFilters& SetTraceConfig();
|
|||
#define CHECK_FPUMULHACK (EmuConfig.Gamefixes.FpuMulHack) // Special Fix for Tales of Destiny hangs.
|
||||
#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_IPUWAITHACK (EmuConfig.Gamefixes.IPUWaitHack) // Special Fix for Erementar Gerad, adds more delay to VU XGkick instructions. Corrects the color of some graphics.
|
||||
|
||||
//------------ Advanced Options!!! ---------------
|
||||
#define CHECK_VU_OVERFLOW (EmuConfig.Cpu.Recompiler.vuOverflow)
|
||||
|
|
|
@ -394,7 +394,7 @@ static __forceinline const wxChar* ChcrName(u32 addr)
|
|||
{
|
||||
case D0_CHCR: return L"Vif 0";
|
||||
case D1_CHCR: return L"Vif 1";
|
||||
case D2_CHCR: return L"GS";
|
||||
case D2_CHCR: return L"GIF";
|
||||
case D3_CHCR: return L"Ipu 0";
|
||||
case D4_CHCR: return L"Ipu 1";
|
||||
case D5_CHCR: return L"Sif 0";
|
||||
|
|
|
@ -230,7 +230,7 @@ void GIFdma()
|
|||
ptag = ReadTag();
|
||||
gifRegs->stat.FQC = max((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // OPH=1 | APATH=3]
|
||||
if (ptag == NULL) return;
|
||||
GIF_LOG("PTH3 MASK gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx", ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr);
|
||||
GIF_LOG("PTH3 MASK gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr, gif->tadr);
|
||||
|
||||
//Check TIE bit of CHCR and IRQ bit of tag
|
||||
if (checkTieBit(ptag)) GIF_LOG("PATH3 MSK dmaIrq Set");
|
||||
|
@ -280,7 +280,7 @@ void GIFdma()
|
|||
{
|
||||
ptag = ReadTag();
|
||||
if (ptag == NULL) return;
|
||||
GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx", ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr);
|
||||
GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr, gif->tadr);
|
||||
gifRegs->stat.FQC = max((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // OPH=1 | APATH=3]
|
||||
if (dmacRegs->ctrl.STD == STD_GIF)
|
||||
{
|
||||
|
@ -314,7 +314,7 @@ void GIFdma()
|
|||
|
||||
checkTieBit(ptag);
|
||||
|
||||
GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx", ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr);
|
||||
GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr, gif->tadr);
|
||||
CPU_INT(DMAC_GIF, gscycles * BIAS);
|
||||
}
|
||||
else
|
||||
|
@ -349,7 +349,7 @@ void dmaGIF()
|
|||
if ((gif->qwc == 0) && (gif->chcr.MOD != NORMAL_MODE))
|
||||
{
|
||||
tDMA_TAG* ptag = ReadTag2();
|
||||
GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx", ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr);
|
||||
GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr, gif->tadr);
|
||||
|
||||
checkTieBit(ptag);
|
||||
GIFdma();
|
||||
|
|
122
pcsx2/HwRead.cpp
122
pcsx2/HwRead.cpp
|
@ -38,8 +38,49 @@ __forceinline mem8_t hwRead8(u32 mem)
|
|||
|
||||
// TODO re-implement this warning along with a *complete* logging of all hw activity.
|
||||
// (implementation should be modelled after thee iopHWRead/iopHwWrite files)
|
||||
if( mem >= IPU_CMD && mem < D0_CHCR ) return psHu8(mem);
|
||||
if( mem >= IPU_CMD && mem < D0_CHCR )
|
||||
{
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
HW_LOG("8bit Hardware IPU Read at 0x%x, value=0x%x", mem, psHu8(mem) );
|
||||
#endif
|
||||
return psHu8(mem);
|
||||
}
|
||||
// DevCon.Warning("Unexpected hwRead8 from 0x%x", mem);
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
switch((mem >> 12) & 0xf)
|
||||
{
|
||||
case 0x03:
|
||||
if((mem & 0xfff) < 0x800) break;
|
||||
case 0x04:
|
||||
case 0x05:
|
||||
case 0x06:
|
||||
case 0x07:
|
||||
case 0x08:
|
||||
case 0x09:
|
||||
case 0x0a:
|
||||
case 0x0b:
|
||||
case 0x0c:
|
||||
case 0x0d:
|
||||
{
|
||||
const char* regName = "Unknown";
|
||||
|
||||
switch( mem & 0xf0)
|
||||
{
|
||||
case 0x00: regName = "CHCR"; break;
|
||||
case 0x10: regName = "MADR"; break;
|
||||
case 0x20: regName = "QWC"; break;
|
||||
case 0x30: regName = "TADR"; break;
|
||||
case 0x40: regName = "ASR0"; break;
|
||||
case 0x50: regName = "ASR1"; break;
|
||||
case 0x80: regName = "SADDR"; break;
|
||||
}
|
||||
|
||||
HW_LOG("Hardware Read 8 at 0x%x (%ls %s), value=0x%x", mem, ChcrName(mem & ~0xff), regName, psHu8(mem) );
|
||||
ret = psHu8(mem);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (mem)
|
||||
{
|
||||
|
@ -113,9 +154,51 @@ __forceinline mem16_t hwRead16(u32 mem)
|
|||
|
||||
// TODO re-implement this warning along with a *complete* logging of all hw activity.
|
||||
// (implementation should be modelled after the iopHWRead/iopHwWrite files)
|
||||
if( mem >= IPU_CMD && mem < D0_CHCR ) return psHu8(mem);
|
||||
if( mem >= IPU_CMD && mem < D0_CHCR )
|
||||
{
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
HW_LOG("16 bit Hardware IPU Read at 0x%x, value=0x%x", mem, psHu16(mem) );
|
||||
#endif
|
||||
return psHu16(mem);
|
||||
}
|
||||
// Console.Warning("Unexpected hwRead16 from 0x%x", mem);
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
switch((mem >> 12) & 0xf)
|
||||
{
|
||||
case 0x03:
|
||||
if((mem & 0xfff) < 0x800) break;
|
||||
case 0x04:
|
||||
case 0x05:
|
||||
case 0x06:
|
||||
case 0x07:
|
||||
case 0x08:
|
||||
case 0x09:
|
||||
case 0x0a:
|
||||
case 0x0b:
|
||||
case 0x0c:
|
||||
case 0x0d:
|
||||
{
|
||||
const char* regName = "Unknown";
|
||||
|
||||
switch( mem & 0xf0)
|
||||
{
|
||||
case 0x00: regName = "CHCR"; break;
|
||||
case 0x10: regName = "MADR"; break;
|
||||
case 0x20: regName = "QWC"; break;
|
||||
case 0x30: regName = "TADR"; break;
|
||||
case 0x40: regName = "ASR0"; break;
|
||||
case 0x50: regName = "ASR1"; break;
|
||||
case 0x80: regName = "SADDR"; break;
|
||||
}
|
||||
|
||||
HW_LOG("Hardware Read16 at 0x%x (%ls %s), value=0x%x", mem, ChcrName(mem & ~0xff), regName, psHu16(mem) );
|
||||
ret = psHu16(mem);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (mem)
|
||||
{
|
||||
case RCNT0_COUNT: ret = (u16)rcntRcount(0); break;
|
||||
|
@ -296,8 +379,9 @@ mem32_t __fastcall hwRead32_generic(u32 mem)
|
|||
///////////////////////////////////////////////////////
|
||||
// Most of the following case handlers are for developer builds only (logging).
|
||||
// It'll all optimize to ziltch in public release builds.
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
case 0x03:
|
||||
if((mem & 0xfff) < 0x800) break;
|
||||
case 0x04:
|
||||
case 0x05:
|
||||
case 0x06:
|
||||
|
@ -305,34 +389,34 @@ mem32_t __fastcall hwRead32_generic(u32 mem)
|
|||
case 0x08:
|
||||
case 0x09:
|
||||
case 0x0a:
|
||||
case 0x0b:
|
||||
case 0x0c:
|
||||
case 0x0d:
|
||||
{
|
||||
const char* regName = "Unknown";
|
||||
|
||||
switch( mem )
|
||||
switch( mem & 0xf0)
|
||||
{
|
||||
case D2_CHCR: regName = "DMA2_CHCR"; break;
|
||||
case D2_MADR: regName = "DMA2_MADR"; break;
|
||||
case D2_QWC: regName = "DMA2_QWC"; break;
|
||||
case D2_TADR: regName = "DMA2_TADDR"; break;
|
||||
case D2_ASR0: regName = "DMA2_ASR0"; break;
|
||||
case D2_ASR1: regName = "DMA2_ASR1"; break;
|
||||
case D2_SADR: regName = "DMA2_SADDR"; break;
|
||||
case 0x00: regName = "CHCR"; break;
|
||||
case 0x10: regName = "MADR"; break;
|
||||
case 0x20: regName = "QWC"; break;
|
||||
case 0x30: regName = "TADR"; break;
|
||||
case 0x40: regName = "ASR0"; break;
|
||||
case 0x50: regName = "ASR1"; break;
|
||||
case 0x80: regName = "SADDR"; break;
|
||||
}
|
||||
|
||||
HW_LOG( "Hardware Read32 at 0x%x (%s), value=0x%x", mem, regName, psHu32(mem) );
|
||||
HW_LOG("Hardware Read32 at 0x%x (%ls %s), value=0x%x", mem, ChcrName(mem & ~0xff), regName, psHu32(mem) );
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0b:
|
||||
if( mem == D4_CHCR )
|
||||
HW_LOG("Hardware Read32 at 0x%x (IPU1:DMA4_CHCR), value=0x%x", mem, psHu32(mem));
|
||||
break;
|
||||
|
||||
case 0x0c:
|
||||
#endif
|
||||
case 0x0e:
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
HW_LOG("DMAC Control Regs addr=0x%x Read32, value=0x%x", mem, psHu32(mem));
|
||||
#else
|
||||
if( mem == DMAC_STAT)
|
||||
HW_LOG("DMAC_STAT Read32, value=0x%x", psHu32(DMAC_STAT));
|
||||
#endif
|
||||
break;
|
||||
|
||||
jNO_DEFAULT;
|
||||
|
|
|
@ -24,167 +24,20 @@ using namespace R5900;
|
|||
/////////////////////////////////////////////////////////////////////////
|
||||
// DMA Execution Interfaces
|
||||
|
||||
// dark cloud2 uses 8 bit DMAs register writes
|
||||
static __forceinline void DmaExec8( void (*func)(), u32 mem, u8 value )
|
||||
{
|
||||
Registers::Freeze();
|
||||
u32 qwcRegister = (mem | 0x20) & ~0x1; //Need to remove the lower bit else we end up clearing TADR
|
||||
|
||||
//It's invalid for the hardware to write a DMA while it is active, not without Suspending the DMAC
|
||||
if ((value & 0x1) && ((psHu8(mem) & 0x1) == 0x1) && dmacRegs->ctrl.DMAE) {
|
||||
DevCon.Warning(L"DMAExec8 Attempt to run DMA while one is already active in %s(%x)", ChcrName(mem), mem);
|
||||
func();
|
||||
Registers::Thaw();
|
||||
return;
|
||||
}
|
||||
|
||||
// Upper 16bits of QWC should not be written since QWC is 16bits in size.
|
||||
if ((psHu32(qwcRegister) >> 16) != 0)
|
||||
{
|
||||
DevCon.Warning("DmaExec8 DMA QWC (%x) upper 16bits set to %x\n", qwcRegister, psHu32(qwcRegister) >> 16);
|
||||
psHu32(qwcRegister) = 0;
|
||||
}
|
||||
|
||||
psHu8(mem) = (u8)value;
|
||||
if ((psHu8(mem) & 0x1) && dmacRegs->ctrl.DMAE && !psHu8(DMAC_ENABLER+2))
|
||||
{
|
||||
/*Console.WriteLn("Running DMA 8 %x", psHu32(mem & ~0x1));*/
|
||||
func();
|
||||
}
|
||||
Registers::Thaw();
|
||||
}
|
||||
|
||||
static __forceinline void DmaExec16( void (*func)(), u32 mem, u16 value )
|
||||
{
|
||||
Registers::Freeze();
|
||||
|
||||
DMACh *reg = &psH_DMACh(mem);
|
||||
tDMA_CHCR chcr(value);
|
||||
|
||||
//It's invalid for the hardware to write a DMA while it is active, not without Suspending the DMAC
|
||||
|
||||
if (chcr.STR && reg->chcr.STR && dmacRegs->ctrl.DMAE) {
|
||||
if((reg->chcr._u32 & 0xff) == (chcr._u32 & 0xff) && psHu8(DMAC_ENABLER+2) == 0) //Tried to start another DMA in the same mode
|
||||
DevCon.Warning(L"DMAExec16 Attempt to run DMA while one is already active in %s(%x)", ChcrName(mem), mem);
|
||||
else //Just trying to change mode without stopping the DMA, so we dont care really :P
|
||||
{
|
||||
HW_LOG("Attempted to change modes while DMA active, ignoring");
|
||||
// When DMA is active only STR field is writable, so we just
|
||||
// call the dma transfer function w/o modifying CHCR contents...
|
||||
//func();
|
||||
Registers::Thaw();
|
||||
return; // Test with Gust games and fatal frame
|
||||
}
|
||||
}
|
||||
|
||||
//This should be more correct, but the FFX video does some WIERD stuff and tries to stop and restart the IPU without suspending
|
||||
/*if (reg->chcr.STR) {
|
||||
if(psHu8(DMAC_ENABLER+2) == 0) // DMA Not in suspend mode
|
||||
{
|
||||
DevCon.Warning(L"DMAExec16 Attempt to alter DMA While not Suspended %s(%x) Current Val %x New Val %x", ChcrName(mem), mem, reg->chcr._u32, value);
|
||||
// When DMA is active only STR field is writable, so we just
|
||||
// call the dma transfer function w/o modifying CHCR contents...
|
||||
//func();
|
||||
Registers::Thaw();
|
||||
return; // Test with Gust games and fatal frame
|
||||
}
|
||||
}*/
|
||||
|
||||
// Note: pad is the padding right above qwc, so we're testing whether qwc
|
||||
// has overflowed into pad.
|
||||
// Note2: May be only needed for IPU which has this handling in IPU.cpp now. (Fixes GS transfers)
|
||||
if (reg->pad != 0)
|
||||
{
|
||||
DevCon.Warning(L"DmaExec16 DMA QWC (%s) upper 16 bits set to %x\n",
|
||||
ChcrName(mem), reg->pad);
|
||||
//reg->qwc = reg->pad = 0;
|
||||
}
|
||||
|
||||
psHu16(mem) = chcr.lower();
|
||||
if (reg->chcr.STR && dmacRegs->ctrl.DMAE && !psHu8(DMAC_ENABLER+2))
|
||||
{
|
||||
//Console.WriteLn("16bit DMA Start");
|
||||
func();
|
||||
}
|
||||
Registers::Thaw();
|
||||
}
|
||||
|
||||
static void DmaExec( void (*func)(), u32 mem, u32 value )
|
||||
{
|
||||
Registers::Freeze();
|
||||
|
||||
DMACh *reg = &psH_DMACh(mem);
|
||||
tDMA_CHCR chcr(value);
|
||||
|
||||
//It's invalid for the hardware to write a DMA while it is active, not without Suspending the DMAC
|
||||
if (chcr.STR && reg->chcr.STR && dmacRegs->ctrl.DMAE)
|
||||
{
|
||||
if((reg->chcr._u32 & 0xff) == (chcr._u32 & 0xff) && psHu8(DMAC_ENABLER+2) == 0) //Tried to start another DMA in the same mode
|
||||
{
|
||||
DevCon.Warning(L"DMAExec32 Attempt to run DMA while one is already active in %s(%x)", ChcrName(mem), mem);
|
||||
cpuClearInt( ChannelNumber(mem) ); // clear any eventual interrupts (Fahrenheit boot, VIF1 active)
|
||||
}
|
||||
else //Just trying to change mode without stopping the DMA, so we dont care really :P
|
||||
{
|
||||
DevCon.Warning("Attempted to change modes while DMA active, ignoring");
|
||||
// When DMA is active only STR field is writable, so we just
|
||||
// call the dma transfer function w/o modifying CHCR contents...
|
||||
//func();
|
||||
Registers::Thaw();
|
||||
return; // Test with Gust games and fatal frame
|
||||
}
|
||||
}
|
||||
|
||||
//This should be more correct, but the FFX video does some WIERD stuff and tries to stop and restart the IPU without suspending
|
||||
/*if (reg->chcr.STR) {
|
||||
if(psHu8(DMAC_ENABLER+2) == 0) // DMA Not in suspend mode
|
||||
{
|
||||
DevCon.Warning(L"DMAExec32 Attempt to alter DMA While not Suspended %s(%x) Current Val %x New Val %x", ChcrName(mem), mem, reg->chcr._u32, value);
|
||||
// When DMA is active only STR field is writable, so we just
|
||||
// call the dma transfer function w/o modifying CHCR contents...
|
||||
//func();
|
||||
Registers::Thaw();
|
||||
return; // Test with Gust games and fatal frame
|
||||
}
|
||||
}*/
|
||||
|
||||
// Note: pad is the padding right above qwc, so we're testing whether qwc
|
||||
// has overflowed into pad.
|
||||
// Note2: May be only needed for IPU which has this handling in IPU.cpp now. (Fixes GS transfers)
|
||||
if (reg->pad != 0)
|
||||
{
|
||||
DevCon.Warning(L"DmaExec32 DMA QWC (%s) upper 16 bits set to %x\n",
|
||||
ChcrName(mem), reg->pad);
|
||||
//reg->qwc = reg->pad = 0;
|
||||
//return;
|
||||
}
|
||||
|
||||
/* Keep the old tag if in chain mode and hw doesn't set it*/
|
||||
if ((chcr.MOD == CHAIN_MODE) && (chcr.TAG == 0))
|
||||
reg->chcr.set((reg->chcr.TAG << 16) | chcr.lower());
|
||||
else /* Else (including Normal mode etc) write whatever the hardware sends*/
|
||||
reg->chcr.set(value);
|
||||
|
||||
if (reg->chcr.STR && dmacRegs->ctrl.DMAE && !psHu8(DMAC_ENABLER+2)) func();
|
||||
|
||||
Registers::Thaw();
|
||||
}
|
||||
|
||||
static bool QuickDmaExec( void (*func)(), u32 mem)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
Registers::Freeze();
|
||||
|
||||
DMACh *reg = &psH_DMACh(mem);
|
||||
|
||||
if (reg->chcr.STR && dmacRegs->ctrl.DMAE && !psHu8(DMAC_ENABLER+2))
|
||||
{
|
||||
Registers::Freeze();
|
||||
func();
|
||||
Registers::Thaw();
|
||||
ret = true;
|
||||
}
|
||||
|
||||
Registers::Thaw();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -195,7 +48,7 @@ u32 oldvalue = 0;
|
|||
void __fastcall StartQueuedDMA()
|
||||
{
|
||||
if (QueuedDMA.VIF0) { DMA_LOG("Resuming DMA for VIF0"); if(QuickDmaExec(dmaVIF0, D0_CHCR) == true) QueuedDMA.VIF0 = false; }
|
||||
if (QueuedDMA.VIF1) { DMA_LOG("Resuming DMA for VIF1"); if(QuickDmaExec(dmaVIF1, D1_CHCR) == true) QueuedDMA.VIF0 = false; }
|
||||
if (QueuedDMA.VIF1) { DMA_LOG("Resuming DMA for VIF1"); if(QuickDmaExec(dmaVIF1, D1_CHCR) == true) QueuedDMA.VIF1 = false; }
|
||||
if (QueuedDMA.GIF ) { DMA_LOG("Resuming DMA for GIF" ); if(QuickDmaExec(dmaGIF , D2_CHCR) == true) QueuedDMA.GIF = false; }
|
||||
if (QueuedDMA.IPU0) { DMA_LOG("Resuming DMA for IPU0"); if(QuickDmaExec(dmaIPU0, D3_CHCR) == true) QueuedDMA.IPU0 = false; }
|
||||
if (QueuedDMA.IPU1) { DMA_LOG("Resuming DMA for IPU1"); if(QuickDmaExec(dmaIPU1, D4_CHCR) == true) QueuedDMA.IPU1 = false; }
|
||||
|
@ -206,6 +59,215 @@ void __fastcall StartQueuedDMA()
|
|||
if (QueuedDMA.SPR1) { DMA_LOG("Resuming DMA for SPR1"); if(QuickDmaExec(dmaSPR1, D9_CHCR) == true) QueuedDMA.SPR1 = false; }
|
||||
}
|
||||
|
||||
// dark cloud2 uses 8 bit DMAs register writes
|
||||
static __forceinline void DmaExec8( void (*func)(), u32 mem, u8 value )
|
||||
{
|
||||
DMACh *reg = &psH_DMACh(mem & ~0xf);
|
||||
|
||||
//The only thing we can do in an 8bit write is set the CHCR, so lets just do checks for that
|
||||
|
||||
//It's invalid for the hardware to write a DMA while it is active, not without Suspending the DMAC
|
||||
if (reg->chcr.STR)// && reg->chcr.STR && dmacRegs->ctrl.DMAE)
|
||||
{
|
||||
if(psHu8(DMAC_ENABLER+2) == 1) //DMA is suspended so we can allow writes to anything
|
||||
{
|
||||
//If it stops the DMA, we need to clear any pending interrupts so the DMA doesnt continue.
|
||||
if(value == 0)
|
||||
{
|
||||
//DevCon.Warning(L"8bit %s DMA Stopped on Suspend", ChcrName(mem & ~0xf));
|
||||
cpuClearInt( ChannelNumber(mem & ~0xf) );
|
||||
}
|
||||
//Here we update the lower part of the CHCR, we dont touch the tag as it is only a 16bit value
|
||||
reg->chcr.STR = value;
|
||||
return;
|
||||
}
|
||||
else //Else the DMA is suspended, so we cant touch it!
|
||||
{
|
||||
//As the manual states "Fields other than STR can only be written to when the DMA is stopped"
|
||||
//Also "The DMA may not stop properly just by writing 0 to STR"
|
||||
//So the presumption is that STR can be written to (ala force stop the DMA) but nothing else
|
||||
|
||||
if(value == 0)
|
||||
{
|
||||
//DevCon.Warning(L"8bit Force Stopping %s (Current CHCR %x) while DMA active", ChcrName(mem & ~0xf), reg->chcr._u32, value);
|
||||
reg->chcr.STR = value;
|
||||
}
|
||||
//else DevCon.Warning(L"8bit Attempted to stop %s DMA without suspend, ignoring", ChcrName(mem & ~0xf));
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
reg->chcr.STR = value;
|
||||
|
||||
if (reg->chcr.STR && dmacRegs->ctrl.DMAE && !psHu8(DMAC_ENABLER+2))
|
||||
{
|
||||
Registers::Freeze();
|
||||
func();
|
||||
Registers::Thaw();
|
||||
}
|
||||
else
|
||||
{
|
||||
//DevCon.Warning(L"8bit %s DMA Start while DMAC Disabled\n",ChcrName(mem));
|
||||
QueuedDMA._u16 |= (1 << ChannelNumber(mem & ~0xf)); //Queue the DMA up to be started then the DMA's are Enabled and or the Suspend is lifted
|
||||
}
|
||||
}
|
||||
|
||||
static __forceinline void DmaExec16( void (*func)(), u32 mem, u16 value )
|
||||
{
|
||||
|
||||
DMACh *reg = &psH_DMACh(mem);
|
||||
tDMA_CHCR chcr(value);
|
||||
|
||||
//It's invalid for the hardware to write a DMA while it is active, not without Suspending the DMAC
|
||||
if (reg->chcr.STR)// && reg->chcr.STR && dmacRegs->ctrl.DMAE)
|
||||
{
|
||||
if(psHu8(DMAC_ENABLER+2) == 1) //DMA is suspended so we can allow writes to anything
|
||||
{
|
||||
//If it stops the DMA, we need to clear any pending interrupts so the DMA doesnt continue.
|
||||
if(chcr.STR == 0)
|
||||
{
|
||||
//DevCon.Warning(L"16bit %s DMA Stopped on Suspend", ChcrName(mem));
|
||||
cpuClearInt( ChannelNumber(mem) );
|
||||
}
|
||||
//Here we update the lower part of the CHCR, we dont touch the tag as it is only a 16bit value
|
||||
reg->chcr.set((reg->chcr.TAG << 16) | chcr.lower());
|
||||
return;
|
||||
}
|
||||
else //Else the DMA is suspended, so we cant touch it!
|
||||
{
|
||||
//As the manual states "Fields other than STR can only be written to when the DMA is stopped"
|
||||
//Also "The DMA may not stop properly just by writing 0 to STR"
|
||||
//So the presumption is that STR can be written to (ala force stop the DMA) but nothing else
|
||||
|
||||
if(chcr.STR == 0)
|
||||
{
|
||||
//DevCon.Warning(L"16bit Force Stopping %s (Current CHCR %x) while DMA active", ChcrName(mem), reg->chcr._u32, chcr._u32);
|
||||
reg->chcr.set((reg->chcr.TAG << 16) | chcr.lower());
|
||||
}
|
||||
//else DevCon.Warning(L"16bit Attempted to change %s modes while DMA active, ignoring", ChcrName(mem));
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
reg->chcr.set((reg->chcr.TAG << 16) | chcr.lower());
|
||||
|
||||
if (reg->chcr.STR && dmacRegs->ctrl.DMAE && !psHu8(DMAC_ENABLER+2))
|
||||
{
|
||||
Registers::Freeze();
|
||||
func();
|
||||
Registers::Thaw();
|
||||
}
|
||||
else
|
||||
{
|
||||
//DevCon.Warning(L"16bit %s DMA Start while DMAC Disabled\n",ChcrName(mem));
|
||||
QueuedDMA._u16 |= (1 << ChannelNumber(mem)); //Queue the DMA up to be started then the DMA's are Enabled and or the Suspend is lifted
|
||||
}
|
||||
}
|
||||
|
||||
static void DmaExec( void (*func)(), u32 mem, u32 value )
|
||||
{
|
||||
|
||||
DMACh *reg = &psH_DMACh(mem);
|
||||
tDMA_CHCR chcr(value);
|
||||
|
||||
//It's invalid for the hardware to write a DMA while it is active, not without Suspending the DMAC
|
||||
if (reg->chcr.STR)// && reg->chcr.STR && dmacRegs->ctrl.DMAE)
|
||||
{
|
||||
if(psHu8(DMAC_ENABLER+2) == 1) //DMA is suspended so we can allow writes to anything
|
||||
{
|
||||
//If it stops the DMA, we need to clear any pending interrupts so the DMA doesnt continue.
|
||||
if(chcr.STR == 0)
|
||||
{
|
||||
//DevCon.Warning(L"32bit %s DMA Stopped on Suspend", ChcrName(mem));
|
||||
cpuClearInt( ChannelNumber(mem) );
|
||||
}
|
||||
//Sanity Check for possible future bug fix0rs ;p
|
||||
if(reg->chcr.TAG != chcr.TAG) DevCon.Warning(L"32bit CHCR Tag on %s changed to %x from %x QWC = %x Channel Active", ChcrName(mem), chcr.TAG, reg->chcr.TAG, reg->qwc);
|
||||
//Here we update the ENTIRE CHCR, if a chain is stopped half way through, it can be manipulated in to a different mode
|
||||
reg->chcr.set(value);
|
||||
return;
|
||||
}
|
||||
else //Else the DMA is suspended, so we cant touch it!
|
||||
{
|
||||
//As the manual states "Fields other than STR can only be written to when the DMA is stopped"
|
||||
//Also "The DMA may not stop properly just by writing 0 to STR"
|
||||
//So the presumption is that STR can be written to (ala force stop the DMA) but nothing else
|
||||
|
||||
if(chcr.STR == 0)
|
||||
{
|
||||
//DevCon.Warning(L"32bit Force Stopping %s (Current CHCR %x) while DMA active", ChcrName(mem), reg->chcr._u32, chcr._u32);
|
||||
reg->chcr.set(value);
|
||||
}
|
||||
//else DevCon.Warning(L"32bit Attempted to change %s CHCR (Currently %x) with %x while DMA active, ignoring QWC = %x", ChcrName(mem), reg->chcr._u32, chcr._u32, reg->qwc);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//if(reg->chcr.TAG != chcr.TAG && chcr.MOD == CHAIN_MODE) //DevCon.Warning(L"32bit CHCR Tag on %s changed to %x from %x QWC = %x Channel Not Active", ChcrName(mem), chcr.TAG, reg->chcr.TAG, reg->qwc);
|
||||
|
||||
reg->chcr.set(value);
|
||||
|
||||
if (reg->chcr.STR && dmacRegs->ctrl.DMAE && !psHu8(DMAC_ENABLER+2))
|
||||
{
|
||||
Registers::Freeze();
|
||||
func();
|
||||
Registers::Thaw();
|
||||
}
|
||||
else if(reg->chcr.STR)
|
||||
{
|
||||
////DevCon.Warning(L"32bit %s DMA Start while DMAC Disabled\n", ChcrName(mem));
|
||||
QueuedDMA._u16 |= (1 << ChannelNumber(mem)); //Queue the DMA up to be started then the DMA's are Enabled and or the Suspend is lifted
|
||||
} //else QueuedDMA._u16 &~= (1 << ChannelNumber(mem)); //
|
||||
|
||||
|
||||
/*
|
||||
if((reg->chcr._u32 & 0xff) == (chcr._u32 & 0xff) && psHu8(DMAC_ENABLER+2) == 0) //Tried to start another DMA in the same mode
|
||||
{
|
||||
//DevCon.Warning(L"DMAExec32 Attempt to run DMA while one is already active in %s(%x)", ChcrName(mem), mem);
|
||||
cpuClearInt( ChannelNumber(mem) ); // clear any eventual interrupts (Fahrenheit boot, VIF1 active)
|
||||
}
|
||||
else //Just trying to change mode without stopping the DMA, so we dont care really :P
|
||||
{
|
||||
DevCon.Warning("Attempted to change modes while DMA active, ignoring");
|
||||
// When DMA is active only STR field is writable, so we just
|
||||
// call the dma transfer function w/o modifying CHCR contents...
|
||||
//func();
|
||||
Registers::Thaw();
|
||||
return; // Test with Gust games and fatal frame
|
||||
}*/
|
||||
//This should be more correct, but the FFX video does some WIERD stuff and tries to stop and restart the IPU without suspending
|
||||
/*if (reg->chcr.STR) {
|
||||
if(psHu8(DMAC_ENABLER+2) == 0) // DMA Not in suspend mode
|
||||
{
|
||||
//DevCon.Warning(L"DMAExec32 Attempt to alter DMA While not Suspended %s(%x) Current Val %x New Val %x", ChcrName(mem), mem, reg->chcr._u32, value);
|
||||
// When DMA is active only STR field is writable, so we just
|
||||
// call the dma transfer function w/o modifying CHCR contents...
|
||||
//func();
|
||||
Registers::Thaw();
|
||||
return; // Test with Gust games and fatal frame
|
||||
}
|
||||
}*/
|
||||
|
||||
// Note: pad is the padding right above qwc, so we're testing whether qwc
|
||||
// has overflowed into pad.
|
||||
// Note2: May be only needed for IPU which has this handling in IPU.cpp now. (Fixes GS transfers)
|
||||
/*if (reg->pad != 0)
|
||||
{
|
||||
//DevCon.Warning(L"DmaExec32 DMA QWC (%s) upper 16 bits set to %x\n",
|
||||
ChcrName(mem), reg->pad);
|
||||
//reg->qwc = reg->pad = 0;
|
||||
//return;
|
||||
}*/
|
||||
|
||||
/* Keep the old tag if in chain mode and hw doesn't set it*/
|
||||
/*if ((chcr.MOD == CHAIN_MODE) && (chcr.TAG == 0))
|
||||
reg->chcr.set((reg->chcr.TAG << 16) | chcr.lower());
|
||||
else*/ /* Else (including Normal mode etc) write whatever the hardware sends*/
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Hardware WRITE 8 bit
|
||||
|
||||
|
@ -277,105 +339,91 @@ void hwWrite8(u32 mem, u8 value)
|
|||
// break;
|
||||
case D0_CHCR + 1: // dma0 - vif0
|
||||
DMA_LOG("VIF0dma EXECUTE, value=0x%x", value);
|
||||
if ((value & 0x1) && !dmacRegs->ctrl.DMAE)
|
||||
{
|
||||
//DevCon.Warning("8 bit VIF0 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.VIF0 = true;
|
||||
} else QueuedDMA.VIF0 = false;
|
||||
DmaExec8(dmaVIF0, mem, value);
|
||||
break;
|
||||
|
||||
case D1_CHCR + 1: // dma1 - vif1
|
||||
DMA_LOG("VIF1dma EXECUTE, value=0x%x", value);
|
||||
if ((value & 0x1) && !dmacRegs->ctrl.DMAE)
|
||||
{
|
||||
//DevCon.Warning("8 bit VIF1 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.VIF1 = true;
|
||||
} else QueuedDMA.VIF1 = false;
|
||||
if(value & 0x1) vif1.done = false; //This must be done here! some games (ala Crash of the Titans) pause the dma to start MFIFO
|
||||
DmaExec8(dmaVIF1, mem, value);
|
||||
break;
|
||||
|
||||
case D2_CHCR + 1: // dma2 - gif
|
||||
DMA_LOG("GSdma EXECUTE, value=0x%x", value);
|
||||
if ((value & 0x1) && !dmacRegs->ctrl.DMAE)
|
||||
{
|
||||
//DevCon.Warning("8 bit GIF DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.GIF = true;
|
||||
} else QueuedDMA.GIF = false;
|
||||
DmaExec8(dmaGIF, mem, value);
|
||||
break;
|
||||
|
||||
case D3_CHCR + 1: // dma3 - fromIPU
|
||||
DMA_LOG("IPU0dma EXECUTE, value=0x%x", value);
|
||||
if ((value & 0x1) && !dmacRegs->ctrl.DMAE)
|
||||
{
|
||||
//DevCon.Warning("8 bit IPU0 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.IPU0 = true;
|
||||
} else QueuedDMA.IPU0 = false;
|
||||
DmaExec8(dmaIPU0, mem, value);
|
||||
break;
|
||||
|
||||
case D4_CHCR + 1: // dma4 - toIPU
|
||||
DMA_LOG("IPU1dma EXECUTE, value=0x%x", value);
|
||||
if ((value & 0x1) && !dmacRegs->ctrl.DMAE)
|
||||
{
|
||||
//DevCon.Warning("8 bit IPU1 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.IPU1 = true;
|
||||
} else QueuedDMA.IPU1 = false;
|
||||
DmaExec8(dmaIPU1, mem, value);
|
||||
break;
|
||||
|
||||
case D5_CHCR + 1: // dma5 - sif0
|
||||
DMA_LOG("SIF0dma EXECUTE, value=0x%x", value);
|
||||
// if (value == 0) psxSu32(0x30) = 0x40000;
|
||||
if ((value & 0x1) && !dmacRegs->ctrl.DMAE)
|
||||
{
|
||||
//DevCon.Warning("8 bit SIF0 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.SIF0 = true;
|
||||
} else QueuedDMA.SIF0 = false;
|
||||
DmaExec8(dmaSIF0, mem, value);
|
||||
break;
|
||||
|
||||
case D6_CHCR + 1: // dma6 - sif1
|
||||
DMA_LOG("SIF1dma EXECUTE, value=0x%x", value);
|
||||
if ((value & 0x1) && !dmacRegs->ctrl.DMAE)
|
||||
{
|
||||
//DevCon.Warning("8 bit SIF1 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.SIF1 = true;
|
||||
} else QueuedDMA.SIF1 = false;
|
||||
DmaExec8(dmaSIF1, mem, value);
|
||||
break;
|
||||
|
||||
case D7_CHCR + 1: // dma7 - sif2
|
||||
DMA_LOG("SIF2dma EXECUTE, value=0x%x", value);
|
||||
if ((value & 0x1) && !dmacRegs->ctrl.DMAE)
|
||||
{
|
||||
//DevCon.Warning("8 bit SIF2 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.SIF2 |= true;
|
||||
} else QueuedDMA.SIF2 = false;
|
||||
DmaExec8(dmaSIF2, mem, value);
|
||||
break;
|
||||
|
||||
case D8_CHCR + 1: // dma8 - fromSPR
|
||||
DMA_LOG("fromSPRdma8 EXECUTE, value=0x%x", value);
|
||||
if ((value & 0x1) && !dmacRegs->ctrl.DMAE)
|
||||
{
|
||||
//DevCon.Warning("8 bit SPR0 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.SPR0 = true;
|
||||
} else QueuedDMA.SPR0 = false;
|
||||
DmaExec8(dmaSPR0, mem, value);
|
||||
break;
|
||||
|
||||
case D9_CHCR + 1: // dma9 - toSPR
|
||||
DMA_LOG("toSPRdma8 EXECUTE, value=0x%x", value);
|
||||
if ((value & 0x1) && !dmacRegs->ctrl.DMAE)
|
||||
{
|
||||
//DevCon.Warning("8 bit SPR1 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA .SPR1 = true;
|
||||
} else QueuedDMA.SPR1 = false;
|
||||
DmaExec8(dmaSPR1, mem, value);
|
||||
break;
|
||||
case D0_CHCR: // dma0 - vif0
|
||||
case D1_CHCR: // dma1 - vif1
|
||||
case D2_CHCR: // dma2 - gif
|
||||
case D3_CHCR: // dma3 - fromIPU
|
||||
case D4_CHCR: // dma4 - toIPU
|
||||
case D5_CHCR: // dma5 - sif0
|
||||
case D6_CHCR: // dma6 - sif1
|
||||
case D7_CHCR: // dma7 - sif2
|
||||
case D8_CHCR: // dma8 - fromSPR
|
||||
case D9_CHCR: // dma9 - toSPR
|
||||
//DevCon.Warning(L"8bit lower CHCR changed to %x from %x on %s DMA", value, psHu32(mem), ChcrName(mem));
|
||||
psHu8(mem) = value;
|
||||
break;
|
||||
|
||||
case D0_CHCR + 2: // dma0 - vif0
|
||||
case D0_CHCR + 3: // dma0 - vif0
|
||||
case D1_CHCR + 2: // dma1 - vif1
|
||||
case D1_CHCR + 3: // dma1 - vif1
|
||||
case D2_CHCR + 2: // dma2 - gif
|
||||
case D2_CHCR + 3: // dma2 - gif
|
||||
case D3_CHCR + 2: // dma3 - fromIPU
|
||||
case D3_CHCR + 3: // dma3 - fromIPU
|
||||
case D4_CHCR + 2: // dma4 - toIPU
|
||||
case D4_CHCR + 3: // dma4 - toIPU
|
||||
case D5_CHCR + 2: // dma5 - sif0
|
||||
case D5_CHCR + 3: // dma5 - sif0
|
||||
case D6_CHCR + 2: // dma6 - sif1
|
||||
case D6_CHCR + 3: // dma6 - sif1
|
||||
case D7_CHCR + 2: // dma7 - sif2
|
||||
case D7_CHCR + 3: // dma7 - sif2
|
||||
case D8_CHCR + 2: // dma8 - fromSPR
|
||||
case D8_CHCR + 3: // dma8 - fromSPR
|
||||
case D9_CHCR + 2: // dma9 - toSPR
|
||||
case D9_CHCR + 3: // dma9 - toSPR
|
||||
//DevCon.Warning(L"8bit CHCR TAG changed to %x from %x on %s DMA", value, psHu32(mem), ChcrName(mem & ~0xf));
|
||||
psHu8(mem) = value;
|
||||
break;
|
||||
|
||||
case DMAC_ENABLEW + 2:
|
||||
oldvalue = psHu8(DMAC_ENABLEW + 2);
|
||||
|
@ -459,23 +507,11 @@ __forceinline void hwWrite16(u32 mem, u16 value)
|
|||
|
||||
case D0_CHCR: // dma0 - vif0
|
||||
DMA_LOG("VIF0dma %lx", value);
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
//DevCon.Warning("16 bit VIF0 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.VIF0 = true;
|
||||
} else QueuedDMA.VIF0 = false;
|
||||
DmaExec16(dmaVIF0, mem, value);
|
||||
break;
|
||||
|
||||
case D1_CHCR: // dma1 - vif1 - chcr
|
||||
DMA_LOG("VIF1dma CHCR %lx", value);
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
//DevCon.Warning("16 bit VIF1 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.VIF1 = true;
|
||||
} else QueuedDMA.VIF1 = false;
|
||||
|
||||
if (CHCR(value).STR) vif1.done = false; //This must be done here! some games (ala Crash of the Titans) pause the dma to start MFIFO
|
||||
DmaExec16(dmaVIF1, mem, value);
|
||||
break;
|
||||
|
||||
|
@ -514,11 +550,6 @@ __forceinline void hwWrite16(u32 mem, u16 value)
|
|||
|
||||
case D2_CHCR: // dma2 - gif
|
||||
DMA_LOG("0x%8.8x hwWrite32: GSdma %lx", cpuRegs.cycle, value);
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
//DevCon.Warning("16 bit GIF DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.GIF = true;
|
||||
} else QueuedDMA.GIF = false;
|
||||
DmaExec16(dmaGIF, mem, value);
|
||||
break;
|
||||
|
||||
|
@ -556,11 +587,6 @@ __forceinline void hwWrite16(u32 mem, u16 value)
|
|||
|
||||
case D3_CHCR: // dma3 - fromIPU
|
||||
DMA_LOG("IPU0dma %lx", value);
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
//DevCon.Warning("16 bit IPU0 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.IPU0 = true;
|
||||
} else QueuedDMA.IPU0 = false;
|
||||
DmaExec16(dmaIPU0, mem, value);
|
||||
break;
|
||||
|
||||
|
@ -588,11 +614,6 @@ __forceinline void hwWrite16(u32 mem, u16 value)
|
|||
|
||||
case D4_CHCR: // dma4 - toIPU
|
||||
DMA_LOG("IPU1dma %lx", value);
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
//DevCon.Warning("16 bit IPU1 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.IPU1 = true;
|
||||
} else QueuedDMA.IPU1 = false;
|
||||
DmaExec16(dmaIPU1, mem, value);
|
||||
break;
|
||||
|
||||
|
@ -619,26 +640,11 @@ __forceinline void hwWrite16(u32 mem, u16 value)
|
|||
#endif
|
||||
case D5_CHCR: // dma5 - sif0
|
||||
DMA_LOG("SIF0dma %lx", value);
|
||||
// if (value == 0) psxSu32(0x30) = 0x40000;
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
//DevCon.Warning("16 bit SIF0 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.SIF0 = true;
|
||||
} else QueuedDMA.SIF0 = false;
|
||||
DmaExec16(dmaSIF0, mem, value);
|
||||
break;
|
||||
|
||||
case D5_CHCR + 2:
|
||||
//?
|
||||
break;
|
||||
|
||||
case D6_CHCR: // dma6 - sif1
|
||||
DMA_LOG("SIF1dma %lx", value);
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
//DevCon.Warning("16 bit SIF1 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.SIF1 = true;
|
||||
} else QueuedDMA.SIF1 = false;
|
||||
DmaExec16(dmaSIF1, mem, value);
|
||||
break;
|
||||
|
||||
|
@ -666,38 +672,33 @@ __forceinline void hwWrite16(u32 mem, u16 value)
|
|||
|
||||
case D7_CHCR: // dma7 - sif2
|
||||
DMA_LOG("SIF2dma %lx", value);
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
//DevCon.Warning("16 bit SIF2 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.SIF2 = true;
|
||||
} else QueuedDMA.SIF2 = false;
|
||||
DmaExec16(dmaSIF2, mem, value);
|
||||
break;
|
||||
|
||||
case D7_CHCR + 2:
|
||||
//?
|
||||
break;
|
||||
|
||||
case D8_CHCR: // dma8 - fromSPR
|
||||
DMA_LOG("fromSPRdma %lx", value);
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
//DevCon.Warning("16 bit SPR0 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.SPR0 = true;
|
||||
} else QueuedDMA.SPR0 = false;
|
||||
DmaExec16(dmaSPR0, mem, value);
|
||||
break;
|
||||
|
||||
case D9_CHCR: // dma9 - toSPR
|
||||
DMA_LOG("toSPRdma %lx", value);
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
//DevCon.Warning("16 bit SPR1 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.SPR1 = true;
|
||||
} else QueuedDMA.SPR1 = false;
|
||||
DmaExec16(dmaSPR1, mem, value);
|
||||
break;
|
||||
|
||||
case D0_CHCR + 2: // dma0 - vif0
|
||||
case D1_CHCR + 2: // dma1 - vif1
|
||||
case D2_CHCR + 2: // dma2 - gif
|
||||
case D3_CHCR + 2: // dma3 - fromIPU
|
||||
case D4_CHCR + 2: // dma4 - toIPU
|
||||
case D5_CHCR + 2: // dma5 - sif0
|
||||
case D6_CHCR + 2: // dma6 - sif1
|
||||
case D7_CHCR + 2: // dma7 - sif2
|
||||
case D8_CHCR + 2: // dma8 - fromSPR
|
||||
case D9_CHCR + 2: // dma9 - toSPR
|
||||
//DevCon.Warning(L"16bit CHCR TAG changed to %x from %x on %s DMA", value, psHu32(mem), ChcrName(mem & ~0xf));
|
||||
psHu16(mem) = value;
|
||||
break;
|
||||
|
||||
case DMAC_ENABLEW + 2:
|
||||
oldvalue = psHu8(DMAC_ENABLEW + 2);
|
||||
psHu16(DMAC_ENABLEW + 2) = value;
|
||||
|
@ -853,11 +854,6 @@ void __fastcall hwWrite32_page_0B( u32 mem, u32 value )
|
|||
{
|
||||
case D3_CHCR: // dma3 - fromIPU
|
||||
DMA_LOG("IPU0dma EXECUTE, value=0x%x\n", value);
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
//DevCon.Warning("32 bit IPU0 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.IPU0 = true;
|
||||
} else QueuedDMA.IPU0 = false;
|
||||
DmaExec(dmaIPU0, mem, value);
|
||||
return;
|
||||
|
||||
|
@ -870,11 +866,6 @@ void __fastcall hwWrite32_page_0B( u32 mem, u32 value )
|
|||
|
||||
case D4_CHCR: // dma4 - toIPU
|
||||
DMA_LOG("IPU1dma EXECUTE, value=0x%x\n", value);
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
//DevCon.Warning("32 bit IPU1 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.IPU1 = true;
|
||||
} else QueuedDMA.IPU1 = false;
|
||||
DmaExec(dmaIPU1, mem, value);
|
||||
return;
|
||||
|
||||
|
@ -1013,35 +1004,12 @@ void __fastcall hwWrite32_generic( u32 mem, u32 value )
|
|||
{
|
||||
case D0_CHCR: // dma0 - vif0
|
||||
DMA_LOG("VIF0dma EXECUTE, value=0x%x", value);
|
||||
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
//DevCon.Warning("32 bit VIF0 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.VIF0 = true;
|
||||
} else QueuedDMA.VIF0 = false;
|
||||
|
||||
DmaExec(dmaVIF0, mem, value);
|
||||
return;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
case D1_CHCR: // dma1 - vif1 - chcr
|
||||
DMA_LOG("VIF1dma EXECUTE, value=0x%x", value);
|
||||
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
//DevCon.Warning("32 bit VIF1 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.VIF1 = true;
|
||||
} else QueuedDMA.VIF1 = false;
|
||||
|
||||
if (CHCR(value).STR)
|
||||
{
|
||||
vif1.done = false; //This must be done here! some games (ala Crash of the Titans) pause the dma to start MFIFO
|
||||
}
|
||||
else
|
||||
{
|
||||
cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Tekken tag seems to stop vif and start it again in normal, so we will cancel the mfifo loop
|
||||
}
|
||||
|
||||
DMA_LOG("VIF1dma EXECUTE, value=0x%x", value);
|
||||
DmaExec(dmaVIF1, mem, value);
|
||||
return;
|
||||
|
||||
|
@ -1055,11 +1023,6 @@ void __fastcall hwWrite32_generic( u32 mem, u32 value )
|
|||
//------------------------------------------------------------------
|
||||
case D2_CHCR: // dma2 - gif
|
||||
DMA_LOG("GIFdma EXECUTE, value=0x%x", value);
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
//DevCon.Warning("32 bit GIF DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.GIF = true;
|
||||
} else QueuedDMA.GIF = false;
|
||||
DmaExec(dmaGIF, mem, value);
|
||||
return;
|
||||
|
||||
|
@ -1073,22 +1036,11 @@ void __fastcall hwWrite32_generic( u32 mem, u32 value )
|
|||
//------------------------------------------------------------------
|
||||
case D5_CHCR: // dma5 - sif0
|
||||
DMA_LOG("SIF0dma EXECUTE, value=0x%x", value);
|
||||
//if (value == 0) psxSu32(0x30) = 0x40000;
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
//DevCon.Warning("32 bit SIF0 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.SIF0 = true;
|
||||
} else QueuedDMA.SIF0 = false;
|
||||
DmaExec(dmaSIF0, mem, value);
|
||||
return;
|
||||
//------------------------------------------------------------------
|
||||
case D6_CHCR: // dma6 - sif1
|
||||
DMA_LOG("SIF1dma EXECUTE, value=0x%x", value);
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
//DevCon.Warning("32 bit SIF1 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.SIF1 = true;
|
||||
} else QueuedDMA.SIF1 = false;
|
||||
DmaExec(dmaSIF1, mem, value);
|
||||
return;
|
||||
|
||||
|
@ -1099,31 +1051,16 @@ void __fastcall hwWrite32_generic( u32 mem, u32 value )
|
|||
//------------------------------------------------------------------
|
||||
case D7_CHCR: // dma7 - sif2
|
||||
DMA_LOG("SIF2dma EXECUTE, value=0x%x", value);
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
//DevCon.Warning("32 bit SIF2 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.SIF2 = true;
|
||||
} else QueuedDMA.SIF2 = false;
|
||||
DmaExec(dmaSIF2, mem, value);
|
||||
return;
|
||||
//------------------------------------------------------------------
|
||||
case D8_CHCR: // dma8 - fromSPR
|
||||
DMA_LOG("SPR0dma EXECUTE (fromSPR), value=0x%x", value);
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
//DevCon.Warning("32 bit SPR0 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.SPR0 = true;
|
||||
} else QueuedDMA.SPR0 = false;
|
||||
DmaExec(dmaSPR0, mem, value);
|
||||
return;
|
||||
//------------------------------------------------------------------
|
||||
case D9_CHCR: // dma9 - toSPR
|
||||
DMA_LOG("SPR1dma EXECUTE (toSPR), value=0x%x", value);
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
//DevCon.Warning("32 bit SPR1 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.SPR1 = true;
|
||||
} else QueuedDMA.SPR1 = false;
|
||||
DmaExec(dmaSPR1, mem, value);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -249,6 +249,8 @@ __forceinline u32 ipuRead32(u32 mem)
|
|||
|
||||
IPU_LOG("Ipu read32: IPU_BP=0x%08X", *(u32*)&g_BP);
|
||||
return ipuRegs->ipubp;
|
||||
default:
|
||||
IPU_LOG("Ipu read32: Addr=0x%x Value = 0x%08X", mem, *(u32*)(((u8*)ipuRegs) + mem));
|
||||
}
|
||||
|
||||
return *(u32*)(((u8*)ipuRegs) + mem);
|
||||
|
@ -1251,49 +1253,52 @@ static __forceinline void ipuDmacSrcChain()
|
|||
{
|
||||
case TAG_REFE: // refe
|
||||
//if(IPU1Status.InProgress == false) ipu1dma->tadr += 16;
|
||||
if(ipu1dma->qwc == 0 && IPU1Status.DMAFinished == false) IPU1Status.DMAFinished = true;
|
||||
if(IPU1Status.DMAFinished == false) IPU1Status.DMAFinished = true;
|
||||
break;
|
||||
case TAG_CNT: // cnt
|
||||
// Set the taddr to the next tag
|
||||
ipu1dma->tadr = ipu1dma->madr;
|
||||
if(ipu1dma->qwc == 0 && IPU1Status.DMAFinished == false) IPU1Status.DMAFinished = false;
|
||||
if(IPU1Status.DMAFinished == false) IPU1Status.DMAFinished = false;
|
||||
break;
|
||||
|
||||
case TAG_NEXT: // next
|
||||
ipu1dma->tadr = IPU1Status.NextMem;
|
||||
if(ipu1dma->qwc == 0 && IPU1Status.DMAFinished == false) IPU1Status.DMAFinished = false;
|
||||
if(IPU1Status.DMAFinished == false) IPU1Status.DMAFinished = false;
|
||||
break;
|
||||
|
||||
case TAG_REF: // ref
|
||||
//if(IPU1Status.InProgress == false)ipu1dma->tadr += 16;
|
||||
if(ipu1dma->qwc == 0 && IPU1Status.DMAFinished == false) IPU1Status.DMAFinished = false;
|
||||
if(IPU1Status.DMAFinished == false) IPU1Status.DMAFinished = false;
|
||||
break;
|
||||
|
||||
case TAG_END: // end
|
||||
ipu1dma->tadr = ipu1dma->madr;
|
||||
if(ipu1dma->qwc == 0 && IPU1Status.DMAFinished == false) IPU1Status.DMAFinished = true;
|
||||
if(IPU1Status.DMAFinished == false) IPU1Status.DMAFinished = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static __forceinline bool WaitGSPaths()
|
||||
{
|
||||
if(GSTransferStatus.PTH3 < STOPPED_MODE)
|
||||
if(CHECK_IPUWAITHACK)
|
||||
{
|
||||
//GIF_LOG("Flushing gif chcr %x tadr %x madr %x qwc %x", gif->chcr._u32, gif->tadr, gif->madr, gif->qwc);
|
||||
//DevCon.WriteLn("Waiting for GIF");
|
||||
return false;
|
||||
}
|
||||
if(GSTransferStatus.PTH3 < STOPPED_MODE)
|
||||
{
|
||||
//GIF_LOG("Flushing gif chcr %x tadr %x madr %x qwc %x", gif->chcr._u32, gif->tadr, gif->madr, gif->qwc);
|
||||
//DevCon.WriteLn("Waiting for GIF");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(GSTransferStatus.PTH2 != STOPPED_MODE)
|
||||
{
|
||||
//DevCon.WriteLn("Waiting for VIF");
|
||||
return false;
|
||||
}
|
||||
if(GSTransferStatus.PTH1 != STOPPED_MODE)
|
||||
{
|
||||
//DevCon.WriteLn("Waiting for VU");
|
||||
return false;
|
||||
if(GSTransferStatus.PTH2 != STOPPED_MODE)
|
||||
{
|
||||
//DevCon.WriteLn("Waiting for VIF");
|
||||
return false;
|
||||
}
|
||||
if(GSTransferStatus.PTH1 != STOPPED_MODE)
|
||||
{
|
||||
//DevCon.WriteLn("Waiting for VU");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -1319,19 +1324,20 @@ static __forceinline int IPU1chain() {
|
|||
qwc = ipu_fifo.in.write(pMem, qwc);
|
||||
ipu1dma->madr += qwc << 4;
|
||||
ipu1dma->qwc -= qwc;
|
||||
totalqwc += qwc;
|
||||
|
||||
if( ipu1dma->qwc == 0 )
|
||||
{
|
||||
//If the transfer has finished or we have room in the FIFO, schedule to the interrupt code.
|
||||
if(IPU1Status.DMAFinished == true || g_BP.IFC < 8)
|
||||
{
|
||||
IPU_INT_TO(4);
|
||||
}
|
||||
//No data left
|
||||
IPU1Status.InProgress = false;
|
||||
} //If we still have data the commands should pull this across when need be.
|
||||
totalqwc += qwc;
|
||||
}
|
||||
if( ipu1dma->qwc == 0)
|
||||
{
|
||||
//Update TADR etc
|
||||
if(IPU1Status.DMAMode == DMA_MODE_CHAIN) ipuDmacSrcChain();
|
||||
//If the transfer has finished or we have room in the FIFO, schedule to the interrupt code.
|
||||
if(IPU1Status.DMAFinished == true || g_BP.IFC < 8)
|
||||
{
|
||||
IPU_INT_TO(4);
|
||||
}
|
||||
//No data left
|
||||
IPU1Status.InProgress = false;
|
||||
} //If we still have data the commands should pull this across when need be.
|
||||
|
||||
return totalqwc;
|
||||
}
|
||||
|
@ -1389,9 +1395,7 @@ int IPU1dma()
|
|||
}
|
||||
IPU_LOG("Processing Chain QWC left %x Finished %d In Progress %d", ipu1dma->qwc, IPU1Status.DMAFinished, IPU1Status.InProgress);
|
||||
totalqwc += IPU1chain();
|
||||
//Set the TADR forward
|
||||
ipuDmacSrcChain();
|
||||
|
||||
//Set the TADR forward
|
||||
}
|
||||
|
||||
|
||||
|
@ -1479,13 +1483,13 @@ int IPU1dma()
|
|||
IPU_LOG("Processing Start Chain QWC left %x Finished %d In Progress %d", ipu1dma->qwc, IPU1Status.DMAFinished, IPU1Status.InProgress);
|
||||
totalqwc += IPU1chain();
|
||||
//Set the TADR forward
|
||||
ipuDmacSrcChain();
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
IPU_LOG("Completed Call IPU1 DMA QWC Remaining %x Finished %d In Progress %d tadr %x", ipu1dma->qwc, IPU1Status.DMAFinished, IPU1Status.InProgress, ipu1dma->tadr);
|
||||
return totalqwc;
|
||||
}
|
||||
|
||||
|
@ -1684,6 +1688,7 @@ IPU_FORCEINLINE void ipu1Interrupt()
|
|||
return;
|
||||
}
|
||||
|
||||
IPU_LOG("ipu1 finish %x:", cpuRegs.cycle);
|
||||
ipu1dma->chcr.STR = false;
|
||||
hwDmacIrq(DMAC_TO_IPU);
|
||||
}
|
||||
|
|
|
@ -34,6 +34,8 @@ void IPU_Fifo::init()
|
|||
void IPU_Fifo_Input::clear()
|
||||
{
|
||||
memzero(data);
|
||||
ipu1dma->chcr.STR = 0; //It forcebly ends, so we should clear the dma too (Kingdom Hearts)
|
||||
ipu1dma->qwc = 0;
|
||||
g_BP.IFC = 0;
|
||||
ipuRegs->ctrl.IFC = 0;
|
||||
readpos = 0;
|
||||
|
|
|
@ -257,6 +257,7 @@ void Pcsx2Config::GamefixOptions::LoadSave( IniInterface& ini )
|
|||
IniBitBool( FpuMulHack );
|
||||
IniBitBool( FpuNegDivHack );
|
||||
IniBitBool( XgKickHack );
|
||||
IniBitBool( IPUWaitHack );
|
||||
}
|
||||
|
||||
Pcsx2Config::Pcsx2Config()
|
||||
|
|
|
@ -40,7 +40,7 @@ void vif0Reset()
|
|||
vif0Regs->stat.VPS = VPS_IDLE;
|
||||
vif0Regs->stat.FQC = 0;
|
||||
|
||||
vif0.done = true;
|
||||
vif0.done = false;
|
||||
|
||||
resetNewVif(0);
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ void vif1Reset()
|
|||
vif1Regs->stat.VPS = VPS_IDLE;
|
||||
vif1Regs->stat.FQC = 0; // FQC=0
|
||||
|
||||
vif1.done = true;
|
||||
vif1.done = false;
|
||||
cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's
|
||||
|
||||
resetNewVif(1);
|
||||
|
@ -101,7 +101,7 @@ _f void vif0FBRST(u32 value) {
|
|||
cpuRegs.interrupt &= ~1; //Stop all vif0 DMA's
|
||||
psHu64(VIF0_FIFO) = 0;
|
||||
psHu64(VIF0_FIFO + 8) = 0;
|
||||
vif0.done = true;
|
||||
vif0.done = false;
|
||||
vif0Regs->err.reset();
|
||||
vif0Regs->stat.clear_flags(VIF0_STAT_FQC | VIF0_STAT_INT | VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS | VIF0_STAT_VPS); // FQC=0
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ _f void vif1FBRST(u32 value) {
|
|||
vif1ch->qwc = 0; //?
|
||||
psHu64(VIF1_FIFO) = 0;
|
||||
psHu64(VIF1_FIFO + 8) = 0;
|
||||
vif1.done = true;
|
||||
vif1.done = false;
|
||||
|
||||
if(vif1Regs->mskpath3)
|
||||
{
|
||||
|
|
|
@ -99,7 +99,8 @@ bool _VIF1chain()
|
|||
return true;
|
||||
}
|
||||
|
||||
if (vif1.dmamode == VIF_NORMAL_FROM_MEM_MODE)
|
||||
// Clarification - this is TO memory mode, for some reason i used the other way round >.<
|
||||
if (vif1.dmamode == VIF_NORMAL_TO_MEM_MODE)
|
||||
{
|
||||
vif1TransferFromMemory();
|
||||
vif1.inprogress = 0;
|
||||
|
@ -305,6 +306,7 @@ void dmaVIF1()
|
|||
vif1ch->chcr._u32, vif1ch->madr, vif1ch->qwc,
|
||||
vif1ch->tadr, vif1ch->asr0, vif1ch->asr1);
|
||||
|
||||
vif1.done = false;
|
||||
g_vifCycles = 0;
|
||||
vif1.inprogress = 0;
|
||||
|
||||
|
@ -332,9 +334,9 @@ void dmaVIF1()
|
|||
Console.WriteLn("DMA Stall Control on VIF1 normal");
|
||||
|
||||
if (vif1ch->chcr.DIR) // to Memory
|
||||
vif1.dmamode = VIF_NORMAL_TO_MEM_MODE;
|
||||
else
|
||||
vif1.dmamode = VIF_NORMAL_FROM_MEM_MODE;
|
||||
else
|
||||
vif1.dmamode = VIF_NORMAL_TO_MEM_MODE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -344,6 +346,5 @@ void dmaVIF1()
|
|||
vif1Regs->stat.FQC = min((u16)0x10, vif1ch->qwc);
|
||||
|
||||
// Chain Mode
|
||||
vif1.done = false;
|
||||
vif1Interrupt();
|
||||
}
|
|
@ -220,6 +220,7 @@ void mfifoVIF1transfer(int qwc)
|
|||
void vifMFIFOInterrupt()
|
||||
{
|
||||
g_vifCycles = 0;
|
||||
VIF_LOG("vif mfifo interrupt");
|
||||
|
||||
if (schedulepath3msk) Vif1MskPath3();
|
||||
|
||||
|
|
|
@ -57,6 +57,10 @@ Panels::GameFixesPanel::GameFixesPanel( wxWindow* parent ) :
|
|||
{
|
||||
_("VU XGkick Hack - for Erementar Gerad."),
|
||||
wxEmptyString
|
||||
},
|
||||
{
|
||||
_("IPU Wait Hack - Fix Ripping/Corrupted videos (FFX, Digital Devil Saga), Causes others to cut short"),
|
||||
wxEmptyString
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue