mirror of https://github.com/PCSX2/pcsx2.git
- Better implementation of Reverse FIFO (Fatal Frame QWC Warning and more!)
- Improved handling of suspended DMA's, Also some traps in case DMA values are changed during suspend (please report if they don't start with 5 or 6) - Better handling of GS Path priorities, this improves many Path3 Masked games such as Star Wars Episode 3, Gran Turismo 4 (slightly) and Videos like Digital Devil Saga/FFX - Removed Voodoo Cycles - Doesn't kill everything this time :P git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2853 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
e170324d51
commit
b1954edc3d
|
@ -401,7 +401,7 @@ static __forceinline const wxChar* ChcrName(u32 addr)
|
|||
case D6_CHCR: return L"Sif 1";
|
||||
case D7_CHCR: return L"Sif 2";
|
||||
case D8_CHCR: return L"SPR 0";
|
||||
case SPR1_CHCR: return L"SPR 1";
|
||||
case D9_CHCR: return L"SPR 1";
|
||||
default: return L"???";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,10 +60,15 @@ void __fastcall ReadFIFO_page_5(u32 mem, u64 *out)
|
|||
if (vif1Regs->stat.test(VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS) )
|
||||
DevCon.Warning( "Reading from vif1 fifo when stalled" );
|
||||
|
||||
if(vif1Regs->stat.FQC == 0) Console.Warning("FQC = 0 on VIF FIFO READ!");
|
||||
if (vif1Regs->stat.FDR)
|
||||
{
|
||||
if (--psHu32(D1_QWC) == 0)
|
||||
vif1Regs->stat.FQC = 0;
|
||||
if (vif1Regs->stat.FQC > 0)
|
||||
{
|
||||
GetMTGS().WaitGS();
|
||||
GSreadFIFO(&psHu64(VIF1_FIFO));
|
||||
}
|
||||
if(vif1Regs->stat.FQC > 0)--vif1Regs->stat.FQC;
|
||||
}
|
||||
|
||||
out[0] = psHu64(VIF1_FIFO);
|
||||
|
@ -184,4 +189,4 @@ void __fastcall WriteFIFO_page_7(u32 mem, const mem128_t *value)
|
|||
Threading::Timeslice();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ void gsReset()
|
|||
GetMTGS().ResetGS();
|
||||
|
||||
UpdateVSyncRate();
|
||||
|
||||
GSTransferStatus = (STOPPED_MODE<<4) | (STOPPED_MODE<<2) | STOPPED_MODE;
|
||||
memzero(g_RealGSMem);
|
||||
|
||||
GSCSRr = 0x551B4000; // Set the FINISH bit to 1 for now
|
||||
|
|
|
@ -56,22 +56,7 @@ __forceinline void gsInterrupt()
|
|||
}
|
||||
|
||||
|
||||
|
||||
if ((vif1.cmd & 0x7e) == 0x50) // DIRECT/HL
|
||||
{
|
||||
|
||||
//original behaviour here - if (Path3progress != IMAGE_MODE) vif1Regs->stat.VGW = false;
|
||||
|
||||
// Transfer in progress on VIF and GIF has finished so let VIF do its bit
|
||||
if (Path3progress == STOPPED_MODE)
|
||||
{
|
||||
vif1Regs->stat.VGW = false;
|
||||
CPU_INT( DMAC_GIF, 4 );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (Path3progress == STOPPED_MODE)
|
||||
if (GSTransferStatus.PTH3 == STOPPED_MODE)
|
||||
{
|
||||
gifRegs->stat.clear_flags(GIF_STAT_APATH3 | GIF_STAT_OPH);
|
||||
}
|
||||
|
@ -90,12 +75,15 @@ __forceinline void gsInterrupt()
|
|||
return;
|
||||
}
|
||||
|
||||
if((gif->chcr.MOD == CHAIN_MODE) && ((gif->chcr.TAG >> 12) & 0x7) != 0x0 && ((gif->chcr.TAG >> 12) & 0x7) != 0x7 && !((gif->chcr.TAG >> 12) & 0x8))
|
||||
DevCon.Warning("GIF Ending when refe or end not set! CHCR = %x", gif->chcr._u32);
|
||||
|
||||
gspath3done = false;
|
||||
gscycles = 0;
|
||||
gif->chcr.STR = false;
|
||||
vif1Regs->stat.VGW = false;
|
||||
|
||||
gifRegs->stat.clear_flags(GIF_STAT_APATH3 | GIF_STAT_OPH | GIF_STAT_P3Q | GIF_STAT_FQC);
|
||||
gifRegs->stat.clear_flags(GIF_STAT_APATH3 | GIF_STAT_OPH | GIF_STAT_FQC);
|
||||
|
||||
clearFIFOstuff(false);
|
||||
hwDmacIrq(DMAC_GIF);
|
||||
|
@ -104,9 +92,6 @@ __forceinline void gsInterrupt()
|
|||
|
||||
static u32 WRITERING_DMA(u32 *pMem, u32 qwc)
|
||||
{
|
||||
gifRegs->stat.APATH = GIF_APATH3;
|
||||
gifRegs->stat.OPH = true;
|
||||
|
||||
int size = GetMTGS().PrepDataPacket(GIF_PATH_3, pMem, qwc);
|
||||
u8* pgsmem = GetMTGS().GetDataPacketPtr();
|
||||
|
||||
|
@ -216,16 +201,24 @@ void GIFdma()
|
|||
}
|
||||
|
||||
clearFIFOstuff(true);
|
||||
gifRegs->stat.FQC |= 0x10;// 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]
|
||||
|
||||
//Path2 gets priority in intermittent mode
|
||||
if ((gifRegs->stat.P1Q || (vif1.cmd & 0x7e) == 0x50) && gifRegs->mode.IMT && (Path3progress == STOPPED_MODE))
|
||||
if (GSTransferStatus.PTH1 != STOPPED_MODE || GSTransferStatus.PTH2 != STOPPED_MODE)
|
||||
{
|
||||
// We are in image mode doing DIRECTHL, Path 1 is in queue, and in intermittant mode.
|
||||
GIF_LOG("Waiting VU %x, PATH2 %x, GIFMODE %x Progress %x", gifRegs->stat.P1Q, (vif1.cmd & 0x7f), gifRegs->mode._u32, Path3progress);
|
||||
//GIF_LOG("Waiting VU %x, PATH2 %x, GIFMODE %x Progress %x", gifRegs->stat.P1Q, (vif1.cmd & 0x7f), gifRegs->mode._u32, GSTransferStatus.PTH3);
|
||||
/*if(GSTransferStatus.PTH3 == STOPPED_MODE)
|
||||
{
|
||||
|
||||
} else Console.Warning("PATH3 Transfer in action while another one path is running, Path3 mode %x", GSTransferStatus.PTH3);*/
|
||||
gifRegs->stat.set_flags(GIF_STAT_P2Q);
|
||||
CPU_INT(DMAC_GIF, 16);
|
||||
return;
|
||||
}
|
||||
gifRegs->stat.clear_flags(GIF_STAT_P2Q);
|
||||
gifRegs->stat.APATH = GIF_APATH3;
|
||||
gifRegs->stat.OPH = true;
|
||||
|
||||
if (vif1Regs->mskpath3 || gifRegs->mode.M3R)
|
||||
{
|
||||
|
@ -234,6 +227,7 @@ void GIFdma()
|
|||
if ((gif->chcr.MOD == CHAIN_MODE) && gif->chcr.STR)
|
||||
{
|
||||
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);
|
||||
|
||||
|
@ -242,15 +236,17 @@ void GIFdma()
|
|||
}
|
||||
}
|
||||
|
||||
if (Path3progress == STOPPED_MODE) /*|| (vif1Regs->stat._u32 |= VIF1_STAT_VGW) == 0*/
|
||||
if (GSTransferStatus.PTH3 == STOPPED_MODE) /*|| (vif1Regs->stat._u32 |= VIF1_STAT_VGW) == 0*/
|
||||
{
|
||||
GIF_LOG("PTH3 MASK Continuing VIF");
|
||||
vif1Regs->stat.VGW = false;
|
||||
if (gif->qwc == 0) CPU_INT(DMAC_GIF, 16);
|
||||
return;
|
||||
}
|
||||
|
||||
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]
|
||||
//Check with Path3 masking games
|
||||
if (gif->qwc > 0) {
|
||||
GIF_LOG("PTH3 MASK Transferring", ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr);
|
||||
GIFchain();
|
||||
CPU_INT(DMAC_GIF, gscycles * BIAS);
|
||||
return;
|
||||
|
@ -266,7 +262,7 @@ void GIFdma()
|
|||
{
|
||||
Console.WriteLn("DMA Stall Control on GIF normal");
|
||||
}
|
||||
|
||||
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]
|
||||
//Check with Path3 masking games
|
||||
if (gif->qwc > 0) {
|
||||
GIFchain(); //Transfers the data set by the switch
|
||||
|
@ -284,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);
|
||||
|
||||
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)
|
||||
{
|
||||
// there are still bugs, need to also check if gif->madr +16*qwc >= stadr, if not, stall
|
||||
|
@ -325,6 +321,7 @@ void GIFdma()
|
|||
CPU_INT(DMAC_GIF, gscycles * BIAS);
|
||||
gscycles = 0;
|
||||
}
|
||||
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]
|
||||
}
|
||||
|
||||
void dmaGIF()
|
||||
|
@ -333,7 +330,7 @@ void dmaGIF()
|
|||
//It takes the time of 24 QW for the BUS to become ready - The Punisher And Streetball
|
||||
GIF_LOG("dmaGIFstart chcr = %lx, madr = %lx, qwc = %lx\n tadr = %lx, asr0 = %lx, asr1 = %lx", gif->chcr._u32, gif->madr, gif->qwc, gif->tadr, gif->asr0, gif->asr1);
|
||||
|
||||
Path3progress = STOPPED_MODE;
|
||||
GSTransferStatus.PTH3 = STOPPED_MODE;
|
||||
gspath3done = false; // For some reason this doesn't clear? So when the system starts the thread, we will clear it :)
|
||||
|
||||
gifRegs->stat.P3Q = true;
|
||||
|
@ -546,7 +543,7 @@ void gifMFIFOInterrupt()
|
|||
//Console.WriteLn("gifMFIFOInterrupt");
|
||||
mfifocycles = 0;
|
||||
|
||||
if (Path3progress == STOPPED_MODE)
|
||||
if (GSTransferStatus.PTH3 == STOPPED_MODE)
|
||||
{
|
||||
gifRegs->stat.APATH = GIF_APATH_IDLE;
|
||||
gifRegs->stat.OPH = false;
|
||||
|
@ -565,9 +562,9 @@ void gifMFIFOInterrupt()
|
|||
return;
|
||||
}
|
||||
|
||||
if ((gifRegs->stat.P1Q || (vif1.cmd & 0x7f) == 0x50) && gifRegs->mode.IMT && Path3progress == IMAGE_MODE) //Path2 gets priority in intermittent mode
|
||||
if ((gifRegs->stat.P1Q || (vif1.cmd & 0x7f) == 0x50) && gifRegs->mode.IMT && GSTransferStatus.PTH3 == IMAGE_MODE) //Path2 gets priority in intermittent mode
|
||||
{
|
||||
//GIF_LOG("Waiting VU %x, PATH2 %x, GIFMODE %x Progress %x", psHu32(GIF_STAT) & 0x100, (vif1.cmd & 0x7f), psHu32(GIF_MODE), Path3progress);
|
||||
//GIF_LOG("Waiting VU %x, PATH2 %x, GIFMODE %x Progress %x", psHu32(GIF_STAT) & 0x100, (vif1.cmd & 0x7f), psHu32(GIF_MODE), GSTransferStatus.PTH3);
|
||||
CPU_INT(11,mfifocycles);
|
||||
return;
|
||||
}
|
||||
|
@ -620,4 +617,4 @@ void SaveStateBase::gifFreeze()
|
|||
Freeze( gscycles );
|
||||
//Freeze(gifempty);
|
||||
// Note: mfifocycles is not a persistent var, so no need to save it here.
|
||||
}
|
||||
}
|
||||
|
|
22
pcsx2/Gif.h
22
pcsx2/Gif.h
|
@ -26,13 +26,29 @@ enum gifstate_t
|
|||
GIF_STATE_EMPTY = 0x10
|
||||
};
|
||||
|
||||
enum Path3Modes //0 = Image Mode (DirectHL), 1 = transferring, 2 = Stopped at End of Packet
|
||||
enum GSTransferModes //0 = Image Mode (DirectHL), 1 = transferring, 2 = Stopped at End of Packet
|
||||
{
|
||||
IMAGE_MODE = 0,
|
||||
TRANSFER_MODE = 1,
|
||||
STOPPED_MODE = 2
|
||||
};
|
||||
|
||||
union tGSTransferStatus {
|
||||
struct {
|
||||
u32 PTH1 : 2; // Resets Vif(0/1) when written.
|
||||
u32 PTH2 : 2; // Causes a Forcebreak to Vif((0/1) when true. (Stall)
|
||||
u32 PTH3 : 2; // Stops after the end of the Vifcode in progress when true. (Stall)
|
||||
u32 reserved : 26;
|
||||
};
|
||||
u32 _u32;
|
||||
|
||||
tGSTransferStatus(u32 val) { _u32 = val; }
|
||||
bool test (u32 flags) const { return !!(_u32 & flags); }
|
||||
void set_flags (u32 flags) { _u32 |= flags; }
|
||||
void clear_flags(u32 flags) { _u32 &= ~flags; }
|
||||
void reset() { _u32 = 0; }
|
||||
wxString desc() const { return wxsFormat(L"GSTransferStatus.PTH3: 0x%x", _u32); }
|
||||
};
|
||||
//GIF_STAT
|
||||
enum gif_stat_flags
|
||||
{
|
||||
|
@ -262,7 +278,7 @@ struct GIFregisters
|
|||
|
||||
#define gifRegs ((GIFregisters*)(PS2MEM_HW+0x3000))
|
||||
|
||||
extern Path3Modes Path3progress;
|
||||
extern tGSTransferStatus GSTransferStatus;
|
||||
|
||||
extern void gsInterrupt();
|
||||
extern int _GIFchain();
|
||||
|
@ -271,4 +287,4 @@ extern void dmaGIF();
|
|||
extern void mfifoGIFtransfer(int qwc);
|
||||
extern void gifMFIFOInterrupt();
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -186,7 +186,7 @@ enum EERegisterAddresses
|
|||
D8_MADR = 0x1000D010,
|
||||
D8_QWC = 0x1000D020,
|
||||
D8_SADR = 0x1000D080,
|
||||
SPR1_CHCR = 0x1000D400,
|
||||
D9_CHCR = 0x1000D400,
|
||||
|
||||
DMAC_CTRL = 0x1000E000,
|
||||
DMAC_STAT = 0x1000E010,
|
||||
|
|
|
@ -46,7 +46,7 @@ static __forceinline void DmaExec8( void (*func)(), u32 mem, u8 value )
|
|||
}
|
||||
|
||||
psHu8(mem) = (u8)value;
|
||||
if ((psHu8(mem) & 0x1) && dmacRegs->ctrl.DMAE)
|
||||
if ((psHu8(mem) & 0x1) && dmacRegs->ctrl.DMAE && !psHu8(DMAC_ENABLER+2))
|
||||
{
|
||||
/*Console.WriteLn("Running DMA 8 %x", psHu32(mem & ~0x1));*/
|
||||
func();
|
||||
|
@ -80,7 +80,7 @@ static __forceinline void DmaExec16( void (*func)(), u32 mem, u16 value )
|
|||
}
|
||||
|
||||
psHu16(mem) = chcr.lower();
|
||||
if (reg->chcr.STR && dmacRegs->ctrl.DMAE)
|
||||
if (reg->chcr.STR && dmacRegs->ctrl.DMAE && !psHu8(DMAC_ENABLER+2))
|
||||
{
|
||||
//Console.WriteLn("16bit DMA Start");
|
||||
func();
|
||||
|
@ -97,10 +97,13 @@ static void DmaExec( void (*func)(), u32 mem, u32 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) {
|
||||
DevCon.Warning(L"DMAExec32 Attempt to run DMA while one is already active in %s(%x)", ChcrName(mem), mem);
|
||||
if((reg->chcr._u32 & 0xff) == (chcr._u32 & 0xff)) //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);
|
||||
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();
|
||||
//func();
|
||||
Registers::Thaw();
|
||||
return; // Test with Gust games and fatal frame
|
||||
}
|
||||
|
@ -122,17 +125,53 @@ static void DmaExec( void (*func)(), u32 mem, u32 value )
|
|||
else /* Else (including Normal mode etc) write whatever the hardware sends*/
|
||||
reg->chcr.set(value);
|
||||
|
||||
if (reg->chcr.STR && dmacRegs->ctrl.DMAE) func();
|
||||
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))
|
||||
{
|
||||
func();
|
||||
ret = true;
|
||||
}
|
||||
|
||||
Registers::Thaw();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
tDMAC_QUEUE QueuedDMA(0);
|
||||
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.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; }
|
||||
if (QueuedDMA.SIF0) { DMA_LOG("Resuming DMA for SIF0"); if(QuickDmaExec(dmaSIF0, D5_CHCR) == true) QueuedDMA.SIF0 = false; }
|
||||
if (QueuedDMA.SIF1) { DMA_LOG("Resuming DMA for SIF1"); if(QuickDmaExec(dmaSIF1, D6_CHCR) == true) QueuedDMA.SIF1 = false; }
|
||||
if (QueuedDMA.SIF2) { DMA_LOG("Resuming DMA for SIF2"); if(QuickDmaExec(dmaSIF2, D7_CHCR) == true) QueuedDMA.SIF2 = false; }
|
||||
if (QueuedDMA.SPR0) { DMA_LOG("Resuming DMA for SPR0"); if(QuickDmaExec(dmaSPR0, D8_CHCR) == true) QueuedDMA.SPR0 = false; }
|
||||
if (QueuedDMA.SPR1) { DMA_LOG("Resuming DMA for SPR1"); if(QuickDmaExec(dmaSPR1, D9_CHCR) == true) QueuedDMA.SPR1 = false; }
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Hardware WRITE 8 bit
|
||||
|
||||
char sio_buffer[1024];
|
||||
int sio_count;
|
||||
tDMAC_QUEUE QueuedDMA(0);
|
||||
|
||||
|
||||
void hwWrite8(u32 mem, u8 value)
|
||||
{
|
||||
|
@ -200,9 +239,9 @@ void hwWrite8(u32 mem, u8 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");
|
||||
//DevCon.Warning("8 bit VIF0 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.VIF0 = true;
|
||||
}
|
||||
} else QueuedDMA.VIF0 = false;
|
||||
DmaExec8(dmaVIF0, mem, value);
|
||||
break;
|
||||
|
||||
|
@ -210,9 +249,9 @@ void hwWrite8(u32 mem, u8 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");
|
||||
//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;
|
||||
|
@ -221,9 +260,9 @@ void hwWrite8(u32 mem, u8 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");
|
||||
//DevCon.Warning("8 bit GIF DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.GIF = true;
|
||||
}
|
||||
} else QueuedDMA.GIF = false;
|
||||
DmaExec8(dmaGIF, mem, value);
|
||||
break;
|
||||
|
||||
|
@ -231,9 +270,9 @@ void hwWrite8(u32 mem, u8 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");
|
||||
//DevCon.Warning("8 bit IPU0 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.IPU0 = true;
|
||||
}
|
||||
} else QueuedDMA.IPU0 = false;
|
||||
DmaExec8(dmaIPU0, mem, value);
|
||||
break;
|
||||
|
||||
|
@ -241,9 +280,9 @@ void hwWrite8(u32 mem, u8 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");
|
||||
//DevCon.Warning("8 bit IPU1 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.IPU1 = true;
|
||||
}
|
||||
} else QueuedDMA.IPU1 = false;
|
||||
DmaExec8(dmaIPU1, mem, value);
|
||||
break;
|
||||
|
||||
|
@ -252,9 +291,9 @@ void hwWrite8(u32 mem, u8 value)
|
|||
// if (value == 0) psxSu32(0x30) = 0x40000;
|
||||
if ((value & 0x1) && !dmacRegs->ctrl.DMAE)
|
||||
{
|
||||
DevCon.Warning("8 bit SIF0 DMA Start while DMAC Disabled\n");
|
||||
//DevCon.Warning("8 bit SIF0 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.SIF0 = true;
|
||||
}
|
||||
} else QueuedDMA.SIF0 = false;
|
||||
DmaExec8(dmaSIF0, mem, value);
|
||||
break;
|
||||
|
||||
|
@ -262,9 +301,9 @@ void hwWrite8(u32 mem, u8 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");
|
||||
//DevCon.Warning("8 bit SIF1 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.SIF1 = true;
|
||||
}
|
||||
} else QueuedDMA.SIF1 = false;
|
||||
DmaExec8(dmaSIF1, mem, value);
|
||||
break;
|
||||
|
||||
|
@ -272,9 +311,9 @@ void hwWrite8(u32 mem, u8 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");
|
||||
//DevCon.Warning("8 bit SIF2 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.SIF2 |= true;
|
||||
}
|
||||
} else QueuedDMA.SIF2 = false;
|
||||
DmaExec8(dmaSIF2, mem, value);
|
||||
break;
|
||||
|
||||
|
@ -282,25 +321,30 @@ void hwWrite8(u32 mem, u8 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");
|
||||
//DevCon.Warning("8 bit SPR0 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.SPR0 = true;
|
||||
}
|
||||
} else QueuedDMA.SPR0 = false;
|
||||
DmaExec8(dmaSPR0, mem, value);
|
||||
break;
|
||||
|
||||
case SPR1_CHCR + 1: // dma9 - toSPR
|
||||
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");
|
||||
//DevCon.Warning("8 bit SPR1 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA .SPR1 = true;
|
||||
}
|
||||
} else QueuedDMA.SPR1 = false;
|
||||
DmaExec8(dmaSPR1, mem, value);
|
||||
break;
|
||||
|
||||
case DMAC_ENABLEW + 2:
|
||||
oldvalue = psHu8(DMAC_ENABLEW + 2);
|
||||
psHu8(DMAC_ENABLEW + 2) = value;
|
||||
psHu8(DMAC_ENABLER + 2) = value;
|
||||
if (((oldvalue & 0x1) == 1) && ((value & 0x1) == 0))
|
||||
{
|
||||
if (!QueuedDMA.empty()) StartQueuedDMA();
|
||||
}
|
||||
break;
|
||||
|
||||
case SBUS_F200: // SIF(?)
|
||||
|
@ -375,21 +419,21 @@ __forceinline void hwWrite16(u32 mem, u16 value)
|
|||
|
||||
case D0_CHCR: // dma0 - vif0
|
||||
DMA_LOG("VIF0dma %lx", value);
|
||||
if (CHCR(value).STR && !dmacRegs->ctrl.DMAE)
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
DevCon.Warning("16 bit VIF0 DMA Start while DMAC Disabled\n");
|
||||
//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)
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
DevCon.Warning("16 bit VIF1 DMA Start while DMAC Disabled\n");
|
||||
//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);
|
||||
|
@ -430,11 +474,11 @@ __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)
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
DevCon.Warning("16 bit GIF DMA Start while DMAC Disabled\n");
|
||||
//DevCon.Warning("16 bit GIF DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.GIF = true;
|
||||
}
|
||||
} else QueuedDMA.GIF = false;
|
||||
DmaExec16(dmaGIF, mem, value);
|
||||
break;
|
||||
|
||||
|
@ -472,11 +516,11 @@ __forceinline void hwWrite16(u32 mem, u16 value)
|
|||
|
||||
case D3_CHCR: // dma3 - fromIPU
|
||||
DMA_LOG("IPU0dma %lx", value);
|
||||
if (CHCR(value).STR && !dmacRegs->ctrl.DMAE)
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
DevCon.Warning("16 bit IPU0 DMA Start while DMAC Disabled\n");
|
||||
//DevCon.Warning("16 bit IPU0 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.IPU0 = true;
|
||||
}
|
||||
} else QueuedDMA.IPU0 = false;
|
||||
DmaExec16(dmaIPU0, mem, value);
|
||||
break;
|
||||
|
||||
|
@ -504,11 +548,11 @@ __forceinline void hwWrite16(u32 mem, u16 value)
|
|||
|
||||
case D4_CHCR: // dma4 - toIPU
|
||||
DMA_LOG("IPU1dma %lx", value);
|
||||
if (CHCR(value).STR && !dmacRegs->ctrl.DMAE)
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
DevCon.Warning("16 bit IPU1 DMA Start while DMAC Disabled\n");
|
||||
//DevCon.Warning("16 bit IPU1 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.IPU1 = true;
|
||||
}
|
||||
} else QueuedDMA.IPU1 = false;
|
||||
DmaExec16(dmaIPU1, mem, value);
|
||||
break;
|
||||
|
||||
|
@ -536,11 +580,11 @@ __forceinline void hwWrite16(u32 mem, u16 value)
|
|||
case D5_CHCR: // dma5 - sif0
|
||||
DMA_LOG("SIF0dma %lx", value);
|
||||
// if (value == 0) psxSu32(0x30) = 0x40000;
|
||||
if (CHCR(value).STR && !dmacRegs->ctrl.DMAE)
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
DevCon.Warning("16 bit SIF0 DMA Start while DMAC Disabled\n");
|
||||
//DevCon.Warning("16 bit SIF0 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.SIF0 = true;
|
||||
}
|
||||
} else QueuedDMA.SIF0 = false;
|
||||
DmaExec16(dmaSIF0, mem, value);
|
||||
break;
|
||||
|
||||
|
@ -550,11 +594,11 @@ __forceinline void hwWrite16(u32 mem, u16 value)
|
|||
|
||||
case D6_CHCR: // dma6 - sif1
|
||||
DMA_LOG("SIF1dma %lx", value);
|
||||
if (CHCR(value).STR && !dmacRegs->ctrl.DMAE)
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
DevCon.Warning("16 bit SIF1 DMA Start while DMAC Disabled\n");
|
||||
//DevCon.Warning("16 bit SIF1 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.SIF1 = true;
|
||||
}
|
||||
} else QueuedDMA.SIF1 = false;
|
||||
DmaExec16(dmaSIF1, mem, value);
|
||||
break;
|
||||
|
||||
|
@ -582,11 +626,11 @@ __forceinline void hwWrite16(u32 mem, u16 value)
|
|||
|
||||
case D7_CHCR: // dma7 - sif2
|
||||
DMA_LOG("SIF2dma %lx", value);
|
||||
if (CHCR(value).STR && !dmacRegs->ctrl.DMAE)
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
DevCon.Warning("16 bit SIF2 DMA Start while DMAC Disabled\n");
|
||||
//DevCon.Warning("16 bit SIF2 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.SIF2 = true;
|
||||
}
|
||||
} else QueuedDMA.SIF2 = false;
|
||||
DmaExec16(dmaSIF2, mem, value);
|
||||
break;
|
||||
|
||||
|
@ -596,27 +640,32 @@ __forceinline void hwWrite16(u32 mem, u16 value)
|
|||
|
||||
case D8_CHCR: // dma8 - fromSPR
|
||||
DMA_LOG("fromSPRdma %lx", value);
|
||||
if (CHCR(value).STR && !dmacRegs->ctrl.DMAE)
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
DevCon.Warning("16 bit SPR0 DMA Start while DMAC Disabled\n");
|
||||
//DevCon.Warning("16 bit SPR0 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.SPR0 = true;
|
||||
}
|
||||
} else QueuedDMA.SPR0 = false;
|
||||
DmaExec16(dmaSPR0, mem, value);
|
||||
break;
|
||||
|
||||
case SPR1_CHCR: // dma9 - toSPR
|
||||
case D9_CHCR: // dma9 - toSPR
|
||||
DMA_LOG("toSPRdma %lx", value);
|
||||
if (CHCR(value).STR && !dmacRegs->ctrl.DMAE)
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
DevCon.Warning("16 bit SPR1 DMA Start while DMAC Disabled\n");
|
||||
//DevCon.Warning("16 bit SPR1 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.SPR1 = true;
|
||||
}
|
||||
} else QueuedDMA.SPR1 = false;
|
||||
DmaExec16(dmaSPR1, mem, value);
|
||||
break;
|
||||
|
||||
case DMAC_ENABLEW + 2:
|
||||
oldvalue = psHu8(DMAC_ENABLEW + 2);
|
||||
psHu16(DMAC_ENABLEW + 2) = value;
|
||||
psHu16(DMAC_ENABLER + 2) = value;
|
||||
if (((oldvalue & 0x1) == 1) && ((value & 0x1) == 0))
|
||||
{
|
||||
if (!QueuedDMA.empty()) StartQueuedDMA();
|
||||
}
|
||||
break;
|
||||
|
||||
case SIO_ISR:
|
||||
|
@ -764,11 +813,11 @@ 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)
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
DevCon.Warning("32 bit IPU0 DMA Start while DMAC Disabled\n");
|
||||
//DevCon.Warning("32 bit IPU0 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.IPU0 = true;
|
||||
}
|
||||
} else QueuedDMA.IPU0 = false;
|
||||
DmaExec(dmaIPU0, mem, value);
|
||||
return;
|
||||
|
||||
|
@ -781,11 +830,11 @@ 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)
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
DevCon.Warning("32 bit IPU1 DMA Start while DMAC Disabled\n");
|
||||
//DevCon.Warning("32 bit IPU1 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.IPU1 = true;
|
||||
}
|
||||
} else QueuedDMA.IPU1 = false;
|
||||
DmaExec(dmaIPU1, mem, value);
|
||||
return;
|
||||
|
||||
|
@ -799,19 +848,7 @@ void __fastcall hwWrite32_page_0B( u32 mem, u32 value )
|
|||
psHu32(mem) = value;
|
||||
}
|
||||
|
||||
void __fastcall StartQueuedDMA()
|
||||
{
|
||||
if (QueuedDMA.VIF0) { QueuedDMA.VIF0 = false; dmaVIF0(); }
|
||||
if (QueuedDMA.VIF1) { QueuedDMA.VIF1 = false; dmaVIF1(); }
|
||||
if (QueuedDMA.GIF ) { QueuedDMA.GIF = false; dmaGIF(); }
|
||||
if (QueuedDMA.IPU0) { QueuedDMA.IPU0 = false; dmaIPU0(); }
|
||||
if (QueuedDMA.IPU1) { QueuedDMA.IPU1 = false; dmaIPU1(); }
|
||||
if (QueuedDMA.SIF0) { QueuedDMA.SIF0 = false; dmaSIF0(); }
|
||||
if (QueuedDMA.SIF1) { QueuedDMA.SIF1 = false; dmaSIF1(); }
|
||||
if (QueuedDMA.SIF2) { QueuedDMA.SIF2 = false; dmaSIF2(); }
|
||||
if (QueuedDMA.SPR0) { QueuedDMA.SPR0 = false; dmaSPR0(); }
|
||||
if (QueuedDMA.SPR1) { QueuedDMA.SPR1 = false; dmaSPR1(); }
|
||||
}
|
||||
|
||||
|
||||
void __fastcall hwWrite32_page_0E( u32 mem, u32 value )
|
||||
{
|
||||
|
@ -907,8 +944,13 @@ void __fastcall hwWrite32_page_0F( u32 mem, u32 value )
|
|||
|
||||
case HELPSWITCH(DMAC_ENABLEW):
|
||||
HW_LOG("DMAC_ENABLEW Write 32bit %lx", value);
|
||||
oldvalue = psHu8(DMAC_ENABLEW + 2);
|
||||
psHu32(DMAC_ENABLEW) = value;
|
||||
psHu32(DMAC_ENABLER) = value;
|
||||
if (((oldvalue & 0x1) == 1) && (((value >> 16) & 0x1) == 0))
|
||||
{
|
||||
if (!QueuedDMA.empty()) StartQueuedDMA();
|
||||
}
|
||||
break;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
@ -932,11 +974,11 @@ 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)
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
DevCon.Warning("32 bit VIF0 DMA Start while DMAC Disabled\n");
|
||||
//DevCon.Warning("32 bit VIF0 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.VIF0 = true;
|
||||
}
|
||||
} else QueuedDMA.VIF0 = false;
|
||||
|
||||
DmaExec(dmaVIF0, mem, value);
|
||||
return;
|
||||
|
@ -945,11 +987,11 @@ void __fastcall hwWrite32_generic( u32 mem, u32 value )
|
|||
case D1_CHCR: // dma1 - vif1 - chcr
|
||||
DMA_LOG("VIF1dma EXECUTE, value=0x%x", value);
|
||||
|
||||
if (CHCR(value).STR && !dmacRegs->ctrl.DMAE)
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
DevCon.Warning("32 bit VIF1 DMA Start while DMAC Disabled\n");
|
||||
//DevCon.Warning("32 bit VIF1 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.VIF1 = true;
|
||||
}
|
||||
} else QueuedDMA.VIF1 = false;
|
||||
|
||||
if (CHCR(value).STR)
|
||||
{
|
||||
|
@ -973,11 +1015,11 @@ 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)
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
DevCon.Warning("32 bit GIF DMA Start while DMAC Disabled\n");
|
||||
//DevCon.Warning("32 bit GIF DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.GIF = true;
|
||||
}
|
||||
} else QueuedDMA.GIF = false;
|
||||
DmaExec(dmaGIF, mem, value);
|
||||
return;
|
||||
|
||||
|
@ -992,21 +1034,21 @@ 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)
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
DevCon.Warning("32 bit SIF0 DMA Start while DMAC Disabled\n");
|
||||
//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)
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
DevCon.Warning("32 bit SIF1 DMA Start while DMAC Disabled\n");
|
||||
//DevCon.Warning("32 bit SIF1 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.SIF1 = true;
|
||||
}
|
||||
} else QueuedDMA.SIF1 = false;
|
||||
DmaExec(dmaSIF1, mem, value);
|
||||
return;
|
||||
|
||||
|
@ -1017,31 +1059,31 @@ 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)
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
DevCon.Warning("32 bit SIF2 DMA Start while DMAC Disabled\n");
|
||||
//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)
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
DevCon.Warning("32 bit SPR0 DMA Start while DMAC Disabled\n");
|
||||
//DevCon.Warning("32 bit SPR0 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.SPR0 = true;
|
||||
}
|
||||
} else QueuedDMA.SPR0 = false;
|
||||
DmaExec(dmaSPR0, mem, value);
|
||||
return;
|
||||
//------------------------------------------------------------------
|
||||
case SPR1_CHCR: // dma9 - toSPR
|
||||
case D9_CHCR: // dma9 - toSPR
|
||||
DMA_LOG("SPR1dma EXECUTE (toSPR), value=0x%x", value);
|
||||
if (CHCR(value).STR && !dmacRegs->ctrl.DMAE)
|
||||
if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)))
|
||||
{
|
||||
DevCon.Warning("32 bit SPR1 DMA Start while DMAC Disabled\n");
|
||||
//DevCon.Warning("32 bit SPR1 DMA Start while DMAC Disabled\n");
|
||||
QueuedDMA.SPR1 = true;
|
||||
}
|
||||
} else QueuedDMA.SPR1 = false;
|
||||
DmaExec(dmaSPR1, mem, value);
|
||||
return;
|
||||
}
|
||||
|
@ -1189,8 +1231,13 @@ void __fastcall hwWrite64_generic( u32 mem, const mem64_t* srcval )
|
|||
break;
|
||||
|
||||
case DMAC_ENABLEW: // DMAC_ENABLEW
|
||||
oldvalue = psHu8(DMAC_ENABLEW + 2);
|
||||
psHu32(DMAC_ENABLEW) = value;
|
||||
psHu32(DMAC_ENABLER) = value;
|
||||
if (((oldvalue & 0x1) == 1) && (((value >> 16) & 0x1) == 0))
|
||||
{
|
||||
if (!QueuedDMA.empty()) StartQueuedDMA();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1222,8 +1269,13 @@ void __fastcall hwWrite128_generic(u32 mem, const mem128_t *srcval)
|
|||
break;
|
||||
|
||||
case DMAC_ENABLEW: // DMAC_ENABLEW
|
||||
oldvalue = psHu8(DMAC_ENABLEW + 2);
|
||||
psHu32(DMAC_ENABLEW) = srcval[0];
|
||||
psHu32(DMAC_ENABLER) = srcval[0];
|
||||
if (((oldvalue & 0x1) == 1) && (((srcval[0] >> 16) & 0x1) == 0))
|
||||
{
|
||||
if (!QueuedDMA.empty()) StartQueuedDMA();
|
||||
}
|
||||
break;
|
||||
|
||||
case SIO_ISR:
|
||||
|
|
|
@ -796,7 +796,7 @@ void IPUCMD_WRITE(u32 val)
|
|||
// have to resort to the thread
|
||||
ipu_cmd.current = val >> 28;
|
||||
ipuRegs->ctrl.BUSY = 1;
|
||||
hwIntcIrq(INTC_IPU);
|
||||
if(ipu1dma->qwc == 0) hwIntcIrq(INTC_IPU);
|
||||
}
|
||||
|
||||
void IPUWorker()
|
||||
|
@ -808,7 +808,7 @@ void IPUWorker()
|
|||
case SCE_IPU_VDEC:
|
||||
if (!ipuVDEC(ipuRegs->cmd.DATA))
|
||||
{
|
||||
hwIntcIrq(INTC_IPU);
|
||||
if(ipu1dma->qwc == 0) hwIntcIrq(INTC_IPU);
|
||||
return;
|
||||
}
|
||||
ipuRegs->cmd.BUSY = 0;
|
||||
|
@ -818,7 +818,7 @@ void IPUWorker()
|
|||
case SCE_IPU_FDEC:
|
||||
if (!ipuFDEC(ipuRegs->cmd.DATA))
|
||||
{
|
||||
hwIntcIrq(INTC_IPU);
|
||||
if(ipu1dma->qwc == 0) hwIntcIrq(INTC_IPU);
|
||||
return;
|
||||
}
|
||||
ipuRegs->cmd.BUSY = 0;
|
||||
|
@ -828,7 +828,7 @@ void IPUWorker()
|
|||
case SCE_IPU_SETIQ:
|
||||
if (!ipuSETIQ(ipuRegs->cmd.DATA))
|
||||
{
|
||||
hwIntcIrq(INTC_IPU);
|
||||
if(ipu1dma->qwc == 0) hwIntcIrq(INTC_IPU);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
@ -836,7 +836,7 @@ void IPUWorker()
|
|||
case SCE_IPU_SETVQ:
|
||||
if (!ipuSETVQ(ipuRegs->cmd.DATA))
|
||||
{
|
||||
hwIntcIrq(INTC_IPU);
|
||||
if(ipu1dma->qwc == 0) hwIntcIrq(INTC_IPU);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
@ -844,7 +844,7 @@ void IPUWorker()
|
|||
case SCE_IPU_CSC:
|
||||
if (!ipuCSC(ipuRegs->cmd.DATA))
|
||||
{
|
||||
hwIntcIrq(INTC_IPU);
|
||||
if(ipu1dma->qwc == 0) hwIntcIrq(INTC_IPU);
|
||||
return;
|
||||
}
|
||||
if (ipu0dma->qwc > 0 && ipu0dma->chcr.STR) IPU_INT0_FROM();
|
||||
|
@ -853,7 +853,7 @@ void IPUWorker()
|
|||
case SCE_IPU_PACK:
|
||||
if (!ipuPACK(ipuRegs->cmd.DATA))
|
||||
{
|
||||
hwIntcIrq(INTC_IPU);
|
||||
if(ipu1dma->qwc == 0) hwIntcIrq(INTC_IPU);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
@ -862,7 +862,7 @@ void IPUWorker()
|
|||
so_call(s_routine);
|
||||
if (!s_RoutineDone)
|
||||
{
|
||||
hwIntcIrq(INTC_IPU);
|
||||
if(ipu1dma->qwc == 0) hwIntcIrq(INTC_IPU);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -881,7 +881,7 @@ void IPUWorker()
|
|||
so_call(s_routine);
|
||||
if (!s_RoutineDone)
|
||||
{
|
||||
hwIntcIrq(INTC_IPU);
|
||||
if(ipu1dma->qwc == 0) hwIntcIrq(INTC_IPU);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1276,6 +1276,30 @@ static __forceinline void ipuDmacSrcChain()
|
|||
}
|
||||
}
|
||||
|
||||
static __forceinline bool WaitGSPaths()
|
||||
{
|
||||
if (dmacRegs->ctrl.STD != STD_GIF || (gif->madr + (gif->qwc * 16)) < dmacRegs->stadr.ADDR)
|
||||
{
|
||||
if(gif->chcr.STR && (vif1Regs->mskpath3 == 0) && 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;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static __forceinline int IPU1chain() {
|
||||
|
||||
int totalqwc = 0;
|
||||
|
@ -1304,7 +1328,7 @@ static __forceinline int IPU1chain() {
|
|||
//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(totalqwc*BIAS);
|
||||
IPU_INT_TO(4);
|
||||
}
|
||||
//No data left
|
||||
IPU1Status.InProgress = false;
|
||||
|
@ -1314,7 +1338,7 @@ static __forceinline int IPU1chain() {
|
|||
return totalqwc;
|
||||
}
|
||||
|
||||
//static __forceinline bool flushGIF()
|
||||
//static __forceinline bool WaitGSPaths()
|
||||
//{
|
||||
// //Wait for all GS paths to be clear
|
||||
// if (GSTransferStatus._u32 != 0x2a)
|
||||
|
@ -1327,17 +1351,7 @@ static __forceinline int IPU1chain() {
|
|||
// return true;
|
||||
//}
|
||||
|
||||
static __forceinline void flushGIF()
|
||||
{
|
||||
if (dmacRegs->ctrl.STD != STD_GIF || (gif->madr + (gif->qwc * 16)) < dmacRegs->stadr.ADDR)
|
||||
{
|
||||
while(gif->chcr.STR && (vif1Regs->mskpath3 == 0) && Path3progress != STOPPED_MODE)
|
||||
{
|
||||
GIF_LOG("Flushing gif chcr %x tadr %x madr %x qwc %x", gif->chcr._u32, gif->tadr, gif->madr, gif->qwc);
|
||||
gsInterrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int IPU1dma()
|
||||
{
|
||||
|
@ -1346,9 +1360,9 @@ int IPU1dma()
|
|||
int totalqwc = 0;
|
||||
|
||||
//We need to make sure GIF has flushed before sending IPU data, it seems to REALLY screw FFX videos
|
||||
//if(!flushGIF()) return totalqwc;
|
||||
//if(!WaitGSPaths()) return totalqwc;
|
||||
|
||||
|
||||
flushGIF(); // legacy flushGIF() for now
|
||||
|
||||
DMA_LOG("IPU1 DMA Called QWC %x Finished %d In Progress %d tadr %x", ipu1dma->qwc, IPU1Status.DMAFinished, IPU1Status.InProgress, ipu1dma->tadr);
|
||||
|
||||
|
@ -1356,6 +1370,11 @@ int IPU1dma()
|
|||
{
|
||||
case DMA_MODE_NORMAL:
|
||||
{
|
||||
if(!WaitGSPaths())
|
||||
{ // legacy WaitGSPaths() for now
|
||||
if(totalqwc == 0)IPU_INT_TO(4); //Give it a short wait.
|
||||
return totalqwc;
|
||||
}
|
||||
DMA_LOG("Processing Normal QWC left %x Finished %d In Progress %d", ipu1dma->qwc, IPU1Status.DMAFinished, IPU1Status.InProgress);
|
||||
if(IPU1Status.InProgress == true) totalqwc += IPU1chain();
|
||||
}
|
||||
|
@ -1365,6 +1384,11 @@ int IPU1dma()
|
|||
{
|
||||
if(IPU1Status.InProgress == true) //No transfer is ready to go so we need to set one up
|
||||
{
|
||||
if(!WaitGSPaths())
|
||||
{ // legacy WaitGSPaths() for now
|
||||
if(totalqwc == 0)IPU_INT_TO(4); //Give it a short wait.
|
||||
return totalqwc;
|
||||
}
|
||||
DMA_LOG("Processing Chain QWC left %x Finished %d In Progress %d", ipu1dma->qwc, IPU1Status.DMAFinished, IPU1Status.InProgress);
|
||||
totalqwc += IPU1chain();
|
||||
//Set the TADR forward
|
||||
|
@ -1449,7 +1473,11 @@ int IPU1dma()
|
|||
IPU1Status.DMAFinished = true;
|
||||
|
||||
|
||||
|
||||
if(!WaitGSPaths() && ipu1dma->qwc > 0)
|
||||
{ // legacy WaitGSPaths() for now
|
||||
if(totalqwc == 0)IPU_INT_TO(4); //Give it a short wait.
|
||||
return totalqwc;
|
||||
}
|
||||
DMA_LOG("Processing Start Chain QWC left %x Finished %d In Progress %d", ipu1dma->qwc, IPU1Status.DMAFinished, IPU1Status.InProgress);
|
||||
totalqwc += IPU1chain();
|
||||
//Set the TADR forward
|
||||
|
@ -1469,15 +1497,6 @@ int IPU0dma()
|
|||
static int totalsize = 0;
|
||||
tDMA_TAG* pMem;
|
||||
|
||||
// Note: pad is the padding right above qwc, so we're testing whether qwc
|
||||
// has overflowed into pad.
|
||||
if (ipu0dma->pad != 0)
|
||||
{
|
||||
DevCon.Warning(L"IPU0dma's upper 16 bits set to %x\n", ipu0dma->pad);
|
||||
ipu0dma->qwc = ipu0dma->pad = 0;
|
||||
//return 0;
|
||||
}
|
||||
|
||||
if ((!(ipu0dma->chcr.STR) || (cpuRegs.interrupt & (1 << DMAC_FROM_IPU))) || (ipu0dma->qwc == 0))
|
||||
return 0;
|
||||
|
||||
|
@ -1533,6 +1552,16 @@ int IPU0dma()
|
|||
|
||||
__forceinline void dmaIPU0() // fromIPU
|
||||
{
|
||||
if (ipu0dma->pad != 0)
|
||||
{
|
||||
// Note: pad is the padding right above qwc, so we're testing whether qwc
|
||||
// has overflowed into pad.
|
||||
DevCon.Warning(L"IPU0dma's upper 16 bits set to %x\n", ipu0dma->pad);
|
||||
ipu0dma->qwc = ipu0dma->pad = 0;
|
||||
//If we are going to clear down IPU0, we should end it too. Going to test this scenario on the PS2 mind - Refraction
|
||||
ipu0dma->chcr.STR = false;
|
||||
hwDmacIrq(DMAC_FROM_IPU);
|
||||
}
|
||||
if (ipuRegs->ctrl.BUSY) IPUWorker();
|
||||
}
|
||||
|
||||
|
@ -1556,7 +1585,6 @@ __forceinline void dmaIPU1() // toIPU
|
|||
}
|
||||
|
||||
IPU1Status.DMAMode = DMA_MODE_CHAIN;
|
||||
|
||||
IPU1dma();
|
||||
if (ipuRegs->ctrl.BUSY) IPUWorker();
|
||||
}
|
||||
|
@ -1582,9 +1610,7 @@ __forceinline void dmaIPU1() // toIPU
|
|||
IPU1dma();
|
||||
if (ipuRegs->ctrl.BUSY) IPUWorker();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
extern void GIFdma();
|
||||
|
|
|
@ -270,6 +270,11 @@ static __forceinline void TESTINT( u8 n, void (*callback)() )
|
|||
|
||||
static __forceinline void _cpuTestInterrupts()
|
||||
{
|
||||
if (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2))
|
||||
{
|
||||
//Console.Write("DMAC Disabled or suspended");
|
||||
return;
|
||||
}
|
||||
/* These are 'pcsx2 interrupts', they handle asynchronous stuff
|
||||
that depends on the cycle timings */
|
||||
|
||||
|
|
|
@ -251,6 +251,10 @@ void SPRFROMinterrupt()
|
|||
}
|
||||
}
|
||||
if (!spr0finished) return;
|
||||
|
||||
if((spr0->chcr.MOD == CHAIN_MODE) && ((spr0->chcr.TAG >> 12) & 0x7) != 0x0 && ((spr0->chcr.TAG >> 12) & 0x7) != 0x7 && !((spr0->chcr.TAG >> 12) & 0x8))
|
||||
DevCon.Warning("SPR0 Ending when refe or end not set! CHCR = %x", spr0->chcr._u32);
|
||||
|
||||
spr0->chcr.STR = false;
|
||||
hwDmacIrq(DMAC_FROM_SPR);
|
||||
}
|
||||
|
@ -424,6 +428,10 @@ void SPRTOinterrupt()
|
|||
{
|
||||
_dmaSPR1();
|
||||
if (!spr1finished) return;
|
||||
|
||||
if((spr1->chcr.MOD == CHAIN_MODE) && ((spr1->chcr.TAG >> 12) & 0x7) != 0x0 && ((spr1->chcr.TAG >> 12) & 0x7) != 0x7 && !((spr1->chcr.TAG >> 12) & 0x8))
|
||||
DevCon.Warning("SPR1 Ending when refe or end not set! CHCR = %x", spr1->chcr._u32);
|
||||
|
||||
spr1->chcr.STR = false;
|
||||
hwDmacIrq(DMAC_TO_SPR);
|
||||
}
|
||||
|
|
|
@ -151,6 +151,9 @@ static __forceinline void EndEE()
|
|||
SIF_LOG("SIF0 EE: cycles = 0");
|
||||
sif0.ee.cycles = 1;
|
||||
}
|
||||
if((sif0dma->chcr.MOD == CHAIN_MODE) && ((sif0dma->chcr.TAG >> 12) & 0x7) != 0x0 && ((sif0dma->chcr.TAG >> 12) & 0x7) != 0x7 && !((sif0dma->chcr.TAG >> 12) & 0x8))
|
||||
DevCon.Warning("SIF0 Ending when refe or end not set! CHCR = %x", sif0dma->chcr._u32);
|
||||
|
||||
CPU_INT(DMAC_SIF0, sif0.ee.cycles*BIAS);
|
||||
}
|
||||
|
||||
|
|
|
@ -174,6 +174,10 @@ static __forceinline void EndEE()
|
|||
SIF_LOG("SIF1 EE: cycles = 0");
|
||||
sif1.ee.cycles = 1;
|
||||
}
|
||||
|
||||
if((sif1dma->chcr.MOD == CHAIN_MODE) && ((sif1dma->chcr.TAG >> 12) & 0x7) != 0x0 && ((sif1dma->chcr.TAG >> 12) & 0x7) != 0x7 && !((sif1dma->chcr.TAG >> 12) & 0x8))
|
||||
DevCon.Warning("SIF0 Ending when refe or end not set! CHCR = %x", sif1dma->chcr._u32);
|
||||
|
||||
CPU_INT(DMAC_SIF1, min((int)(sif1.ee.cycles*BIAS), 384));
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
vifStruct vif0;
|
||||
vifStruct vif1;
|
||||
Path3Modes Path3progress = STOPPED_MODE;
|
||||
tGSTransferStatus GSTransferStatus = (STOPPED_MODE<<4) | (STOPPED_MODE<<2) | STOPPED_MODE;
|
||||
|
||||
void vif0Init() { initNewVif(0); }
|
||||
void vif1Init() { initNewVif(1); }
|
||||
|
@ -253,13 +253,20 @@ _f void vif1STAT(u32 value) {
|
|||
if (vif1Regs->stat.FDR) // Vif transferring to memory.
|
||||
{
|
||||
// Hack but it checks this is true before transfer? (fatal frame)
|
||||
vif1Regs->stat.FQC = 0x1;
|
||||
// Update Refraction: Use of this function has been investigated and understood.
|
||||
// Before this ever happens, a DIRECT/HL command takes place sending the transfer info to the GS
|
||||
// One of the registers told about this is TRXREG which tells us how much data is going to transfer (th x tw) in words
|
||||
// As far as the GS is concerned, the transfer starts as soon as TRXREG is accessed, which is why fatal frame
|
||||
// was expecting data, the GS should already be sending it over (buffering in the FIFO)
|
||||
|
||||
vif1Regs->stat.FQC = max((u32)16, vif1.GSLastTRXPOS);
|
||||
//Console.Warning("Reversing VIF Transfer for %x QWC", vif1.GSLastTRXPOS);
|
||||
|
||||
}
|
||||
else // Memory transferring to Vif.
|
||||
{
|
||||
vif1ch->qwc = 0;
|
||||
vif1.vifstalled = false;
|
||||
vif1.done = true;
|
||||
//Sometimes the value from the GS is bigger than vif wanted, so it just sets it back and cancels it.
|
||||
//Other times it can read it off ;)
|
||||
vif1Regs->stat.FQC = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -152,7 +152,7 @@ __forceinline void vif0Interrupt()
|
|||
// VIF_NORMAL_FROM_MEM_MODE is a very slow operation.
|
||||
// Timesplitters 2 depends on this beeing a bit higher than 128.
|
||||
if (vif0.dmamode == VIF_NORMAL_FROM_MEM_MODE ) CPU_INT(DMAC_VIF0, 1024);
|
||||
else CPU_INT(DMAC_VIF0, /*g_vifCycles*/ VifCycleVoodoo);
|
||||
else CPU_INT(DMAC_VIF0, g_vifCycles);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -167,7 +167,7 @@ __forceinline void vif0Interrupt()
|
|||
|
||||
if ((vif0.inprogress & 0x1) == 0) vif0SetupTransfer();
|
||||
|
||||
CPU_INT(DMAC_VIF0, /*g_vifCycles*/ VifCycleVoodoo);
|
||||
CPU_INT(DMAC_VIF0, g_vifCycles);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -182,6 +182,9 @@ __forceinline void vif0Interrupt()
|
|||
if (vif0.cmd != 0) Console.WriteLn("vif0.cmd still set %x tag size %x", vif0.cmd, vif0.tag.size);
|
||||
#endif
|
||||
|
||||
/*if(vif0.dmamode == VIF_CHAIN_MODE && ((vif0ch->chcr.TAG >> 12) & 0x7) != 0x0 && ((vif0ch->chcr.TAG >> 12) & 0x7) != 0x7 && !((vif0ch->chcr.TAG >> 12) & 0x8))
|
||||
DevCon.Warning("VIF0 Ending when refe or end not set! CHCR = %x", vif0ch->chcr._u32);*/
|
||||
|
||||
vif0Regs->stat.VPS = VPS_IDLE; //Vif goes idle as the stall happened between commands;
|
||||
vif0ch->chcr.STR = false;
|
||||
g_vifCycles = 0;
|
||||
|
|
|
@ -50,7 +50,7 @@ void vif1TransferFromMemory()
|
|||
// MTGS concerns: The MTGS is inherently disagreeable with the idea of downloading
|
||||
// stuff from the GS. The *only* way to handle this case safely is to flush the GS
|
||||
// completely and execute the transfer there-after.
|
||||
|
||||
//Console.Warning("Real QWC %x", vif1ch->qwc);
|
||||
XMMRegisters::Freeze();
|
||||
|
||||
if (GSreadFIFO2 == NULL)
|
||||
|
@ -81,6 +81,11 @@ void vif1TransferFromMemory()
|
|||
|
||||
g_vifCycles += vif1ch->qwc * 2;
|
||||
vif1ch->madr += vif1ch->qwc * 16; // mgs3 scene changes
|
||||
if(vif1.GSLastTRXPOS > vif1ch->qwc)
|
||||
vif1Regs->stat.FQC = vif1.GSLastTRXPOS - vif1ch->qwc;
|
||||
else
|
||||
vif1Regs->stat.FQC = 0;
|
||||
|
||||
vif1ch->qwc = 0;
|
||||
}
|
||||
|
||||
|
@ -195,12 +200,18 @@ __forceinline void vif1Interrupt()
|
|||
VIF_LOG("vif1Interrupt: %8.8x", cpuRegs.cycle);
|
||||
|
||||
g_vifCycles = 0;
|
||||
if (vif1ch->chcr.DIR) vif1Regs->stat.FQC = min(vif1ch->qwc, (u16)16);
|
||||
//Simulated GS transfer time done, clear the flags
|
||||
if(gifRegs->stat.APATH == GIF_APATH2 && (vif1.cmd & 0x70) != 0x50)
|
||||
{
|
||||
gifRegs->stat.clear_flags(GIF_STAT_APATH2|GIF_STAT_OPH);
|
||||
}
|
||||
|
||||
if (schedulepath3msk) Vif1MskPath3();
|
||||
|
||||
if ((vif1Regs->stat.VGW))
|
||||
{
|
||||
if (gif->chcr.STR && (Path3progress != STOPPED_MODE))
|
||||
if ((gif->chcr.STR && (GSTransferStatus.PTH3 != STOPPED_MODE)) || (GSTransferStatus.PTH1 != STOPPED_MODE))
|
||||
{
|
||||
CPU_INT(DMAC_VIF1, 4);
|
||||
return;
|
||||
|
@ -220,7 +231,7 @@ __forceinline void vif1Interrupt()
|
|||
--vif1.irq;
|
||||
if (vif1Regs->stat.test(VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS))
|
||||
{
|
||||
vif1Regs->stat.FQC = 0;
|
||||
//vif1Regs->stat.FQC = 0;
|
||||
|
||||
// One game doesn't like vif stalling at end, can't remember what. Spiderman isn't keen on it tho
|
||||
vif1ch->chcr.STR = false;
|
||||
|
@ -240,8 +251,10 @@ __forceinline void vif1Interrupt()
|
|||
_VIF1chain();
|
||||
// VIF_NORMAL_FROM_MEM_MODE is a very slow operation.
|
||||
// Timesplitters 2 depends on this beeing a bit higher than 128.
|
||||
if (vif1.dmamode == VIF_NORMAL_FROM_MEM_MODE ) CPU_INT(DMAC_VIF1, 1024);
|
||||
else CPU_INT(DMAC_VIF1, /*g_vifCycles*/ VifCycleVoodoo);
|
||||
if (vif1ch->chcr.DIR) vif1Regs->stat.FQC = min(vif1ch->qwc, (u16)16);
|
||||
// Refraction - Removing voodoo timings for now, completely messes a lot of Path3 masked games.
|
||||
/*if (vif1.dmamode == VIF_NORMAL_FROM_MEM_MODE ) CPU_INT(DMAC_VIF1, 1024);
|
||||
else */CPU_INT(DMAC_VIF1, g_vifCycles /*VifCycleVoodoo*/);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -255,8 +268,8 @@ __forceinline void vif1Interrupt()
|
|||
}
|
||||
|
||||
if ((vif1.inprogress & 0x1) == 0) vif1SetupTransfer();
|
||||
|
||||
CPU_INT(DMAC_VIF1, /*g_vifCycles*/ VifCycleVoodoo);
|
||||
if (vif1ch->chcr.DIR) vif1Regs->stat.FQC = min(vif1ch->qwc, (u16)16);
|
||||
CPU_INT(DMAC_VIF1, g_vifCycles);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -275,12 +288,14 @@ __forceinline void vif1Interrupt()
|
|||
vif1ch->chcr.STR = false;
|
||||
g_vifCycles = 0;
|
||||
hwDmacIrq(DMAC_VIF1);
|
||||
|
||||
|
||||
/*if(vif1.dmamode == VIF_CHAIN_MODE && ((vif1ch->chcr.TAG >> 12) & 0x7) != 0x0 && ((vif1ch->chcr.TAG >> 12) & 0x7) != 0x7 && !((vif1ch->chcr.TAG >> 12) & 0x8))
|
||||
DevCon.Warning("VIF1 Ending when refe or end not set! CHCR = %x", vif1ch->chcr._u32);*/
|
||||
//Im not totally sure why Path3 Masking makes it want to see stuff in the fifo
|
||||
//Games effected by setting, Fatal Frame, KH2, Shox, Crash N Burn, GT3/4 possibly
|
||||
//Im guessing due to the full gs fifo before the reverse? (Refraction)
|
||||
//Note also this is only the condition for reverse fifo mode, normal direction clears it as normal
|
||||
if (!vif1Regs->mskpath3 || vif1ch->chcr.DIR) vif1Regs->stat.FQC = 0;
|
||||
//if (!vif1Regs->mskpath3 || vif1ch->chcr.DIR) vif1Regs->stat.FQC = min(vif1ch->qwc, (u16)16);
|
||||
}
|
||||
|
||||
void dmaVIF1()
|
||||
|
@ -298,6 +313,7 @@ void dmaVIF1()
|
|||
//Console.WriteLn("VIFMFIFO\n");
|
||||
// Test changed because the Final Fantasy 12 opening somehow has the tag in *Undefined* mode, which is not in the documentation that I saw.
|
||||
if (vif1ch->chcr.MOD == NORMAL_MODE) Console.WriteLn("MFIFO mode is normal (which isn't normal here)! %x", vif1ch->chcr._u32);
|
||||
vif1Regs->stat.FQC = min((u16)0x10, vif1ch->qwc);
|
||||
vifMFIFOInterrupt();
|
||||
return;
|
||||
}
|
||||
|
@ -325,10 +341,7 @@ void dmaVIF1()
|
|||
vif1.dmamode = VIF_CHAIN_MODE;
|
||||
}
|
||||
|
||||
if (vif1.dmamode != VIF_NORMAL_FROM_MEM_MODE)
|
||||
vif1Regs->stat.FQC = 0x10;
|
||||
else
|
||||
vif1Regs->stat.FQC = min((u16)0x10, vif1ch->qwc);
|
||||
vif1Regs->stat.FQC = min((u16)0x10, vif1ch->qwc);
|
||||
|
||||
// Chain Mode
|
||||
vif1.done = false;
|
||||
|
|
|
@ -210,7 +210,7 @@ void mfifoVIF1transfer(int qwc)
|
|||
vif1.done = true;
|
||||
}
|
||||
}
|
||||
|
||||
vif1Regs->stat.FQC = min(vif1ch->qwc, (u16)16);
|
||||
vif1.inprogress |= 1;
|
||||
|
||||
SPR_LOG("mfifoVIF1transfer end %x madr %x, tadr %x vifqwc %x", vif1ch->chcr._u32, vif1ch->madr, vif1ch->tadr, vifqwc);
|
||||
|
@ -295,6 +295,9 @@ void vifMFIFOInterrupt()
|
|||
hwDmacIrq(DMAC_MFIFO_EMPTY);
|
||||
}*/
|
||||
|
||||
if(((vif1ch->chcr.TAG >> 12) & 0x7) != 0x0 && ((vif1ch->chcr.TAG >> 12) & 0x7) != 0x7)
|
||||
DevCon.Warning("VIF1 MFIFO Ending when refe or end not set! CHCR = %x", vif1ch->chcr._u32);
|
||||
|
||||
vif1.done = 1;
|
||||
g_vifCycles = 0;
|
||||
vif1ch->chcr.STR = false;
|
||||
|
|
|
@ -78,9 +78,9 @@ void Vif1MskPath3() {
|
|||
|
||||
if (!vif1Regs->mskpath3) {
|
||||
//Let the Gif know it can transfer again (making sure any vif stall isnt unset prematurely)
|
||||
Path3progress = TRANSFER_MODE;
|
||||
GSTransferStatus.PTH3 = TRANSFER_MODE;
|
||||
gifRegs->stat.IMT = false;
|
||||
CPU_INT(DMAC_GIF, 4);
|
||||
if(gif->chcr.STR == true) CPU_INT(DMAC_GIF, 4);
|
||||
}
|
||||
else gifRegs->stat.M3P = true;
|
||||
|
||||
|
@ -108,10 +108,10 @@ template<int idx> _f int _vifCode_Direct(int pass, u8* data, bool isDirectHL) {
|
|||
pass2 {
|
||||
vif1Only();
|
||||
//return vifTrans_DirectHL<idx>((u32*)data);
|
||||
|
||||
gifRegs->stat.P2Q = true;
|
||||
//Should probably do this for both types of transfer seen as the GS hates taking 2 seperate chunks
|
||||
//if (isDirectHL) {
|
||||
if (gif->chcr.STR && (!vif1Regs->mskpath3 && (Path3progress != STOPPED_MODE)))
|
||||
if ((gif->chcr.STR && (!vif1Regs->mskpath3 && (GSTransferStatus.PTH3 != STOPPED_MODE))) || GSTransferStatus.PTH1 != STOPPED_MODE)
|
||||
{
|
||||
/*if(!isDirectHL) DevCon.WriteLn("Direct: Waiting for Path3 to finish!");
|
||||
else DevCon.WriteLn("DirectHL: Waiting for Path3 to finish!");*/
|
||||
|
@ -121,11 +121,14 @@ template<int idx> _f int _vifCode_Direct(int pass, u8* data, bool isDirectHL) {
|
|||
return 0;
|
||||
}
|
||||
//}
|
||||
gifRegs->stat.clear_flags(GIF_STAT_P2Q);
|
||||
gifRegs->stat.APATH = GIF_APATH2;
|
||||
gifRegs->stat.OPH = true;
|
||||
|
||||
Registers::Freeze();
|
||||
nVifStruct& v = nVif[1];
|
||||
const int ret = aMin(vif1.vifpacketsize, vif1.tag.size);
|
||||
s32 size = ret << 2;
|
||||
u32 size = ret << 2;
|
||||
|
||||
if (ret == v.vif->tag.size) { // Full Transfer
|
||||
if (v.bSize) { // Last transfer was partial
|
||||
|
@ -180,7 +183,7 @@ vifOp(vifCode_FlushA) {
|
|||
vif1Only();
|
||||
pass1 {
|
||||
// Gif is already transferring so wait for it.
|
||||
if (((Path3progress != STOPPED_MODE) || !vif1Regs->mskpath3) && gif->chcr.STR) {
|
||||
if (((GSTransferStatus.PTH3 != STOPPED_MODE) || !vif1Regs->mskpath3) && gif->chcr.STR) {
|
||||
//DevCon.WriteLn("FlushA path3 Wait!");
|
||||
vif1Regs->stat.VGW = true;
|
||||
vifX.vifstalled = true;
|
||||
|
@ -467,4 +470,4 @@ int (__fastcall *vif1Code[128])(int pass, u32 *data) = {
|
|||
vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1>, /*0x68*/
|
||||
vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Null<1>, /*0x70*/
|
||||
vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Null<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> /*0x78*/
|
||||
};
|
||||
};
|
||||
|
|
|
@ -24,6 +24,18 @@ struct vifCode {
|
|||
u16 cl;
|
||||
};
|
||||
|
||||
union tBITBLT {
|
||||
struct {
|
||||
u32 reserved : 8;
|
||||
u32 BLTDIVIDE : 8; // This is the value we want to work out the divider for the reverse transfer
|
||||
u32 reserved2 : 6;
|
||||
u32 TRXPOS : 16;
|
||||
};
|
||||
u32 _u32;
|
||||
|
||||
|
||||
};
|
||||
|
||||
// NOTE, if debugging vif stalls, use sega classics, spyro, gt4, and taito
|
||||
struct vifStruct {
|
||||
vifCode tag;
|
||||
|
@ -36,7 +48,10 @@ struct vifStruct {
|
|||
bool done;
|
||||
bool vifstalled;
|
||||
bool stallontag;
|
||||
tBITBLT TRXPOS; //used for reversed fifo operations, sometimes only the GS knows how big (like on HW register fifo read)!
|
||||
u32 GSLastTRXPOS;
|
||||
|
||||
|
||||
u8 irqoffset; // 32bit offset where next vif code is
|
||||
u32 savedtag; // need this for backwards compat with save states
|
||||
u32 vifpacketsize;
|
||||
|
@ -47,7 +62,6 @@ struct vifStruct {
|
|||
extern vifStruct* vif;
|
||||
extern vifStruct vif0, vif1;
|
||||
extern u8 schedulepath3msk;
|
||||
static const int VifCycleVoodoo = 4;
|
||||
|
||||
extern void vif0Init();
|
||||
extern void vif0Interrupt();
|
||||
|
|
|
@ -130,4 +130,4 @@ bool VIF0transfer(u32 *data, int size, bool istag) {
|
|||
}
|
||||
bool VIF1transfer(u32 *data, int size, bool istag) {
|
||||
return vifTransfer<1>(data, size);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "GS.h"
|
||||
#include "Gif.h"
|
||||
#include "Vif_Dma.h"
|
||||
#include "vif.h"
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// GIFpath -- the GIFtag Parser
|
||||
|
@ -277,6 +278,40 @@ void SaveStateBase::gifPathFreeze()
|
|||
static __forceinline void gsHandler(const u8* pMem)
|
||||
{
|
||||
const int handler = pMem[8];
|
||||
|
||||
if(handler == 0x50)
|
||||
{
|
||||
const u16* pMem16 = (const u16*)pMem;
|
||||
|
||||
vif1.TRXPOS._u32 = pMem16[1];
|
||||
//Console.Warning("BLITBUF = %x %x_%x_%x_%x", vif1.TRXPOS.BLTDIVIDE, pMem16[0], pMem16[1], pMem16[2], pMem16[3]);
|
||||
switch(vif1.TRXPOS.BLTDIVIDE & 0x3)
|
||||
{
|
||||
case 0x3:
|
||||
VIF_LOG("8bit");
|
||||
vif1.TRXPOS.BLTDIVIDE = 16; //8bit
|
||||
break;
|
||||
case 0x2:
|
||||
VIF_LOG("16bit");
|
||||
vif1.TRXPOS.BLTDIVIDE = 8; //16bit
|
||||
break;
|
||||
case 0x1:
|
||||
VIF_LOG("24bit");
|
||||
vif1.TRXPOS.BLTDIVIDE = 5; //24bit
|
||||
break;
|
||||
default:
|
||||
VIF_LOG("32bit");
|
||||
vif1.TRXPOS.BLTDIVIDE = 4; //32bit
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(handler == 0x52)
|
||||
{
|
||||
const u16* pMem16 = (const u16*)pMem;
|
||||
VIF_LOG("TRX REG = %x_%x_%x_%x", pMem16[0], pMem16[1], pMem16[2], pMem16[3]);
|
||||
vif1.GSLastTRXPOS = (pMem16[0] * pMem16[2]) / (u8)vif1.TRXPOS.BLTDIVIDE;
|
||||
|
||||
}
|
||||
if (handler >= 0x60)
|
||||
{
|
||||
// Question: What happens if an app writes to uncharted register space on real PS2
|
||||
|
@ -310,14 +345,28 @@ __forceinline int GIFPath::ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size)
|
|||
SetTag(pMem);
|
||||
incTag(16, 1);
|
||||
|
||||
if (pathidx == GIF_PATH_3) {
|
||||
if (tag.FLG&2) Path3progress = IMAGE_MODE;
|
||||
else Path3progress = TRANSFER_MODE;
|
||||
//if (pathidx == GIF_PATH_3) {
|
||||
switch(pathidx)
|
||||
{
|
||||
case GIF_PATH_1:
|
||||
if (tag.FLG&2) GSTransferStatus.PTH1 = IMAGE_MODE;
|
||||
else GSTransferStatus.PTH1 = TRANSFER_MODE;
|
||||
break;
|
||||
case GIF_PATH_2:
|
||||
if (tag.FLG&2) GSTransferStatus.PTH2 = IMAGE_MODE;
|
||||
else GSTransferStatus.PTH2 = TRANSFER_MODE;
|
||||
break;
|
||||
case GIF_PATH_3:
|
||||
if (tag.FLG&2) GSTransferStatus.PTH3 = IMAGE_MODE;
|
||||
else GSTransferStatus.PTH3 = TRANSFER_MODE;
|
||||
break;
|
||||
}
|
||||
//}
|
||||
}
|
||||
else {
|
||||
switch(tag.FLG) {
|
||||
case GIF_FLG_PACKED:
|
||||
GIF_LOG("Packed Mode");
|
||||
PrepPackedRegs();
|
||||
do {
|
||||
if (GetReg() == 0xe) {
|
||||
|
@ -328,6 +377,7 @@ __forceinline int GIFPath::ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size)
|
|||
break;
|
||||
case GIF_FLG_REGLIST:
|
||||
{
|
||||
GIF_LOG("Reglist Mode");
|
||||
size *= 2;
|
||||
|
||||
do { incTag(8, 1); }
|
||||
|
@ -340,6 +390,7 @@ __forceinline int GIFPath::ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size)
|
|||
case GIF_FLG_IMAGE:
|
||||
case GIF_FLG_IMAGE2:
|
||||
{
|
||||
GIF_LOG("IMAGE Mode");
|
||||
int len = aMin(size, nloop);
|
||||
incTag(( len * 16 ), len);
|
||||
nloop -= len;
|
||||
|
@ -354,17 +405,32 @@ __forceinline int GIFPath::ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size)
|
|||
}
|
||||
}
|
||||
}
|
||||
/*if(((GSTransferStatus.PTH1 & 0x2) + (GSTransferStatus.PTH2 & 0x2) + ((GSTransferStatus.PTH3 & 0x2) && !vif1Regs->mskpath3)) < 0x4 )
|
||||
Console.Warning("CHK PTH1 %x, PTH2 %x, PTH3 %x", GSTransferStatus.PTH1, GSTransferStatus.PTH2, GSTransferStatus.PTH3);*/
|
||||
|
||||
size = (startSize - size);
|
||||
|
||||
if (pathidx == GIF_PATH_3) {
|
||||
|
||||
if (tag.EOP && !nloop) {
|
||||
Path3progress = STOPPED_MODE;
|
||||
//Console.Warning("Finishing path %x", pathidx);
|
||||
switch(pathidx)
|
||||
{
|
||||
case GIF_PATH_1:
|
||||
GSTransferStatus.PTH1 = STOPPED_MODE;
|
||||
break;
|
||||
case GIF_PATH_2:
|
||||
GSTransferStatus.PTH2 = STOPPED_MODE;
|
||||
break;
|
||||
case GIF_PATH_3:
|
||||
GSTransferStatus.PTH3 = STOPPED_MODE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pathidx == GIF_PATH_3) {
|
||||
gif->madr += size * 16;
|
||||
gif->qwc -= size;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue