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.
|
FpuCompareHack :1, // Digimon Rumble Arena 2, fixes spinning/hanging on intro-menu.
|
||||||
FpuMulHack :1, // Tales of Destiny hangs.
|
FpuMulHack :1, // Tales of Destiny hangs.
|
||||||
FpuNegDivHack :1, // Gundam games messed up camera-view.
|
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
|
BITFIELD_END
|
||||||
|
|
||||||
// all gamefixes are disabled by default.
|
// all gamefixes are disabled by default.
|
||||||
|
@ -555,7 +556,7 @@ TraceLogFilters& SetTraceConfig();
|
||||||
#define CHECK_IOPREC (EmuConfig.Cpu.Recompiler.EnableIOP && GetSysCoreAlloc().IsRecAvailable_IOP())
|
#define CHECK_IOPREC (EmuConfig.Cpu.Recompiler.EnableIOP && GetSysCoreAlloc().IsRecAvailable_IOP())
|
||||||
|
|
||||||
//------------ SPECIAL GAME FIXES!!! ---------------
|
//------------ 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_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.
|
#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_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_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_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!!! ---------------
|
//------------ Advanced Options!!! ---------------
|
||||||
#define CHECK_VU_OVERFLOW (EmuConfig.Cpu.Recompiler.vuOverflow)
|
#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 D0_CHCR: return L"Vif 0";
|
||||||
case D1_CHCR: return L"Vif 1";
|
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 D3_CHCR: return L"Ipu 0";
|
||||||
case D4_CHCR: return L"Ipu 1";
|
case D4_CHCR: return L"Ipu 1";
|
||||||
case D5_CHCR: return L"Sif 0";
|
case D5_CHCR: return L"Sif 0";
|
||||||
|
|
|
@ -230,7 +230,7 @@ void GIFdma()
|
||||||
ptag = ReadTag();
|
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]
|
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;
|
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
|
//Check TIE bit of CHCR and IRQ bit of tag
|
||||||
if (checkTieBit(ptag)) GIF_LOG("PATH3 MSK dmaIrq Set");
|
if (checkTieBit(ptag)) GIF_LOG("PATH3 MSK dmaIrq Set");
|
||||||
|
@ -280,7 +280,7 @@ void GIFdma()
|
||||||
{
|
{
|
||||||
ptag = ReadTag();
|
ptag = ReadTag();
|
||||||
if (ptag == NULL) return;
|
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]
|
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)
|
if (dmacRegs->ctrl.STD == STD_GIF)
|
||||||
{
|
{
|
||||||
|
@ -314,7 +314,7 @@ void GIFdma()
|
||||||
|
|
||||||
checkTieBit(ptag);
|
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);
|
CPU_INT(DMAC_GIF, gscycles * BIAS);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -349,7 +349,7 @@ void dmaGIF()
|
||||||
if ((gif->qwc == 0) && (gif->chcr.MOD != NORMAL_MODE))
|
if ((gif->qwc == 0) && (gif->chcr.MOD != NORMAL_MODE))
|
||||||
{
|
{
|
||||||
tDMA_TAG* ptag = ReadTag2();
|
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);
|
checkTieBit(ptag);
|
||||||
GIFdma();
|
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.
|
// TODO re-implement this warning along with a *complete* logging of all hw activity.
|
||||||
// (implementation should be modelled after thee iopHWRead/iopHwWrite files)
|
// (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);
|
// 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)
|
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.
|
// TODO re-implement this warning along with a *complete* logging of all hw activity.
|
||||||
// (implementation should be modelled after the iopHWRead/iopHwWrite files)
|
// (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);
|
// 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)
|
switch (mem)
|
||||||
{
|
{
|
||||||
case RCNT0_COUNT: ret = (u16)rcntRcount(0); break;
|
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).
|
// Most of the following case handlers are for developer builds only (logging).
|
||||||
// It'll all optimize to ziltch in public release builds.
|
// It'll all optimize to ziltch in public release builds.
|
||||||
|
#ifdef PCSX2_DEVBUILD
|
||||||
case 0x03:
|
case 0x03:
|
||||||
|
if((mem & 0xfff) < 0x800) break;
|
||||||
case 0x04:
|
case 0x04:
|
||||||
case 0x05:
|
case 0x05:
|
||||||
case 0x06:
|
case 0x06:
|
||||||
|
@ -305,34 +389,34 @@ mem32_t __fastcall hwRead32_generic(u32 mem)
|
||||||
case 0x08:
|
case 0x08:
|
||||||
case 0x09:
|
case 0x09:
|
||||||
case 0x0a:
|
case 0x0a:
|
||||||
|
case 0x0b:
|
||||||
|
case 0x0c:
|
||||||
case 0x0d:
|
case 0x0d:
|
||||||
{
|
{
|
||||||
const char* regName = "Unknown";
|
const char* regName = "Unknown";
|
||||||
|
|
||||||
switch( mem )
|
switch( mem & 0xf0)
|
||||||
{
|
{
|
||||||
case D2_CHCR: regName = "DMA2_CHCR"; break;
|
case 0x00: regName = "CHCR"; break;
|
||||||
case D2_MADR: regName = "DMA2_MADR"; break;
|
case 0x10: regName = "MADR"; break;
|
||||||
case D2_QWC: regName = "DMA2_QWC"; break;
|
case 0x20: regName = "QWC"; break;
|
||||||
case D2_TADR: regName = "DMA2_TADDR"; break;
|
case 0x30: regName = "TADR"; break;
|
||||||
case D2_ASR0: regName = "DMA2_ASR0"; break;
|
case 0x40: regName = "ASR0"; break;
|
||||||
case D2_ASR1: regName = "DMA2_ASR1"; break;
|
case 0x50: regName = "ASR1"; break;
|
||||||
case D2_SADR: regName = "DMA2_SADDR"; 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;
|
break;
|
||||||
|
#endif
|
||||||
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:
|
|
||||||
case 0x0e:
|
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)
|
if( mem == DMAC_STAT)
|
||||||
HW_LOG("DMAC_STAT Read32, value=0x%x", psHu32(DMAC_STAT));
|
HW_LOG("DMAC_STAT Read32, value=0x%x", psHu32(DMAC_STAT));
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
jNO_DEFAULT;
|
jNO_DEFAULT;
|
||||||
|
|
|
@ -24,167 +24,20 @@ using namespace R5900;
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
// DMA Execution Interfaces
|
// 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)
|
static bool QuickDmaExec( void (*func)(), u32 mem)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
||||||
Registers::Freeze();
|
|
||||||
|
|
||||||
DMACh *reg = &psH_DMACh(mem);
|
DMACh *reg = &psH_DMACh(mem);
|
||||||
|
|
||||||
if (reg->chcr.STR && dmacRegs->ctrl.DMAE && !psHu8(DMAC_ENABLER+2))
|
if (reg->chcr.STR && dmacRegs->ctrl.DMAE && !psHu8(DMAC_ENABLER+2))
|
||||||
{
|
{
|
||||||
|
Registers::Freeze();
|
||||||
func();
|
func();
|
||||||
|
Registers::Thaw();
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Registers::Thaw();
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,7 +48,7 @@ u32 oldvalue = 0;
|
||||||
void __fastcall StartQueuedDMA()
|
void __fastcall StartQueuedDMA()
|
||||||
{
|
{
|
||||||
if (QueuedDMA.VIF0) { DMA_LOG("Resuming DMA for VIF0"); if(QuickDmaExec(dmaVIF0, D0_CHCR) == true) QueuedDMA.VIF0 = false; }
|
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.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.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; }
|
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; }
|
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
|
// Hardware WRITE 8 bit
|
||||||
|
|
||||||
|
@ -277,105 +339,91 @@ void hwWrite8(u32 mem, u8 value)
|
||||||
// break;
|
// break;
|
||||||
case D0_CHCR + 1: // dma0 - vif0
|
case D0_CHCR + 1: // dma0 - vif0
|
||||||
DMA_LOG("VIF0dma EXECUTE, value=0x%x", value);
|
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);
|
DmaExec8(dmaVIF0, mem, value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D1_CHCR + 1: // dma1 - vif1
|
case D1_CHCR + 1: // dma1 - vif1
|
||||||
DMA_LOG("VIF1dma EXECUTE, value=0x%x", value);
|
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);
|
DmaExec8(dmaVIF1, mem, value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D2_CHCR + 1: // dma2 - gif
|
case D2_CHCR + 1: // dma2 - gif
|
||||||
DMA_LOG("GSdma EXECUTE, value=0x%x", value);
|
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);
|
DmaExec8(dmaGIF, mem, value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D3_CHCR + 1: // dma3 - fromIPU
|
case D3_CHCR + 1: // dma3 - fromIPU
|
||||||
DMA_LOG("IPU0dma EXECUTE, value=0x%x", value);
|
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);
|
DmaExec8(dmaIPU0, mem, value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D4_CHCR + 1: // dma4 - toIPU
|
case D4_CHCR + 1: // dma4 - toIPU
|
||||||
DMA_LOG("IPU1dma EXECUTE, value=0x%x", value);
|
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);
|
DmaExec8(dmaIPU1, mem, value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D5_CHCR + 1: // dma5 - sif0
|
case D5_CHCR + 1: // dma5 - sif0
|
||||||
DMA_LOG("SIF0dma EXECUTE, value=0x%x", value);
|
DMA_LOG("SIF0dma EXECUTE, value=0x%x", value);
|
||||||
// if (value == 0) psxSu32(0x30) = 0x40000;
|
// 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);
|
DmaExec8(dmaSIF0, mem, value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D6_CHCR + 1: // dma6 - sif1
|
case D6_CHCR + 1: // dma6 - sif1
|
||||||
DMA_LOG("SIF1dma EXECUTE, value=0x%x", value);
|
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);
|
DmaExec8(dmaSIF1, mem, value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D7_CHCR + 1: // dma7 - sif2
|
case D7_CHCR + 1: // dma7 - sif2
|
||||||
DMA_LOG("SIF2dma EXECUTE, value=0x%x", value);
|
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);
|
DmaExec8(dmaSIF2, mem, value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D8_CHCR + 1: // dma8 - fromSPR
|
case D8_CHCR + 1: // dma8 - fromSPR
|
||||||
DMA_LOG("fromSPRdma8 EXECUTE, value=0x%x", value);
|
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);
|
DmaExec8(dmaSPR0, mem, value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D9_CHCR + 1: // dma9 - toSPR
|
case D9_CHCR + 1: // dma9 - toSPR
|
||||||
DMA_LOG("toSPRdma8 EXECUTE, value=0x%x", value);
|
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);
|
DmaExec8(dmaSPR1, mem, value);
|
||||||
break;
|
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:
|
case DMAC_ENABLEW + 2:
|
||||||
oldvalue = psHu8(DMAC_ENABLEW + 2);
|
oldvalue = psHu8(DMAC_ENABLEW + 2);
|
||||||
|
@ -459,23 +507,11 @@ __forceinline void hwWrite16(u32 mem, u16 value)
|
||||||
|
|
||||||
case D0_CHCR: // dma0 - vif0
|
case D0_CHCR: // dma0 - vif0
|
||||||
DMA_LOG("VIF0dma %lx", value);
|
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);
|
DmaExec16(dmaVIF0, mem, value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D1_CHCR: // dma1 - vif1 - chcr
|
case D1_CHCR: // dma1 - vif1 - chcr
|
||||||
DMA_LOG("VIF1dma CHCR %lx", value);
|
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);
|
DmaExec16(dmaVIF1, mem, value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -514,11 +550,6 @@ __forceinline void hwWrite16(u32 mem, u16 value)
|
||||||
|
|
||||||
case D2_CHCR: // dma2 - gif
|
case D2_CHCR: // dma2 - gif
|
||||||
DMA_LOG("0x%8.8x hwWrite32: GSdma %lx", cpuRegs.cycle, value);
|
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);
|
DmaExec16(dmaGIF, mem, value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -556,11 +587,6 @@ __forceinline void hwWrite16(u32 mem, u16 value)
|
||||||
|
|
||||||
case D3_CHCR: // dma3 - fromIPU
|
case D3_CHCR: // dma3 - fromIPU
|
||||||
DMA_LOG("IPU0dma %lx", value);
|
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);
|
DmaExec16(dmaIPU0, mem, value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -588,11 +614,6 @@ __forceinline void hwWrite16(u32 mem, u16 value)
|
||||||
|
|
||||||
case D4_CHCR: // dma4 - toIPU
|
case D4_CHCR: // dma4 - toIPU
|
||||||
DMA_LOG("IPU1dma %lx", value);
|
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);
|
DmaExec16(dmaIPU1, mem, value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -619,26 +640,11 @@ __forceinline void hwWrite16(u32 mem, u16 value)
|
||||||
#endif
|
#endif
|
||||||
case D5_CHCR: // dma5 - sif0
|
case D5_CHCR: // dma5 - sif0
|
||||||
DMA_LOG("SIF0dma %lx", value);
|
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);
|
DmaExec16(dmaSIF0, mem, value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D5_CHCR + 2:
|
|
||||||
//?
|
|
||||||
break;
|
|
||||||
|
|
||||||
case D6_CHCR: // dma6 - sif1
|
case D6_CHCR: // dma6 - sif1
|
||||||
DMA_LOG("SIF1dma %lx", value);
|
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);
|
DmaExec16(dmaSIF1, mem, value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -666,38 +672,33 @@ __forceinline void hwWrite16(u32 mem, u16 value)
|
||||||
|
|
||||||
case D7_CHCR: // dma7 - sif2
|
case D7_CHCR: // dma7 - sif2
|
||||||
DMA_LOG("SIF2dma %lx", value);
|
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);
|
DmaExec16(dmaSIF2, mem, value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D7_CHCR + 2:
|
|
||||||
//?
|
|
||||||
break;
|
|
||||||
|
|
||||||
case D8_CHCR: // dma8 - fromSPR
|
case D8_CHCR: // dma8 - fromSPR
|
||||||
DMA_LOG("fromSPRdma %lx", value);
|
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);
|
DmaExec16(dmaSPR0, mem, value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D9_CHCR: // dma9 - toSPR
|
case D9_CHCR: // dma9 - toSPR
|
||||||
DMA_LOG("toSPRdma %lx", value);
|
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);
|
DmaExec16(dmaSPR1, mem, value);
|
||||||
break;
|
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:
|
case DMAC_ENABLEW + 2:
|
||||||
oldvalue = psHu8(DMAC_ENABLEW + 2);
|
oldvalue = psHu8(DMAC_ENABLEW + 2);
|
||||||
psHu16(DMAC_ENABLEW + 2) = value;
|
psHu16(DMAC_ENABLEW + 2) = value;
|
||||||
|
@ -853,11 +854,6 @@ void __fastcall hwWrite32_page_0B( u32 mem, u32 value )
|
||||||
{
|
{
|
||||||
case D3_CHCR: // dma3 - fromIPU
|
case D3_CHCR: // dma3 - fromIPU
|
||||||
DMA_LOG("IPU0dma EXECUTE, value=0x%x\n", value);
|
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);
|
DmaExec(dmaIPU0, mem, value);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -870,11 +866,6 @@ void __fastcall hwWrite32_page_0B( u32 mem, u32 value )
|
||||||
|
|
||||||
case D4_CHCR: // dma4 - toIPU
|
case D4_CHCR: // dma4 - toIPU
|
||||||
DMA_LOG("IPU1dma EXECUTE, value=0x%x\n", value);
|
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);
|
DmaExec(dmaIPU1, mem, value);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1013,35 +1004,12 @@ void __fastcall hwWrite32_generic( u32 mem, u32 value )
|
||||||
{
|
{
|
||||||
case D0_CHCR: // dma0 - vif0
|
case D0_CHCR: // dma0 - vif0
|
||||||
DMA_LOG("VIF0dma EXECUTE, value=0x%x", value);
|
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);
|
DmaExec(dmaVIF0, mem, value);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
case D1_CHCR: // dma1 - vif1 - chcr
|
case D1_CHCR: // dma1 - vif1 - chcr
|
||||||
DMA_LOG("VIF1dma EXECUTE, value=0x%x", value);
|
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
|
|
||||||
}
|
|
||||||
|
|
||||||
DmaExec(dmaVIF1, mem, value);
|
DmaExec(dmaVIF1, mem, value);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1055,11 +1023,6 @@ void __fastcall hwWrite32_generic( u32 mem, u32 value )
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
case D2_CHCR: // dma2 - gif
|
case D2_CHCR: // dma2 - gif
|
||||||
DMA_LOG("GIFdma EXECUTE, value=0x%x", value);
|
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);
|
DmaExec(dmaGIF, mem, value);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1073,22 +1036,11 @@ void __fastcall hwWrite32_generic( u32 mem, u32 value )
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
case D5_CHCR: // dma5 - sif0
|
case D5_CHCR: // dma5 - sif0
|
||||||
DMA_LOG("SIF0dma EXECUTE, value=0x%x", value);
|
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);
|
DmaExec(dmaSIF0, mem, value);
|
||||||
return;
|
return;
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
case D6_CHCR: // dma6 - sif1
|
case D6_CHCR: // dma6 - sif1
|
||||||
DMA_LOG("SIF1dma EXECUTE, value=0x%x", value);
|
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);
|
DmaExec(dmaSIF1, mem, value);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1099,31 +1051,16 @@ void __fastcall hwWrite32_generic( u32 mem, u32 value )
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
case D7_CHCR: // dma7 - sif2
|
case D7_CHCR: // dma7 - sif2
|
||||||
DMA_LOG("SIF2dma EXECUTE, value=0x%x", value);
|
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);
|
DmaExec(dmaSIF2, mem, value);
|
||||||
return;
|
return;
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
case D8_CHCR: // dma8 - fromSPR
|
case D8_CHCR: // dma8 - fromSPR
|
||||||
DMA_LOG("SPR0dma EXECUTE (fromSPR), value=0x%x", value);
|
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);
|
DmaExec(dmaSPR0, mem, value);
|
||||||
return;
|
return;
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
case D9_CHCR: // dma9 - toSPR
|
case D9_CHCR: // dma9 - toSPR
|
||||||
DMA_LOG("SPR1dma EXECUTE (toSPR), value=0x%x", value);
|
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);
|
DmaExec(dmaSPR1, mem, value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -249,6 +249,8 @@ __forceinline u32 ipuRead32(u32 mem)
|
||||||
|
|
||||||
IPU_LOG("Ipu read32: IPU_BP=0x%08X", *(u32*)&g_BP);
|
IPU_LOG("Ipu read32: IPU_BP=0x%08X", *(u32*)&g_BP);
|
||||||
return ipuRegs->ipubp;
|
return ipuRegs->ipubp;
|
||||||
|
default:
|
||||||
|
IPU_LOG("Ipu read32: Addr=0x%x Value = 0x%08X", mem, *(u32*)(((u8*)ipuRegs) + mem));
|
||||||
}
|
}
|
||||||
|
|
||||||
return *(u32*)(((u8*)ipuRegs) + mem);
|
return *(u32*)(((u8*)ipuRegs) + mem);
|
||||||
|
@ -1251,49 +1253,52 @@ static __forceinline void ipuDmacSrcChain()
|
||||||
{
|
{
|
||||||
case TAG_REFE: // refe
|
case TAG_REFE: // refe
|
||||||
//if(IPU1Status.InProgress == false) ipu1dma->tadr += 16;
|
//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;
|
break;
|
||||||
case TAG_CNT: // cnt
|
case TAG_CNT: // cnt
|
||||||
// Set the taddr to the next tag
|
// Set the taddr to the next tag
|
||||||
ipu1dma->tadr = ipu1dma->madr;
|
ipu1dma->tadr = ipu1dma->madr;
|
||||||
if(ipu1dma->qwc == 0 && IPU1Status.DMAFinished == false) IPU1Status.DMAFinished = false;
|
if(IPU1Status.DMAFinished == false) IPU1Status.DMAFinished = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TAG_NEXT: // next
|
case TAG_NEXT: // next
|
||||||
ipu1dma->tadr = IPU1Status.NextMem;
|
ipu1dma->tadr = IPU1Status.NextMem;
|
||||||
if(ipu1dma->qwc == 0 && IPU1Status.DMAFinished == false) IPU1Status.DMAFinished = false;
|
if(IPU1Status.DMAFinished == false) IPU1Status.DMAFinished = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TAG_REF: // ref
|
case TAG_REF: // ref
|
||||||
//if(IPU1Status.InProgress == false)ipu1dma->tadr += 16;
|
//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;
|
break;
|
||||||
|
|
||||||
case TAG_END: // end
|
case TAG_END: // end
|
||||||
ipu1dma->tadr = ipu1dma->madr;
|
ipu1dma->tadr = ipu1dma->madr;
|
||||||
if(ipu1dma->qwc == 0 && IPU1Status.DMAFinished == false) IPU1Status.DMAFinished = true;
|
if(IPU1Status.DMAFinished == false) IPU1Status.DMAFinished = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static __forceinline bool WaitGSPaths()
|
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);
|
if(GSTransferStatus.PTH3 < STOPPED_MODE)
|
||||||
//DevCon.WriteLn("Waiting for GIF");
|
{
|
||||||
return false;
|
//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)
|
if(GSTransferStatus.PTH2 != STOPPED_MODE)
|
||||||
{
|
{
|
||||||
//DevCon.WriteLn("Waiting for VIF");
|
//DevCon.WriteLn("Waiting for VIF");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(GSTransferStatus.PTH1 != STOPPED_MODE)
|
if(GSTransferStatus.PTH1 != STOPPED_MODE)
|
||||||
{
|
{
|
||||||
//DevCon.WriteLn("Waiting for VU");
|
//DevCon.WriteLn("Waiting for VU");
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1319,19 +1324,20 @@ static __forceinline int IPU1chain() {
|
||||||
qwc = ipu_fifo.in.write(pMem, qwc);
|
qwc = ipu_fifo.in.write(pMem, qwc);
|
||||||
ipu1dma->madr += qwc << 4;
|
ipu1dma->madr += qwc << 4;
|
||||||
ipu1dma->qwc -= qwc;
|
ipu1dma->qwc -= qwc;
|
||||||
totalqwc += 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.
|
|
||||||
}
|
}
|
||||||
|
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;
|
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);
|
IPU_LOG("Processing Chain QWC left %x Finished %d In Progress %d", ipu1dma->qwc, IPU1Status.DMAFinished, IPU1Status.InProgress);
|
||||||
totalqwc += IPU1chain();
|
totalqwc += IPU1chain();
|
||||||
//Set the TADR forward
|
//Set the TADR forward
|
||||||
ipuDmacSrcChain();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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);
|
IPU_LOG("Processing Start Chain QWC left %x Finished %d In Progress %d", ipu1dma->qwc, IPU1Status.DMAFinished, IPU1Status.InProgress);
|
||||||
totalqwc += IPU1chain();
|
totalqwc += IPU1chain();
|
||||||
//Set the TADR forward
|
//Set the TADR forward
|
||||||
ipuDmacSrcChain();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
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;
|
return totalqwc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1684,6 +1688,7 @@ IPU_FORCEINLINE void ipu1Interrupt()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IPU_LOG("ipu1 finish %x:", cpuRegs.cycle);
|
||||||
ipu1dma->chcr.STR = false;
|
ipu1dma->chcr.STR = false;
|
||||||
hwDmacIrq(DMAC_TO_IPU);
|
hwDmacIrq(DMAC_TO_IPU);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,8 @@ void IPU_Fifo::init()
|
||||||
void IPU_Fifo_Input::clear()
|
void IPU_Fifo_Input::clear()
|
||||||
{
|
{
|
||||||
memzero(data);
|
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;
|
g_BP.IFC = 0;
|
||||||
ipuRegs->ctrl.IFC = 0;
|
ipuRegs->ctrl.IFC = 0;
|
||||||
readpos = 0;
|
readpos = 0;
|
||||||
|
|
|
@ -257,6 +257,7 @@ void Pcsx2Config::GamefixOptions::LoadSave( IniInterface& ini )
|
||||||
IniBitBool( FpuMulHack );
|
IniBitBool( FpuMulHack );
|
||||||
IniBitBool( FpuNegDivHack );
|
IniBitBool( FpuNegDivHack );
|
||||||
IniBitBool( XgKickHack );
|
IniBitBool( XgKickHack );
|
||||||
|
IniBitBool( IPUWaitHack );
|
||||||
}
|
}
|
||||||
|
|
||||||
Pcsx2Config::Pcsx2Config()
|
Pcsx2Config::Pcsx2Config()
|
||||||
|
|
|
@ -40,7 +40,7 @@ void vif0Reset()
|
||||||
vif0Regs->stat.VPS = VPS_IDLE;
|
vif0Regs->stat.VPS = VPS_IDLE;
|
||||||
vif0Regs->stat.FQC = 0;
|
vif0Regs->stat.FQC = 0;
|
||||||
|
|
||||||
vif0.done = true;
|
vif0.done = false;
|
||||||
|
|
||||||
resetNewVif(0);
|
resetNewVif(0);
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ void vif1Reset()
|
||||||
vif1Regs->stat.VPS = VPS_IDLE;
|
vif1Regs->stat.VPS = VPS_IDLE;
|
||||||
vif1Regs->stat.FQC = 0; // FQC=0
|
vif1Regs->stat.FQC = 0; // FQC=0
|
||||||
|
|
||||||
vif1.done = true;
|
vif1.done = false;
|
||||||
cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's
|
cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's
|
||||||
|
|
||||||
resetNewVif(1);
|
resetNewVif(1);
|
||||||
|
@ -101,7 +101,7 @@ _f void vif0FBRST(u32 value) {
|
||||||
cpuRegs.interrupt &= ~1; //Stop all vif0 DMA's
|
cpuRegs.interrupt &= ~1; //Stop all vif0 DMA's
|
||||||
psHu64(VIF0_FIFO) = 0;
|
psHu64(VIF0_FIFO) = 0;
|
||||||
psHu64(VIF0_FIFO + 8) = 0;
|
psHu64(VIF0_FIFO + 8) = 0;
|
||||||
vif0.done = true;
|
vif0.done = false;
|
||||||
vif0Regs->err.reset();
|
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
|
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; //?
|
vif1ch->qwc = 0; //?
|
||||||
psHu64(VIF1_FIFO) = 0;
|
psHu64(VIF1_FIFO) = 0;
|
||||||
psHu64(VIF1_FIFO + 8) = 0;
|
psHu64(VIF1_FIFO + 8) = 0;
|
||||||
vif1.done = true;
|
vif1.done = false;
|
||||||
|
|
||||||
if(vif1Regs->mskpath3)
|
if(vif1Regs->mskpath3)
|
||||||
{
|
{
|
||||||
|
|
|
@ -99,7 +99,8 @@ bool _VIF1chain()
|
||||||
return true;
|
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();
|
vif1TransferFromMemory();
|
||||||
vif1.inprogress = 0;
|
vif1.inprogress = 0;
|
||||||
|
@ -305,6 +306,7 @@ void dmaVIF1()
|
||||||
vif1ch->chcr._u32, vif1ch->madr, vif1ch->qwc,
|
vif1ch->chcr._u32, vif1ch->madr, vif1ch->qwc,
|
||||||
vif1ch->tadr, vif1ch->asr0, vif1ch->asr1);
|
vif1ch->tadr, vif1ch->asr0, vif1ch->asr1);
|
||||||
|
|
||||||
|
vif1.done = false;
|
||||||
g_vifCycles = 0;
|
g_vifCycles = 0;
|
||||||
vif1.inprogress = 0;
|
vif1.inprogress = 0;
|
||||||
|
|
||||||
|
@ -332,9 +334,9 @@ void dmaVIF1()
|
||||||
Console.WriteLn("DMA Stall Control on VIF1 normal");
|
Console.WriteLn("DMA Stall Control on VIF1 normal");
|
||||||
|
|
||||||
if (vif1ch->chcr.DIR) // to Memory
|
if (vif1ch->chcr.DIR) // to Memory
|
||||||
vif1.dmamode = VIF_NORMAL_TO_MEM_MODE;
|
|
||||||
else
|
|
||||||
vif1.dmamode = VIF_NORMAL_FROM_MEM_MODE;
|
vif1.dmamode = VIF_NORMAL_FROM_MEM_MODE;
|
||||||
|
else
|
||||||
|
vif1.dmamode = VIF_NORMAL_TO_MEM_MODE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -344,6 +346,5 @@ void dmaVIF1()
|
||||||
vif1Regs->stat.FQC = min((u16)0x10, vif1ch->qwc);
|
vif1Regs->stat.FQC = min((u16)0x10, vif1ch->qwc);
|
||||||
|
|
||||||
// Chain Mode
|
// Chain Mode
|
||||||
vif1.done = false;
|
|
||||||
vif1Interrupt();
|
vif1Interrupt();
|
||||||
}
|
}
|
|
@ -220,6 +220,7 @@ void mfifoVIF1transfer(int qwc)
|
||||||
void vifMFIFOInterrupt()
|
void vifMFIFOInterrupt()
|
||||||
{
|
{
|
||||||
g_vifCycles = 0;
|
g_vifCycles = 0;
|
||||||
|
VIF_LOG("vif mfifo interrupt");
|
||||||
|
|
||||||
if (schedulepath3msk) Vif1MskPath3();
|
if (schedulepath3msk) Vif1MskPath3();
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,10 @@ Panels::GameFixesPanel::GameFixesPanel( wxWindow* parent ) :
|
||||||
{
|
{
|
||||||
_("VU XGkick Hack - for Erementar Gerad."),
|
_("VU XGkick Hack - for Erementar Gerad."),
|
||||||
wxEmptyString
|
wxEmptyString
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_("IPU Wait Hack - Fix Ripping/Corrupted videos (FFX, Digital Devil Saga), Causes others to cut short"),
|
||||||
|
wxEmptyString
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue