mirror of https://github.com/PCSX2/pcsx2.git
Summary of fixes
Games - Resident Evil Dead Aim flickering graphics fixed. - Flatout games should now boot everytime (instead of randomly) - Sega Superstar Tennis flashing fixed - Destruction Derby graphics fixed (NTSC confirmed, PAL unsure) - Tenchu Fatal Shadows flickering textures fixed, Issue 748 - Spyro Hero's Tail should boot again, Issue 746 General Info - General reworking of the GS paths with all paths prioritizing more correctly. - XGKICK can stall if another GS transfer is in progress - Major reworking of Path3 masking, could still be combined with normal Path3 transfers, but lets get it working first :P - Taken in to account a few conditions which could have caused VIF to lock up/crash when stalling on ends. - Unreversed GIF and SPR and VIF so its the normal way round - all DMA paths should now resume correctly after being stopped by hardware - GIF FIFO now actually transfers stuff :P - VIF CMD's simulated by the length of the interrupts at the end. Phew, i think that's everything :S git-svn-id: http://pcsx2.googlecode.com/svn/trunk@3274 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
24ae022a74
commit
26fece9510
|
@ -628,6 +628,13 @@ static __forceinline tDMA_TAG *SPRdmaGetAddr(u32 addr, bool write)
|
|||
{
|
||||
// if (addr & 0xf) { DMA_LOG("*PCSX2*: DMA address not 128bit aligned: %8.8x", addr); }
|
||||
|
||||
|
||||
//For some reason Getaway references SPR Memory from itself using SPR0, oh well, let it i guess...
|
||||
if((addr & 0x70000000) == 0x70000000)
|
||||
{
|
||||
return (tDMA_TAG*)&psS[addr & 0x3ff0];
|
||||
}
|
||||
|
||||
// FIXME: Why??? DMA uses physical addresses
|
||||
addr &= 0x1ffffff0;
|
||||
|
||||
|
|
|
@ -129,7 +129,18 @@ void __fastcall WriteFIFO_page_4(u32 mem, const mem128_t *value)
|
|||
psHu64(VIF0_FIFO + 8) = value[1];
|
||||
|
||||
vif0ch->qwc += 1;
|
||||
bool ret = VIF0transfer((u32*)value, 4, true);
|
||||
if(vif0.irqoffset != 0 && vif0.vifstalled == true) DevCon.Warning("Offset on VIF0 FIFO start!");
|
||||
bool ret = VIF0transfer((u32*)value, 4);
|
||||
|
||||
if (vif0.cmd)
|
||||
{
|
||||
if(vif0.done == true && vif0ch->qwc == 0) vif0Regs->stat.VPS = VPS_WAITING;
|
||||
}
|
||||
else
|
||||
{
|
||||
vif0Regs->stat.VPS = VPS_IDLE;
|
||||
}
|
||||
|
||||
pxAssertDev( ret, "vif stall code not implemented" );
|
||||
}
|
||||
|
||||
|
@ -148,12 +159,23 @@ void __fastcall WriteFIFO_page_5(u32 mem, const mem128_t *value)
|
|||
DevCon.Warning("writing to vif1 fifo when stalled");
|
||||
|
||||
vif1ch->qwc += 1;
|
||||
bool ret = VIF1transfer((u32*)value, 4, false);
|
||||
if(vif1.irqoffset != 0 && vif1.vifstalled == true) DevCon.Warning("Offset on VIF1 FIFO start!");
|
||||
bool ret = VIF1transfer((u32*)value, 4);
|
||||
|
||||
if (vif1.cmd)
|
||||
{
|
||||
if(vif1.done == true && vif1ch->qwc == 0) vif1Regs->stat.VPS = VPS_WAITING;
|
||||
}
|
||||
else
|
||||
{
|
||||
vif1Regs->stat.VPS = VPS_IDLE;
|
||||
}
|
||||
|
||||
pxAssertDev( ret, "vif stall code not implemented" );
|
||||
}
|
||||
|
||||
// Dummy GIF-TAG Packet to Guarantee Count = 1
|
||||
__aligned16 u32 nloop0_packet[4] = {0x8000, 0, 0, 0};
|
||||
__aligned16 u32 nloop0_packet[4] = {0, 0, 0, 0};
|
||||
|
||||
void __fastcall WriteFIFO_page_6(u32 mem, const mem128_t *value)
|
||||
{
|
||||
|
@ -163,12 +185,23 @@ void __fastcall WriteFIFO_page_6(u32 mem, const mem128_t *value)
|
|||
psHu64(GIF_FIFO) = value[0];
|
||||
psHu64(GIF_FIFO + 8) = value[1];
|
||||
|
||||
nloop0_packet[0] = psHu32(GIF_FIFO);
|
||||
nloop0_packet[1] = psHu32(GIF_FIFO + 4);
|
||||
nloop0_packet[2] = psHu32(GIF_FIFO + 8);
|
||||
nloop0_packet[3] = psHu32(GIF_FIFO + 12);
|
||||
Registers::Freeze();
|
||||
GetMTGS().PrepDataPacket(GIF_PATH_3, nloop0_packet, 1);
|
||||
gifRegs->stat.APATH = GIF_APATH3;
|
||||
GetMTGS().PrepDataPacket(GIF_PATH_3, nloop0_packet, 1, false);
|
||||
u64* data = (u64*)GetMTGS().GetDataPacketPtr();
|
||||
data[0] = value[0];
|
||||
data[1] = value[1];
|
||||
GetMTGS().SendDataPacket();
|
||||
if(GSTransferStatus.PTH3 == PENDINGSTOP_MODE)
|
||||
{
|
||||
GSTransferStatus.PTH3 = STOPPED_MODE;
|
||||
gifRegs->stat.APATH = GIF_APATH_IDLE;
|
||||
if(gifRegs->stat.DIR == 0)gifRegs->stat.OPH = false;
|
||||
}
|
||||
Registers::Thaw();
|
||||
}
|
||||
|
||||
|
|
19
pcsx2/GS.cpp
19
pcsx2/GS.cpp
|
@ -59,7 +59,7 @@ void gsReset()
|
|||
GetMTGS().ResetGS();
|
||||
|
||||
UpdateVSyncRate();
|
||||
GSTransferStatus = (STOPPED_MODE<<4) | (STOPPED_MODE<<2) | STOPPED_MODE;
|
||||
GSTransferStatus = (STOPPED_MODE<<8) | (STOPPED_MODE<<4) | STOPPED_MODE;
|
||||
memzero(g_RealGSMem);
|
||||
|
||||
GSCSRr = 0x551B4000; // Set the FINISH bit to 1 for now
|
||||
|
@ -98,17 +98,15 @@ void gsCSRwrite(u32 value)
|
|||
GSCSRr = 0x551B4000; // Set the FINISH bit to 1 - GS is always at a finish state as we don't have a FIFO(saqib)
|
||||
GSIMR = 0x7F00; //This is bits 14-8 thats all that should be 1
|
||||
}
|
||||
else if( value & 0x100 ) // FLUSH
|
||||
if( value & 0x100 ) // FLUSH
|
||||
{
|
||||
// Our emulated GS has no FIFO, but if it did, it would flush it here...
|
||||
//Console.WriteLn("GS_CSR FLUSH GS fifo: %x (CSRr=%x)", value, GSCSRr);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
CSRw |= value & 0x1f;
|
||||
GetMTGS().SendSimplePacket( GS_RINGTYPE_WRITECSR, CSRw, 0, 0 );
|
||||
GSCSRr = ((GSCSRr&~value)&0x1f)|(GSCSRr&~0x1f);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -224,6 +222,17 @@ void __fastcall gsWrite64_page_01( u32 mem, const mem64_t* value )
|
|||
|
||||
switch( mem )
|
||||
{
|
||||
case 0x12001040: //busdir
|
||||
gsWrite64_generic( mem, value );
|
||||
|
||||
//This is probably a complete hack, however writing to BUSDIR "should" start a transfer (Bleach Blade Battlers)
|
||||
//Only problem is it kills killzone :( leaving it commented out for now.
|
||||
//=========================================================================
|
||||
//gifRegs->stat.OPH = true;
|
||||
//=========================================================================
|
||||
gifRegs->stat.DIR = (u32)value;
|
||||
|
||||
return;
|
||||
case GS_CSR:
|
||||
gsCSRwrite((u32)value[0]);
|
||||
return;
|
||||
|
|
|
@ -157,7 +157,7 @@ enum GIF_PATH
|
|||
GIF_PATH_3,
|
||||
};
|
||||
|
||||
extern int GIFPath_ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size);
|
||||
extern int GIFPath_ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size, bool TestOnly);
|
||||
extern void GIFPath_Reset();
|
||||
extern void GIFPath_Clear( GIF_PATH pathidx );
|
||||
|
||||
|
@ -252,8 +252,8 @@ public:
|
|||
void WaitGS();
|
||||
void ResetGS();
|
||||
|
||||
int PrepDataPacket( GIF_PATH pathidx, const u8* srcdata, u32 size );
|
||||
int PrepDataPacket( GIF_PATH pathidx, const u32* srcdata, u32 size );
|
||||
int PrepDataPacket( GIF_PATH pathidx, const u8* srcdata, u32 size, bool TestOnly );
|
||||
int PrepDataPacket( GIF_PATH pathidx, const u32* srcdata, u32 size, bool TestOnly );
|
||||
void SendDataPacket();
|
||||
void SendGameCRC( u32 crc );
|
||||
void WaitForOpen();
|
||||
|
|
246
pcsx2/Gif.cpp
246
pcsx2/Gif.cpp
|
@ -35,6 +35,11 @@ static u32 gscycles = 0, prevcycles = 0, mfifocycles = 0;
|
|||
static u32 gifqwc = 0;
|
||||
static bool gifmfifoirq = false;
|
||||
|
||||
//Just some temporary bits to store Path1 transfers if another is in progress.
|
||||
u8 Path1Buffer[0x1000000];
|
||||
u32 Path1WritePos = 0;
|
||||
u32 Path1ReadPos = 0;
|
||||
|
||||
static __forceinline void clearFIFOstuff(bool full)
|
||||
{
|
||||
GSCSRr &= ~0xC000; //Clear FIFO stuff
|
||||
|
@ -45,10 +50,51 @@ static __forceinline void clearFIFOstuff(bool full)
|
|||
GSCSRr |= 0x4000; //FIFO empty
|
||||
}
|
||||
|
||||
void gsPath1Interrupt()
|
||||
{
|
||||
//DevCon.Warning("Path1 flush W %x, R %x", Path1WritePos, Path1ReadPos);
|
||||
|
||||
|
||||
|
||||
if((gifRegs->stat.APATH == GIF_APATH_IDLE || gifRegs->stat.APATH == GIF_APATH1) && Path1WritePos > 0 && !gifRegs->stat.PSE)
|
||||
{
|
||||
Registers::Freeze();
|
||||
u32 size = GetMTGS().PrepDataPacket(GIF_PATH_1, Path1Buffer + (Path1ReadPos*16), (Path1WritePos - Path1ReadPos), false);
|
||||
u8* pDest = GetMTGS().GetDataPacketPtr();
|
||||
//DevCon.Warning("Flush Size = %x", size);
|
||||
|
||||
gifRegs->stat.APATH = GIF_APATH1;
|
||||
memcpy_aligned(pDest, Path1Buffer + (Path1ReadPos * 16), size*16);
|
||||
GetMTGS().SendDataPacket();
|
||||
Path1ReadPos += size;
|
||||
if(Path1ReadPos == Path1WritePos)
|
||||
{
|
||||
Path1WritePos = Path1ReadPos = 0;
|
||||
}
|
||||
Registers::Thaw();
|
||||
CPU_INT(28, 16); //Should be size * BIAS (probably) but Tony Hawk doesnt like this, probably to do with vif flush stalling
|
||||
}
|
||||
else
|
||||
{
|
||||
if(Path1WritePos == 0)
|
||||
{
|
||||
gifRegs->stat.P1Q = false;
|
||||
gifRegs->stat.APATH = GIF_APATH_IDLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(gifRegs->stat.PSE) DevCon.Warning("Path1 paused by GIF_CTRL");
|
||||
CPU_INT(28, 16);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
__forceinline void gsInterrupt()
|
||||
{
|
||||
GIF_LOG("gsInterrupt: %8.8x", cpuRegs.cycle);
|
||||
|
||||
|
||||
|
||||
if (!(gif->chcr.STR))
|
||||
{
|
||||
//Console.WriteLn("Eh? why are you still interrupting! chcr %x, qwc %x, done = %x", gif->chcr._u32, gif->qwc, done);
|
||||
|
@ -56,11 +102,6 @@ __forceinline void gsInterrupt()
|
|||
}
|
||||
|
||||
|
||||
if (GSTransferStatus.PTH3 == STOPPED_MODE)
|
||||
{
|
||||
gifRegs->stat.clear_flags(GIF_STAT_APATH3);
|
||||
}
|
||||
|
||||
if ((gif->qwc > 0) || (!gspath3done))
|
||||
{
|
||||
if (!dmacRegs->ctrl.DMAE)
|
||||
|
@ -78,18 +119,16 @@ __forceinline void gsInterrupt()
|
|||
gspath3done = false;
|
||||
gscycles = 0;
|
||||
gif->chcr.STR = false;
|
||||
vif1Regs->stat.VGW = false;
|
||||
if(GSTransferStatus.PTH3 == 3) GSTransferStatus.PTH3 = STOPPED_MODE;
|
||||
gifRegs->stat.clear_flags(GIF_STAT_APATH3 | GIF_STAT_FQC);
|
||||
|
||||
//gifRegs->stat.OPH = false;
|
||||
gifRegs->stat.clear_flags(GIF_STAT_FQC);
|
||||
clearFIFOstuff(false);
|
||||
hwDmacIrq(DMAC_GIF);
|
||||
GIF_LOG("GIF DMA end");
|
||||
//DevCon.Warning("GIF DMA end");
|
||||
}
|
||||
|
||||
static u32 WRITERING_DMA(u32 *pMem, u32 qwc)
|
||||
{
|
||||
int size = GetMTGS().PrepDataPacket(GIF_PATH_3, pMem, qwc);
|
||||
int size = GetMTGS().PrepDataPacket(GIF_PATH_3, pMem, qwc, false);
|
||||
u8* pgsmem = GetMTGS().GetDataPacketPtr();
|
||||
|
||||
memcpy_aligned(pgsmem, pMem, size<<4);
|
||||
|
@ -106,6 +145,7 @@ static u32 WRITERING_DMA(tDMA_TAG *pMem, u32 qwc)
|
|||
int _GIFchain()
|
||||
{
|
||||
tDMA_TAG *pMem;
|
||||
int qwc = 0;
|
||||
|
||||
pMem = dmaGetAddr(gif->madr, false);
|
||||
if (pMem == NULL)
|
||||
|
@ -120,7 +160,12 @@ int _GIFchain()
|
|||
return -1;
|
||||
}
|
||||
|
||||
return WRITERING_DMA(pMem, gif->qwc);
|
||||
//in Intermittent Mode it enabled, IMAGE_MODE transfers are sliced.
|
||||
|
||||
if(gifRegs->stat.IMT && GSTransferStatus.PTH3 == IMAGE_MODE) qwc = min((int)gif->qwc, 8);
|
||||
else qwc = gif->qwc;
|
||||
|
||||
return WRITERING_DMA(pMem, qwc);
|
||||
}
|
||||
|
||||
static __forceinline void GIFchain()
|
||||
|
@ -129,7 +174,7 @@ static __forceinline void GIFchain()
|
|||
// qwc check now done outside this function
|
||||
// Voodoocycles
|
||||
// >> 2 so Drakan and Tekken 5 don't mess up in some PATH3 transfer. Cycles to interrupt were getting huge..
|
||||
/*if (gif->qwc)*/ gscycles+= ( _GIFchain() >> 2 ); /* guessing */
|
||||
/*if (gif->qwc)*/ gscycles+= ( _GIFchain() * BIAS); /* guessing */
|
||||
Registers::Thaw();
|
||||
}
|
||||
|
||||
|
@ -169,6 +214,43 @@ static __forceinline tDMA_TAG* ReadTag2()
|
|||
return ptag;
|
||||
}
|
||||
|
||||
bool CheckPaths(int Channel)
|
||||
{
|
||||
if(GSTransferStatus.PTH3 <= IMAGE_MODE && gifRegs->mode.IMT)
|
||||
{
|
||||
if((gifRegs->stat.P1Q == true || gifRegs->stat.P2Q == true) || (gifRegs->stat.APATH > GIF_APATH_IDLE && gifRegs->stat.APATH < GIF_APATH3))
|
||||
{
|
||||
if((vif1.cmd & 0x7f) != 0x51 || gifRegs->stat.P1Q == true)
|
||||
{
|
||||
if(gifRegs->stat.APATH == GIF_APATH3)
|
||||
{
|
||||
gifRegs->stat.APATH = GIF_APATH_IDLE;
|
||||
}
|
||||
gifRegs->stat.IP3 = true;
|
||||
CPU_INT(DMAC_GIF, 16);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if((GSTransferStatus.PTH3 >= IDLE_MODE))
|
||||
{
|
||||
//This should cover both scenarios, as DIRECTHL doesn't gain priority when image mode is running (PENDINGIMAGE_MODE == fininshed).
|
||||
if((gifRegs->stat.P1Q == true || gifRegs->stat.P2Q == true) || (gifRegs->stat.APATH > GIF_APATH_IDLE && gifRegs->stat.APATH < GIF_APATH3))
|
||||
{
|
||||
if(gifRegs->stat.APATH == GIF_APATH3)
|
||||
{
|
||||
gifRegs->stat.APATH = GIF_APATH_IDLE;
|
||||
}
|
||||
gifRegs->stat.IP3 = true;
|
||||
CPU_INT(DMAC_GIF, 16);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
gifRegs->stat.IP3 = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void GIFdma()
|
||||
{
|
||||
tDMA_TAG *ptag;
|
||||
|
@ -177,7 +259,8 @@ void GIFdma()
|
|||
|
||||
if (gifRegs->ctrl.PSE) // temporarily stop
|
||||
{
|
||||
Console.WriteLn("Gif dma temp paused?");
|
||||
Console.WriteLn("Gif dma temp paused? (non MFIFO GIF)");
|
||||
CPU_INT(DMAC_GIF, 16);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -199,24 +282,14 @@ void GIFdma()
|
|||
clearFIFOstuff(true);
|
||||
gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
|
||||
|
||||
//Path2 gets priority in intermittent 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, GSTransferStatus.PTH3);
|
||||
gifRegs->stat.set_flags(GIF_STAT_P3Q);
|
||||
CPU_INT(DMAC_GIF, 16);
|
||||
return;
|
||||
}
|
||||
gifRegs->stat.clear_flags(GIF_STAT_P3Q);
|
||||
gifRegs->stat.APATH = GIF_APATH3;
|
||||
|
||||
|
||||
if (vif1Regs->mskpath3 || gifRegs->mode.M3R)
|
||||
{
|
||||
if (gif->qwc == 0)
|
||||
{
|
||||
if ((gif->chcr.MOD == CHAIN_MODE) && gif->chcr.STR)
|
||||
{
|
||||
//DevCon.Warning("GIF Reading Tag Masked MSK = %x", vif1Regs->mskpath3);
|
||||
ptag = ReadTag();
|
||||
gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
|
||||
if (ptag == NULL) return;
|
||||
|
@ -226,25 +299,41 @@ void GIFdma()
|
|||
if (checkTieBit(ptag)) GIF_LOG("PATH3 MSK dmaIrq Set");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (GSTransferStatus.PTH3 == STOPPED_MODE) /*|| (vif1Regs->stat._u32 |= VIF1_STAT_VGW) == 0*/
|
||||
if (GSTransferStatus.PTH3 == STOPPED_MODE)
|
||||
{
|
||||
GIF_LOG("PTH3 MASK Paused by VIF");
|
||||
vif1Regs->stat.VGW = false;
|
||||
if (gif->qwc == 0) CPU_INT(DMAC_GIF, 16);
|
||||
|
||||
//DevCon.Warning("GIF Paused by Mask MSK = %x", vif1Regs->mskpath3);
|
||||
|
||||
if(gif->qwc == 0) gsInterrupt();
|
||||
else gifRegs->stat.set_flags(GIF_STAT_P3Q);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//gifRegs->stat.OPH = true;
|
||||
gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
|
||||
//Check with Path3 masking games
|
||||
if (gif->qwc > 0) {
|
||||
gifRegs->stat.set_flags(GIF_STAT_P3Q);
|
||||
if(CheckPaths(DMAC_GIF) == false) return;
|
||||
gifRegs->stat.clear_flags(GIF_STAT_P3Q);
|
||||
GIF_LOG("PTH3 MASK Transferring");
|
||||
GIFchain();
|
||||
GIFchain();
|
||||
/*if(GSTransferStatus.PTH3 == PENDINGSTOP_MODE && gifRegs->stat.APATH == GIF_APATH_IDLE)
|
||||
{
|
||||
GSTransferStatus.PTH3 = STOPPED_MODE;
|
||||
}*/
|
||||
}//else DevCon.WriteLn("GIFdma() case 1, but qwc = 0!"); //Don't do 0 GIFchain and then return
|
||||
CPU_INT(DMAC_GIF, gscycles * BIAS);
|
||||
CPU_INT(DMAC_GIF, gscycles);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//gifRegs->stat.OPH = true;
|
||||
// Transfer Dn_QWC from Dn_MADR to GIF
|
||||
if ((gif->chcr.MOD == NORMAL_MODE) || (gif->qwc > 0)) // Normal Mode
|
||||
{
|
||||
|
@ -255,13 +344,18 @@ void GIFdma()
|
|||
}
|
||||
gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
|
||||
//Check with Path3 masking games
|
||||
//DevCon.Warning("GIF Transferring Normal/ChainQWC MSK = %x", vif1Regs->mskpath3);
|
||||
|
||||
|
||||
|
||||
if (gif->qwc > 0) {
|
||||
gifRegs->stat.set_flags(GIF_STAT_P3Q);
|
||||
if(CheckPaths(DMAC_GIF) == false) return;
|
||||
gifRegs->stat.clear_flags(GIF_STAT_P3Q);
|
||||
GIFchain(); //Transfers the data set by the switch
|
||||
CPU_INT(DMAC_GIF, gscycles * BIAS);
|
||||
CPU_INT(DMAC_GIF, gscycles);
|
||||
return;
|
||||
} else { //Else it really is a normal transfer and we want to quit, else it gets confused with chains
|
||||
gspath3done = 1;
|
||||
}
|
||||
} else DevCon.Warning("GIF Normalmode or QWC going to invalid case? CHCR %x", gif->chcr);
|
||||
|
||||
//else DevCon.WriteLn("GIFdma() case 2, but qwc = 0!"); //Don't do 0 GIFchain and then return, fixes Dual Hearts
|
||||
}
|
||||
|
@ -270,6 +364,7 @@ void GIFdma()
|
|||
{
|
||||
ptag = ReadTag();
|
||||
if (ptag == NULL) return;
|
||||
//DevCon.Warning("GIF Reading Tag MSK = %x", vif1Regs->mskpath3);
|
||||
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 = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
|
||||
if (dmacRegs->ctrl.STD == STD_GIF)
|
||||
|
@ -290,65 +385,48 @@ void GIFdma()
|
|||
}
|
||||
|
||||
checkTieBit(ptag);
|
||||
/*if(gif->qwc == 0)
|
||||
{
|
||||
gsInterrupt();
|
||||
return;
|
||||
}*/
|
||||
}
|
||||
|
||||
prevcycles = 0;
|
||||
|
||||
if ((!gspath3done) && (gif->qwc == 0))
|
||||
{
|
||||
ptag = dmaGetAddr(gif->tadr, false); //Set memory pointer to TADR
|
||||
gif->unsafeTransfer(ptag);
|
||||
gif->madr = ptag[1]._u32;
|
||||
|
||||
gspath3done = hwDmacSrcChainWithStack(gif, ptag->ID);
|
||||
|
||||
checkTieBit(ptag);
|
||||
|
||||
GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr, gif->tadr);
|
||||
CPU_INT(DMAC_GIF, gscycles * BIAS);
|
||||
}
|
||||
else
|
||||
{
|
||||
CPU_INT(DMAC_GIF, gscycles * BIAS);
|
||||
gscycles = 0;
|
||||
}
|
||||
gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
|
||||
CPU_INT(DMAC_GIF, gscycles);
|
||||
gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // OPH=1 | APATH=3]
|
||||
}
|
||||
|
||||
void dmaGIF()
|
||||
{
|
||||
//We used to add wait time for the buffer to fill here, fixing some timing problems in path 3 masking
|
||||
//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);
|
||||
//DevCon.Warning("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);
|
||||
|
||||
//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;
|
||||
gifRegs->stat.FQC |= 0x10; // hack ;)
|
||||
|
||||
if (gif->chcr.MOD == NORMAL_MODE) { //Else it really is a normal transfer and we want to quit, else it gets confused with chains
|
||||
gspath3done = true;
|
||||
}
|
||||
clearFIFOstuff(true);
|
||||
|
||||
if(gif->chcr.MOD == CHAIN_MODE && gif->qwc > 0)
|
||||
{
|
||||
//DevCon.Warning(L"GIF QWC on Chain " + gif->chcr.desc());
|
||||
if(((gif->chcr.TAG >> 12) & 0x7) == 0x0 || ((gif->chcr.TAG >> 12) & 0x7) == 0x7)
|
||||
{
|
||||
gspath3done = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (dmacRegs->ctrl.MFD == MFD_GIF) // GIF MFIFO
|
||||
{
|
||||
//Console.WriteLn("GIF MFIFO");
|
||||
gifMFIFOInterrupt();
|
||||
return;
|
||||
}
|
||||
|
||||
if ((gif->qwc == 0) && (gif->chcr.MOD != NORMAL_MODE))
|
||||
{
|
||||
tDMA_TAG* ptag = ReadTag2();
|
||||
GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr, gif->tadr);
|
||||
|
||||
checkTieBit(ptag);
|
||||
GIFdma();
|
||||
return;
|
||||
}
|
||||
|
||||
//Halflife sets a QWC amount in chain mode, no tadr set.
|
||||
if (gif->qwc > 0) gspath3done = true;
|
||||
if(gif->chcr.MOD == CHAIN_MODE && gif->qwc > 0) DevCon.Warning(L"GIF QWC on Chain " + gif->chcr.desc());
|
||||
}
|
||||
|
||||
GIFdma();
|
||||
}
|
||||
|
@ -447,7 +525,12 @@ void mfifoGIFtransfer(int qwc)
|
|||
gifempty = false;
|
||||
}
|
||||
|
||||
GIF_LOG("mfifoGIFtransfer %x madr %x, tadr %x", gif->chcr._u32, gif->madr, gif->tadr);
|
||||
if (gifRegs->ctrl.PSE) // temporarily stop
|
||||
{
|
||||
Console.WriteLn("Gif dma temp paused?");
|
||||
CPU_INT(11, 16);
|
||||
return;
|
||||
}
|
||||
|
||||
if (gif->qwc == 0)
|
||||
{
|
||||
|
@ -540,11 +623,7 @@ void gifMFIFOInterrupt()
|
|||
gifRegs->stat.APATH = GIF_APATH_IDLE;
|
||||
}
|
||||
|
||||
if ((spr0->chcr.STR) && (spr0->qwc == 0))
|
||||
{
|
||||
spr0->chcr.STR = false;
|
||||
hwDmacIrq(DMAC_FROM_SPR);
|
||||
}
|
||||
if(CheckPaths(11) == false) return;
|
||||
|
||||
if (!(gif->chcr.STR))
|
||||
{
|
||||
|
@ -553,13 +632,6 @@ void gifMFIFOInterrupt()
|
|||
return;
|
||||
}
|
||||
|
||||
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), GSTransferStatus.PTH3);
|
||||
CPU_INT(11,mfifocycles);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(gifstate & GIF_STATE_STALL))
|
||||
{
|
||||
if (gifqwc <= 0)
|
||||
|
|
22
pcsx2/Gif.h
22
pcsx2/Gif.h
|
@ -26,17 +26,20 @@ enum gifstate_t
|
|||
|
||||
enum GSTransferModes //0 = Image Mode (DirectHL), 1 = transferring, 2 = Stopped at End of Packet
|
||||
{
|
||||
IMAGE_MODE = 0,
|
||||
TRANSFER_MODE = 1,
|
||||
STOPPED_MODE = 2
|
||||
PENDINGIMAGE_MODE = 0,
|
||||
IMAGE_MODE = 1,
|
||||
TRANSFER_MODE = 2,
|
||||
PENDINGSTOP_MODE = 3,
|
||||
IDLE_MODE = 4,
|
||||
STOPPED_MODE = 5
|
||||
};
|
||||
|
||||
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 PTH1 : 4; // Resets Vif(0/1) when written.
|
||||
u32 PTH2 : 4; // Causes a Forcebreak to Vif((0/1) when true. (Stall)
|
||||
u32 PTH3 : 4; // Stops after the end of the Vifcode in progress when true. (Stall)
|
||||
u32 reserved : 20;
|
||||
};
|
||||
u32 _u32;
|
||||
|
||||
|
@ -285,4 +288,9 @@ extern void dmaGIF();
|
|||
extern void mfifoGIFtransfer(int qwc);
|
||||
extern void gifMFIFOInterrupt();
|
||||
|
||||
//Just some temporary bits to store Path1 transfers if another is in progress.
|
||||
extern void gsPath1Interrupt();
|
||||
extern u8 Path1Buffer[0x1000000];
|
||||
extern u32 Path1WritePos;
|
||||
extern u32 Path1ReadPos;
|
||||
#endif
|
||||
|
|
29
pcsx2/Hw.cpp
29
pcsx2/Hw.cpp
|
@ -75,13 +75,15 @@ void hwReset()
|
|||
|
||||
__forceinline void intcInterrupt()
|
||||
{
|
||||
if ((cpuRegs.CP0.n.Status.val & 0x400) != 0x400) return;
|
||||
|
||||
if ((psHu32(INTC_STAT)) == 0) {
|
||||
DevCon.Warning("*PCSX2*: intcInterrupt already cleared");
|
||||
//DevCon.Warning("*PCSX2*: intcInterrupt already cleared");
|
||||
return;
|
||||
}
|
||||
if ((psHu32(INTC_STAT) & psHu32(INTC_MASK)) == 0) return;
|
||||
if ((psHu32(INTC_STAT) & psHu32(INTC_MASK)) == 0)
|
||||
{
|
||||
//DevCon.Warning("*PCSX2*: No valid interrupt INTC_MASK: %x INTC_STAT: %x", psHu32(INTC_MASK), psHu32(INTC_STAT));
|
||||
return;
|
||||
}
|
||||
|
||||
HW_LOG("intcInterrupt %x", psHu32(INTC_STAT) & psHu32(INTC_MASK));
|
||||
if(psHu32(INTC_STAT) & 0x2){
|
||||
|
@ -94,13 +96,18 @@ __forceinline void intcInterrupt()
|
|||
|
||||
__forceinline void dmacInterrupt()
|
||||
{
|
||||
if ((cpuRegs.CP0.n.Status.val & 0x10807) != 0x10801) return;
|
||||
|
||||
if( ((psHu16(DMAC_STAT + 2) & psHu16(DMAC_STAT)) == 0 ) &&
|
||||
( psHu16(DMAC_STAT) & 0x8000) == 0 ) return;
|
||||
|
||||
if (!(dmacRegs->ctrl.DMAE)) return;
|
||||
( psHu16(DMAC_STAT) & 0x8000) == 0 )
|
||||
{
|
||||
//DevCon.Warning("No valid DMAC interrupt MASK %x STAT %x", psHu16(DMAC_STAT+2), psHu16(DMAC_STAT));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(dmacRegs->ctrl.DMAE) || psHu8(DMAC_ENABLER+2) == 1)
|
||||
{
|
||||
//DevCon.Warning("DMAC Suspended or Disabled on interrupt");
|
||||
return;
|
||||
}
|
||||
HW_LOG("dmacInterrupt %x", (psHu16(DMAC_STAT + 2) & psHu16(DMAC_STAT) |
|
||||
psHu16(DMAC_STAT) & 0x8000));
|
||||
|
||||
|
@ -110,13 +117,13 @@ __forceinline void dmacInterrupt()
|
|||
void hwIntcIrq(int n)
|
||||
{
|
||||
psHu32(INTC_STAT) |= 1<<n;
|
||||
cpuTestINTCInts();
|
||||
if(psHu32(INTC_MASK) & (1<<n))cpuTestINTCInts();
|
||||
}
|
||||
|
||||
void hwDmacIrq(int n)
|
||||
{
|
||||
psHu32(DMAC_STAT) |= 1<<n;
|
||||
cpuTestDMACInts();
|
||||
if(psHu16(DMAC_STAT+2) & (1<<n))cpuTestDMACInts();
|
||||
}
|
||||
|
||||
// Write 'size' bytes to memory address 'addr' from 'data'.
|
||||
|
|
|
@ -381,7 +381,9 @@ mem32_t __fastcall hwRead32_generic(u32 mem)
|
|||
// It'll all optimize to ziltch in public release builds.
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
case 0x03:
|
||||
if((mem & 0xfff) < 0x800) break;
|
||||
if(masked_mem >= 0x3800) HW_LOG("VIF%x Register Read32 at 0x%x, value=0x%x", (masked_mem < 0x3c00) ? 0 : 1, mem, psHu32(mem) );
|
||||
else HW_LOG("GIF Register Read32 at 0x%x, value=0x%x", mem, psHu32(mem) );
|
||||
break;
|
||||
case 0x04:
|
||||
case 0x05:
|
||||
case 0x06:
|
||||
|
|
|
@ -75,8 +75,19 @@ static __forceinline void DmaExec8( void (*func)(), u32 mem, u8 value )
|
|||
if(value == 0)
|
||||
{
|
||||
//DevCon.Warning(L"8bit %s DMA Stopped on Suspend", ChcrName(mem & ~0xf));
|
||||
if(ChannelNumber(mem & ~0xf) == 1)
|
||||
{
|
||||
cpuClearInt( 10 );
|
||||
QueuedDMA._u16 &= ~(1 << 10); //Clear any queued DMA requests for this channel
|
||||
}
|
||||
else if(ChannelNumber(mem & ~0xf) == 2)
|
||||
{
|
||||
cpuClearInt( 11 );
|
||||
QueuedDMA._u16 &= ~(1 << 11); //Clear any queued DMA requests for this channel
|
||||
}
|
||||
|
||||
cpuClearInt( ChannelNumber(mem & ~0xf) );
|
||||
QueuedDMA._u16 &= ~(1 << ChannelNumber(mem & ~0xf));
|
||||
QueuedDMA._u16 &= ~(1 << ChannelNumber(mem & ~0xf)); //Clear any queued DMA requests for this channel;
|
||||
}
|
||||
//Here we update the CHCR STR (Busy) bit, we don't touch anything else.
|
||||
reg->chcr.STR = value;
|
||||
|
@ -93,8 +104,20 @@ static __forceinline void DmaExec8( void (*func)(), u32 mem, u8 value )
|
|||
//DevCon.Warning(L"8bit Force Stopping %s (Current CHCR %x) while DMA active", ChcrName(mem & ~0xf), reg->chcr._u32, value);
|
||||
reg->chcr.STR = value;
|
||||
//We need to clear any existing DMA loops that are in progress else they will continue!
|
||||
cpuClearInt( ChannelNumber(mem&~0xf) );
|
||||
QueuedDMA._u16 &= ~(1 << ChannelNumber(mem&~0xf)); //Clear any queued DMA requests for this channel
|
||||
|
||||
if(ChannelNumber(mem & ~0xf) == 1)
|
||||
{
|
||||
cpuClearInt( 10 );
|
||||
QueuedDMA._u16 &= ~(1 << 10); //Clear any queued DMA requests for this channel
|
||||
}
|
||||
else if(ChannelNumber(mem & ~0xf) == 2)
|
||||
{
|
||||
cpuClearInt( 11 );
|
||||
QueuedDMA._u16 &= ~(1 << 11); //Clear any queued DMA requests for this channel
|
||||
}
|
||||
|
||||
cpuClearInt( ChannelNumber(mem & ~0xf) );
|
||||
QueuedDMA._u16 &= ~(1 << ChannelNumber(mem & ~0xf)); //Clear any queued DMA requests for this channel
|
||||
}
|
||||
//else DevCon.Warning(L"8bit Attempted to stop %s DMA without suspend, ignoring", ChcrName(mem & ~0xf));
|
||||
return;
|
||||
|
@ -132,6 +155,17 @@ static __forceinline void DmaExec16( void (*func)(), u32 mem, u16 value )
|
|||
if(chcr.STR == 0)
|
||||
{
|
||||
//DevCon.Warning(L"16bit %s DMA Stopped on Suspend", ChcrName(mem));
|
||||
if(ChannelNumber(mem) == 1)
|
||||
{
|
||||
cpuClearInt( 10 );
|
||||
QueuedDMA._u16 &= ~(1 << 10); //Clear any queued DMA requests for this channel
|
||||
}
|
||||
else if(ChannelNumber(mem) == 2)
|
||||
{
|
||||
cpuClearInt( 11 );
|
||||
QueuedDMA._u16 &= ~(1 << 11); //Clear any queued DMA requests for this channel
|
||||
}
|
||||
|
||||
cpuClearInt( ChannelNumber(mem) );
|
||||
QueuedDMA._u16 &= ~(1 << ChannelNumber(mem)); //Clear any queued DMA requests for this channel
|
||||
}
|
||||
|
@ -150,6 +184,18 @@ static __forceinline void DmaExec16( void (*func)(), u32 mem, u16 value )
|
|||
//DevCon.Warning(L"16bit Force Stopping %s (Current CHCR %x) while DMA active", ChcrName(mem), reg->chcr._u32, chcr._u32);
|
||||
reg->chcr.STR = 0;
|
||||
//We need to clear any existing DMA loops that are in progress else they will continue!
|
||||
|
||||
if(ChannelNumber(mem) == 1)
|
||||
{
|
||||
cpuClearInt( 10 );
|
||||
QueuedDMA._u16 &= ~(1 << 10); //Clear any queued DMA requests for this channel
|
||||
}
|
||||
else if(ChannelNumber(mem) == 2)
|
||||
{
|
||||
cpuClearInt( 11 );
|
||||
QueuedDMA._u16 &= ~(1 << 11); //Clear any queued DMA requests for this channel
|
||||
}
|
||||
|
||||
cpuClearInt( ChannelNumber(mem) );
|
||||
QueuedDMA._u16 &= ~(1 << ChannelNumber(mem)); //Clear any queued DMA requests for this channel
|
||||
}
|
||||
|
@ -189,8 +235,19 @@ static void DmaExec( void (*func)(), u32 mem, u32 value )
|
|||
if(chcr.STR == 0)
|
||||
{
|
||||
//DevCon.Warning(L"32bit %s DMA Stopped on Suspend", ChcrName(mem));
|
||||
QueuedDMA._u16 &= ~(1 << ChannelNumber(mem)); //Clear any queued DMA requests for this channel
|
||||
if(ChannelNumber(mem) == 1)
|
||||
{
|
||||
cpuClearInt( 10 );
|
||||
QueuedDMA._u16 &= ~(1 << 10); //Clear any queued DMA requests for this channel
|
||||
}
|
||||
else if(ChannelNumber(mem) == 2)
|
||||
{
|
||||
cpuClearInt( 11 );
|
||||
QueuedDMA._u16 &= ~(1 << 11); //Clear any queued DMA requests for this channel
|
||||
}
|
||||
|
||||
cpuClearInt( ChannelNumber(mem) );
|
||||
QueuedDMA._u16 &= ~(1 << ChannelNumber(mem)); //Clear any queued DMA requests for this channel
|
||||
}
|
||||
//Sanity Check for possible future bug fix0rs ;p
|
||||
//Spams on Persona 4 opening.
|
||||
|
@ -211,6 +268,18 @@ static void DmaExec( void (*func)(), u32 mem, u32 value )
|
|||
//DevCon.Warning(L"32bit Force Stopping %s (Current CHCR %x) while DMA active", ChcrName(mem), reg->chcr._u32, chcr._u32);
|
||||
reg->chcr.STR = 0;
|
||||
//We need to clear any existing DMA loops that are in progress else they will continue!
|
||||
|
||||
if(ChannelNumber(mem) == 1)
|
||||
{
|
||||
cpuClearInt( 10 );
|
||||
QueuedDMA._u16 &= ~(1 << 10); //Clear any queued DMA requests for this channel
|
||||
}
|
||||
else if(ChannelNumber(mem) == 2)
|
||||
{
|
||||
cpuClearInt( 11 );
|
||||
QueuedDMA._u16 &= ~(1 << 11); //Clear any queued DMA requests for this channel
|
||||
}
|
||||
|
||||
cpuClearInt( ChannelNumber(mem) );
|
||||
QueuedDMA._u16 &= ~(1 << ChannelNumber(mem)); //Clear any queued DMA requests for this channel
|
||||
}
|
||||
|
@ -282,6 +351,31 @@ void hwWrite8(u32 mem, u8 value)
|
|||
case RCNT3_MODE + 1: rcntWmode(3, (counters[3].modeval & 0xff) | value << 8); break;
|
||||
case RCNT3_TARGET: rcntWtarget(3, value); break;
|
||||
|
||||
case GIF_CTRL:
|
||||
psHu32(mem) = value & 0x8;
|
||||
DevCon.Warning("GIFCTRL 8 = %x", value);
|
||||
if (value & 0x1)
|
||||
gsGIFReset();
|
||||
|
||||
if ( value & 8 )
|
||||
gifRegs->stat.PSE = true;
|
||||
else
|
||||
gifRegs->stat.PSE = false;
|
||||
break;
|
||||
|
||||
case GIF_MODE:
|
||||
{
|
||||
// need to set GIF_MODE (hamster ball)
|
||||
gifRegs->mode.write(value);
|
||||
|
||||
// set/clear bits 0 and 2 as per the GIF_MODE value.
|
||||
const u32 bitmask = GIF_MODE_M3R | GIF_MODE_IMT;
|
||||
psHu32(GIF_STAT) &= ~bitmask;
|
||||
psHu32(GIF_STAT) |= (u32)value & bitmask;
|
||||
if(value & GIF_MODE_M3R) DevCon.Warning("8bit GIFMODE M3R write %x", value);
|
||||
//if(value & GIF_MODE_IMT) DevCon.Warning("8bit GIFMODE INT write %x", value);
|
||||
}
|
||||
break;
|
||||
case SIO_TXFIFO:
|
||||
{
|
||||
// Terminate lines on CR or full buffers, and ignore \n's if the string contents
|
||||
|
@ -394,6 +488,13 @@ void hwWrite8(u32 mem, u8 value)
|
|||
psHu8(mem) = value;
|
||||
break;
|
||||
|
||||
case DMAC_STAT:
|
||||
case DMAC_STAT + 1:
|
||||
case DMAC_STAT + 2:
|
||||
case DMAC_STAT + 3:
|
||||
DevCon.Warning("8bit dmac stat! %x", mem);
|
||||
break;
|
||||
|
||||
case DMAC_ENABLEW + 2:
|
||||
oldvalue = psHu8(DMAC_ENABLEW + 2);
|
||||
psHu8(DMAC_ENABLEW + 2) = value;
|
||||
|
@ -403,6 +504,18 @@ void hwWrite8(u32 mem, u8 value)
|
|||
if (!QueuedDMA.empty()) StartQueuedDMA();
|
||||
}
|
||||
break;
|
||||
case DMAC_CTRL+2:
|
||||
oldvalue = psHu8(mem);
|
||||
if ((oldvalue & 0x3) != (value & 0x3))
|
||||
{
|
||||
DevCon.Warning("8 Stall Source Changed to %x", (value & 0x30) >> 4);
|
||||
}
|
||||
if ((oldvalue & 0xC) != (value & 0xC))
|
||||
{
|
||||
DevCon.Warning("8 Stall Destination Changed to %x", (value & 0xC0) >> 4);
|
||||
}
|
||||
psHu8(mem) = value;
|
||||
break;
|
||||
|
||||
case SBUS_F200: // SIF(?)
|
||||
psHu8(mem) = value;
|
||||
|
@ -474,6 +587,32 @@ __forceinline void hwWrite16(u32 mem, u16 value)
|
|||
case RCNT3_MODE: rcntWmode(3, value); break;
|
||||
case RCNT3_TARGET: rcntWtarget(3, value); break;
|
||||
|
||||
case GIF_CTRL:
|
||||
psHu32(mem) = value & 0x8;
|
||||
DevCon.Warning("GIFCTRL 16 %x", value);
|
||||
if (value & 0x1)
|
||||
gsGIFReset();
|
||||
|
||||
if ( value & 8 )
|
||||
gifRegs->stat.PSE = true;
|
||||
else
|
||||
gifRegs->stat.PSE = false;
|
||||
break;
|
||||
|
||||
case GIF_MODE:
|
||||
{
|
||||
// need to set GIF_MODE (hamster ball)
|
||||
gifRegs->mode.write(value);
|
||||
|
||||
// set/clear bits 0 and 2 as per the GIF_MODE value.
|
||||
const u32 bitmask = GIF_MODE_M3R | GIF_MODE_IMT;
|
||||
psHu32(GIF_STAT) &= ~bitmask;
|
||||
psHu32(GIF_STAT) |= (u32)value & bitmask;
|
||||
if(value & GIF_MODE_M3R) DevCon.Warning("16bit GIFMODE M3R write %x", value);
|
||||
//if(value & GIF_MODE_IMT) DevCon.Warning("16bit GIFMODE INT write %x", value);
|
||||
|
||||
}
|
||||
break;
|
||||
case D0_CHCR: // dma0 - vif0
|
||||
DMA_LOG("VIF0dma %lx", value);
|
||||
DmaExec16(dmaVIF0, mem, value);
|
||||
|
@ -667,6 +806,10 @@ __forceinline void hwWrite16(u32 mem, u16 value)
|
|||
//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_STAT:
|
||||
case DMAC_STAT + 2:
|
||||
DevCon.Warning("16bit dmac stat! %x", mem);
|
||||
break;
|
||||
|
||||
case DMAC_ENABLEW + 2:
|
||||
oldvalue = psHu8(DMAC_ENABLEW + 2);
|
||||
|
@ -677,7 +820,18 @@ __forceinline void hwWrite16(u32 mem, u16 value)
|
|||
if (!QueuedDMA.empty()) StartQueuedDMA();
|
||||
}
|
||||
break;
|
||||
|
||||
case DMAC_CTRL:
|
||||
oldvalue = psHu16(mem);
|
||||
if ((oldvalue & 0x30) != (value & 0x30))
|
||||
{
|
||||
DevCon.Warning("Stall Source Changed to %x", (value & 0x30) >> 4);
|
||||
}
|
||||
if ((oldvalue & 0xC0) != (value & 0xC0))
|
||||
{
|
||||
DevCon.Warning("Stall Destination Changed to %x", (value & 0xC0) >> 4);
|
||||
}
|
||||
psHu16(mem) = value;
|
||||
break;
|
||||
case SIO_ISR:
|
||||
case SIO_ISR + 2:
|
||||
case 0x1000f410:
|
||||
|
@ -786,7 +940,8 @@ void __fastcall hwWrite32_page_03( u32 mem, u32 value )
|
|||
|
||||
if (value & 0x1)
|
||||
gsGIFReset();
|
||||
else if ( value & 8 )
|
||||
|
||||
if ( value & 8 )
|
||||
gifRegs->stat.PSE = true;
|
||||
else
|
||||
gifRegs->stat.PSE = false;
|
||||
|
@ -866,6 +1021,14 @@ void __fastcall hwWrite32_page_0E( u32 mem, u32 value )
|
|||
{
|
||||
if (!QueuedDMA.empty()) StartQueuedDMA();
|
||||
}
|
||||
if ((oldvalue & 0x30) != (value & 0x30))
|
||||
{
|
||||
DevCon.Warning("Stall Source Changed to %x", (value & 0x30) >> 4);
|
||||
}
|
||||
if ((oldvalue & 0xC0) != (value & 0xC0))
|
||||
{
|
||||
DevCon.Warning("Stall Destination Changed to %x", (value & 0xC0) >> 4);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1127,6 +1290,14 @@ void __fastcall hwWrite64_page_0E( u32 mem, const mem64_t* srcval )
|
|||
{
|
||||
if (!QueuedDMA.empty()) StartQueuedDMA();
|
||||
}
|
||||
if ((oldvalue & 0x30) != (value & 0x30))
|
||||
{
|
||||
DevCon.Warning("Stall Source Changed to %x", (value & 0x30) >> 4);
|
||||
}
|
||||
if ((oldvalue & 0xC0) != (value & 0xC0))
|
||||
{
|
||||
DevCon.Warning("Stall Destination Changed to %x", (value & 0xC0) >> 4);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -197,12 +197,14 @@ void psxDma9(u32 madr, u32 bcr, u32 chcr)
|
|||
sif0.iop.busy = true;
|
||||
psHu32(SBUS_F240) |= 0x2000;
|
||||
|
||||
if (sif0.ee.busy)
|
||||
{
|
||||
/*if (sif0.ee.busy)
|
||||
{*/
|
||||
XMMRegisters::Freeze();
|
||||
SIF0Dma();
|
||||
psHu32(SBUS_F240) &= ~0x20;
|
||||
psHu32(SBUS_F240) &= ~0x2000;
|
||||
}
|
||||
XMMRegisters::Thaw();
|
||||
//}
|
||||
}
|
||||
|
||||
void psxDma10(u32 madr, u32 bcr, u32 chcr)
|
||||
|
@ -212,15 +214,15 @@ void psxDma10(u32 madr, u32 bcr, u32 chcr)
|
|||
sif1.iop.busy = true;
|
||||
psHu32(SBUS_F240) |= 0x4000;
|
||||
|
||||
if (sif1.ee.busy)
|
||||
{
|
||||
/*if (sif1.ee.busy)
|
||||
{*/
|
||||
XMMRegisters::Freeze();
|
||||
SIF1Dma();
|
||||
psHu32(SBUS_F240) &= ~0x40;
|
||||
psHu32(SBUS_F240) &= ~0x100;
|
||||
psHu32(SBUS_F240) &= ~0x4000;
|
||||
XMMRegisters::Thaw();
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
/* psxDma11 & psxDma 12 are in IopSio2.cpp, along with the appropriate interrupt functions. */
|
||||
|
|
|
@ -594,9 +594,9 @@ void SysMtgsThread::SendDataPacket()
|
|||
//m_PacketLocker.Release();
|
||||
}
|
||||
|
||||
int SysMtgsThread::PrepDataPacket( GIF_PATH pathidx, const u32* srcdata, u32 size )
|
||||
int SysMtgsThread::PrepDataPacket( GIF_PATH pathidx, const u32* srcdata, u32 size, bool TestOnly )
|
||||
{
|
||||
return PrepDataPacket( pathidx, (u8*)srcdata, size );
|
||||
return PrepDataPacket( pathidx, (u8*)srcdata, size, TestOnly );
|
||||
}
|
||||
|
||||
#ifdef PCSX2_GSRING_TX_STATS
|
||||
|
@ -614,7 +614,7 @@ static u32 ringtx_inf_s[32];
|
|||
// around VU memory instead of having buffer overflow...
|
||||
// Parameters:
|
||||
// size - size of the packet data, in smd128's
|
||||
int SysMtgsThread::PrepDataPacket( GIF_PATH pathidx, const u8* srcdata, u32 size )
|
||||
int SysMtgsThread::PrepDataPacket( GIF_PATH pathidx, const u8* srcdata, u32 size, bool TestOnly )
|
||||
{
|
||||
//m_PacketLocker.Acquire();
|
||||
|
||||
|
@ -674,9 +674,10 @@ int SysMtgsThread::PrepDataPacket( GIF_PATH pathidx, const u8* srcdata, u32 size
|
|||
pxAssert( size < RingBufferSize );
|
||||
pxAssert( writepos < RingBufferSize );
|
||||
|
||||
m_packet_size = GIFPath_ParseTag(pathidx, srcdata, size);
|
||||
m_packet_size = GIFPath_ParseTag(pathidx, srcdata, size, TestOnly);
|
||||
if( TestOnly == true) return m_packet_size;
|
||||
size = m_packet_size + 1; // takes into account our command qword.
|
||||
|
||||
|
||||
if( writepos + size < RingBufferSize )
|
||||
{
|
||||
// generic gs wait/stall.
|
||||
|
|
|
@ -294,8 +294,9 @@ static __forceinline void _cpuTestInterrupts()
|
|||
/* These are 'pcsx2 interrupts', they handle asynchronous stuff
|
||||
that depends on the cycle timings */
|
||||
|
||||
TESTINT(1, vif1Interrupt);
|
||||
TESTINT(2, gsInterrupt);
|
||||
TESTINT(28, gsPath1Interrupt);
|
||||
TESTINT(1, vif1Interrupt);
|
||||
TESTINT(2, gsInterrupt);
|
||||
TESTINT(5, EEsif0Interrupt);
|
||||
TESTINT(6, EEsif1Interrupt);
|
||||
|
||||
|
@ -351,10 +352,12 @@ static __forceinline void _cpuTestPERF()
|
|||
// them out. Exceptions while the exception handler is active (EIE), or exceptions of any
|
||||
// level other than 0 are ignored here.
|
||||
|
||||
static bool cpuIntsEnabled()
|
||||
static bool cpuIntsEnabled(int Interrupt)
|
||||
{
|
||||
int IntType = cpuRegs.CP0.n.Status.val & Interrupt; //Choose either INTC or DMAC, depending on what called it
|
||||
|
||||
return cpuRegs.CP0.n.Status.b.EIE && cpuRegs.CP0.n.Status.b.IE &&
|
||||
!cpuRegs.CP0.n.Status.b.EXL && (cpuRegs.CP0.n.Status.b.ERL == 0);
|
||||
!cpuRegs.CP0.n.Status.b.EXL && (cpuRegs.CP0.n.Status.b.ERL == 0) && Interrupt;
|
||||
}
|
||||
|
||||
// if cpuRegs.cycle is greater than this cycle, should check cpuBranchTest for updates
|
||||
|
@ -480,18 +483,15 @@ __forceinline void _cpuBranchTest_Shared()
|
|||
// exceptions.
|
||||
|
||||
//if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001)
|
||||
if( cpuIntsEnabled() )
|
||||
{
|
||||
TESTINT(30, intcInterrupt);
|
||||
TESTINT(31, dmacInterrupt);
|
||||
}
|
||||
if( cpuIntsEnabled(0x400) ) TESTINT(30, intcInterrupt);
|
||||
if( cpuIntsEnabled(0x800) ) TESTINT(31, dmacInterrupt);
|
||||
}
|
||||
|
||||
__releaseinline void cpuTestINTCInts()
|
||||
{
|
||||
if( cpuRegs.interrupt & (1 << 30) ) return;
|
||||
//if( (cpuRegs.CP0.n.Status.val & 0x10407) != 0x10401 ) return;
|
||||
if( !cpuIntsEnabled() ) return;
|
||||
if( !cpuIntsEnabled(0x400) ) return;
|
||||
if( (psHu32(INTC_STAT) & psHu32(INTC_MASK)) == 0 ) return;
|
||||
|
||||
cpuRegs.interrupt|= 1 << 30;
|
||||
|
@ -512,7 +512,8 @@ __releaseinline void cpuTestINTCInts()
|
|||
__forceinline void cpuTestDMACInts()
|
||||
{
|
||||
if ( cpuRegs.interrupt & (1 << 31) ) return;
|
||||
if ((cpuRegs.CP0.n.Status.val & 0x10807) != 0x10801) return;
|
||||
|
||||
if( !cpuIntsEnabled(0x800) ) return;
|
||||
|
||||
if ( ( (psHu16(0xe012) & psHu16(0xe010)) == 0) &&
|
||||
( (psHu16(0xe010) & 0x8000) == 0) ) return;
|
||||
|
|
145
pcsx2/SPR.cpp
145
pcsx2/SPR.cpp
|
@ -81,12 +81,12 @@ int _SPR0chain()
|
|||
|
||||
spr0->sadr += spr0->qwc << 4;
|
||||
|
||||
return (spr0->qwc) * BIAS; // bus is 1/2 the ee speed
|
||||
return (spr0->qwc); // bus is 1/2 the ee speed
|
||||
}
|
||||
|
||||
__forceinline void SPR0chain()
|
||||
{
|
||||
_SPR0chain();
|
||||
CPU_INT(DMAC_FROM_SPR, _SPR0chain() / BIAS);
|
||||
spr0->qwc = 0;
|
||||
}
|
||||
|
||||
|
@ -102,6 +102,8 @@ void _SPR0interleave()
|
|||
SPR_LOG("SPR0 interleave size=%d, tqwc=%d, sqwc=%d, addr=%lx sadr=%lx",
|
||||
spr0->qwc, tqwc, sqwc, spr0->madr, spr0->sadr);
|
||||
|
||||
CPU_INT(DMAC_FROM_SPR, qwc / BIAS);
|
||||
|
||||
while (qwc > 0)
|
||||
{
|
||||
spr0->qwc = std::min(tqwc, qwc);
|
||||
|
@ -150,12 +152,11 @@ static __forceinline void _dmaSPR0()
|
|||
case CHAIN_MODE:
|
||||
{
|
||||
tDMA_TAG *ptag;
|
||||
bool done = FALSE;
|
||||
bool done = false;
|
||||
|
||||
if (spr0->qwc > 0)
|
||||
{
|
||||
SPR0chain();
|
||||
spr0finished = true;
|
||||
return;
|
||||
}
|
||||
// Destination Chain Mode
|
||||
|
@ -198,13 +199,6 @@ static __forceinline void _dmaSPR0()
|
|||
}
|
||||
|
||||
spr0finished = done;
|
||||
|
||||
if (!done)
|
||||
{
|
||||
ptag = (tDMA_TAG*)&psSu32(spr0->sadr); //Set memory pointer to SADR
|
||||
CPU_INT(DMAC_FROM_SPR, /*ptag[0].QWC / BIAS*/ 4 ); // the lower 16bits of the tag / BIAS);
|
||||
return;
|
||||
}
|
||||
SPR_LOG("spr0 dmaChain complete %8.8x_%8.8x size=%d, id=%d, addr=%lx spr=%lx",
|
||||
ptag[1]._u32, ptag[0]._u32, spr0->qwc, ptag->ID, spr0->madr);
|
||||
break;
|
||||
|
@ -220,37 +214,39 @@ static __forceinline void _dmaSPR0()
|
|||
|
||||
void SPRFROMinterrupt()
|
||||
{
|
||||
_dmaSPR0();
|
||||
|
||||
if(mfifotransferred != 0)
|
||||
|
||||
if (!spr0finished || spr0->qwc > 0)
|
||||
{
|
||||
switch (dmacRegs->ctrl.MFD)
|
||||
_dmaSPR0();
|
||||
|
||||
if(mfifotransferred != 0)
|
||||
{
|
||||
case MFD_VIF1: // Most common case.
|
||||
switch (dmacRegs->ctrl.MFD)
|
||||
{
|
||||
if ((spr0->madr & ~dmacRegs->rbsr.RMSK) != dmacRegs->rbor.ADDR) Console.WriteLn("VIF MFIFO Write outside MFIFO area");
|
||||
spr0->madr = dmacRegs->rbor.ADDR + (spr0->madr & dmacRegs->rbsr.RMSK);
|
||||
//Console.WriteLn("mfifoVIF1transfer %x madr %x, tadr %x", vif1ch->chcr._u32, vif1ch->madr, vif1ch->tadr);
|
||||
mfifoVIF1transfer(mfifotransferred);
|
||||
mfifotransferred = 0;
|
||||
if (vif1ch->chcr.STR) return;
|
||||
break;
|
||||
case MFD_VIF1: // Most common case.
|
||||
{
|
||||
if ((spr0->madr & ~dmacRegs->rbsr.RMSK) != dmacRegs->rbor.ADDR) Console.WriteLn("VIF MFIFO Write outside MFIFO area");
|
||||
spr0->madr = dmacRegs->rbor.ADDR + (spr0->madr & dmacRegs->rbsr.RMSK);
|
||||
//Console.WriteLn("mfifoVIF1transfer %x madr %x, tadr %x", vif1ch->chcr._u32, vif1ch->madr, vif1ch->tadr);
|
||||
mfifoVIF1transfer(mfifotransferred);
|
||||
mfifotransferred = 0;
|
||||
break;
|
||||
}
|
||||
case MFD_GIF:
|
||||
{
|
||||
if ((spr0->madr & ~dmacRegs->rbsr.RMSK) != dmacRegs->rbor.ADDR) Console.WriteLn("GIF MFIFO Write outside MFIFO area");
|
||||
spr0->madr = dmacRegs->rbor.ADDR + (spr0->madr & dmacRegs->rbsr.RMSK);
|
||||
//Console.WriteLn("mfifoGIFtransfer %x madr %x, tadr %x", gif->chcr._u32, gif->madr, gif->tadr);
|
||||
mfifoGIFtransfer(mfifotransferred);
|
||||
mfifotransferred = 0;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case MFD_GIF:
|
||||
{
|
||||
if ((spr0->madr & ~dmacRegs->rbsr.RMSK) != dmacRegs->rbor.ADDR) Console.WriteLn("GIF MFIFO Write outside MFIFO area");
|
||||
spr0->madr = dmacRegs->rbor.ADDR + (spr0->madr & dmacRegs->rbsr.RMSK);
|
||||
//Console.WriteLn("mfifoGIFtransfer %x madr %x, tadr %x", gif->chcr._u32, gif->madr, gif->tadr);
|
||||
mfifoGIFtransfer(mfifotransferred);
|
||||
mfifotransferred = 0;
|
||||
if (gif->chcr.STR) return;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!spr0finished) return;
|
||||
|
||||
|
||||
spr0->chcr.STR = false;
|
||||
|
@ -262,18 +258,23 @@ void dmaSPR0() // fromSPR
|
|||
SPR_LOG("dmaSPR0 chcr = %lx, madr = %lx, qwc = %lx, sadr = %lx",
|
||||
spr0->chcr._u32, spr0->madr, spr0->qwc, spr0->sadr);
|
||||
|
||||
if ((spr0->chcr.MOD == CHAIN_MODE) && spr0->qwc == 0)
|
||||
|
||||
spr0finished = false; //Init
|
||||
|
||||
if(spr0->chcr.MOD == CHAIN_MODE && spr0->qwc > 0)
|
||||
{
|
||||
tDMA_TAG *ptag;
|
||||
ptag = (tDMA_TAG*)&psSu32(spr0->sadr); //Set memory pointer to SADR
|
||||
CPU_INT(DMAC_FROM_SPR, /*ptag[0].QWC / BIAS*/ 4 );
|
||||
return;
|
||||
//DevCon.Warning(L"SPR0 QWC on Chain " + spr0->chcr.desc());
|
||||
if(((spr0->chcr.TAG >> 12) & 0x7) == 0x7)
|
||||
{
|
||||
spr0finished = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
spr0finished = false;
|
||||
}
|
||||
}
|
||||
if(spr0->chcr.MOD == CHAIN_MODE && spr0->qwc > 0) DevCon.Warning(L"SPR0 QWC on Chain " + spr0->chcr.desc());
|
||||
// COMPLETE HACK!!! For now at least.. FFX Videos dont rely on interrupts or reading DMA values
|
||||
// It merely assumes that the last one has finished then starts another one (broke with the DMA fix)
|
||||
// This "shouldn't" cause any problems as SPR is generally faster than the other DMAS anyway. (Refraction)
|
||||
CPU_INT(DMAC_FROM_SPR, /*spr0->qwc / BIAS*/ 4 );
|
||||
|
||||
SPRFROMinterrupt();
|
||||
}
|
||||
|
||||
__forceinline static void SPR1transfer(u32 *data, int size)
|
||||
|
@ -295,12 +296,12 @@ int _SPR1chain()
|
|||
SPR1transfer((u32*)pMem, spr1->qwc << 2);
|
||||
spr1->madr += spr1->qwc << 4;
|
||||
|
||||
return (spr1->qwc) * BIAS;
|
||||
return (spr1->qwc);
|
||||
}
|
||||
|
||||
__forceinline void SPR1chain()
|
||||
{
|
||||
_SPR1chain();
|
||||
CPU_INT(DMAC_TO_SPR, _SPR1chain() / BIAS);
|
||||
spr1->qwc = 0;
|
||||
}
|
||||
|
||||
|
@ -314,7 +315,7 @@ void _SPR1interleave()
|
|||
if (tqwc == 0) tqwc = qwc;
|
||||
SPR_LOG("SPR1 interleave size=%d, tqwc=%d, sqwc=%d, addr=%lx sadr=%lx",
|
||||
spr1->qwc, tqwc, sqwc, spr1->madr, spr1->sadr);
|
||||
|
||||
CPU_INT(DMAC_TO_SPR, qwc / BIAS);
|
||||
while (qwc > 0)
|
||||
{
|
||||
spr1->qwc = std::min(tqwc, qwc);
|
||||
|
@ -348,9 +349,9 @@ void _dmaSPR1() // toSPR work function
|
|||
|
||||
if (spr1->qwc > 0)
|
||||
{
|
||||
SPR_LOG("spr1 Normal or in Progress size=%d, addr=%lx taddr=%lx saddr=%lx", spr1->qwc, spr1->madr, spr1->tadr, spr1->sadr);
|
||||
// Transfer Dn_QWC from Dn_MADR to SPR1
|
||||
SPR1chain();
|
||||
spr1finished = true;
|
||||
return;
|
||||
}
|
||||
// Chain Mode
|
||||
|
@ -372,8 +373,8 @@ void _dmaSPR1() // toSPR work function
|
|||
SPR1transfer((u32*)ptag, 4); //Transfer Tag
|
||||
}
|
||||
|
||||
SPR_LOG("spr1 dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx",
|
||||
ptag[1]._u32, ptag[0]._u32, spr1->qwc, ptag->ID, spr1->madr);
|
||||
SPR_LOG("spr1 dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx taddr=%lx saddr=%lx",
|
||||
ptag[1]._u32, ptag[0]._u32, spr1->qwc, ptag->ID, spr1->madr, spr1->tadr, spr1->sadr);
|
||||
|
||||
done = (hwDmacSrcChain(spr1, ptag->ID));
|
||||
SPR1chain(); //Transfers the data set by the switch
|
||||
|
@ -387,11 +388,6 @@ void _dmaSPR1() // toSPR work function
|
|||
}
|
||||
|
||||
spr1finished = done;
|
||||
if (!done)
|
||||
{
|
||||
ptag = SPRdmaGetAddr(spr1->tadr, false); //Set memory pointer to TADR
|
||||
CPU_INT(DMAC_TO_SPR, /*(ptag[0].QWC / BIAS)*/ 4 );// the lower 16 bits of the tag / BIAS);
|
||||
}
|
||||
break;
|
||||
}
|
||||
//case INTERLEAVE_MODE:
|
||||
|
@ -409,26 +405,35 @@ void dmaSPR1() // toSPR
|
|||
" tadr = 0x%x, sadr = 0x%x",
|
||||
spr1->chcr._u32, spr1->madr, spr1->qwc,
|
||||
spr1->tadr, spr1->sadr);
|
||||
|
||||
if ((spr1->chcr.MOD == CHAIN_MODE) && (spr1->qwc == 0))
|
||||
|
||||
spr1finished = false; //Init
|
||||
|
||||
if(spr1->chcr.MOD == CHAIN_MODE && spr1->qwc > 0)
|
||||
{
|
||||
tDMA_TAG *ptag;
|
||||
ptag = SPRdmaGetAddr(spr1->tadr, false); //Set memory pointer to TADR
|
||||
CPU_INT(DMAC_TO_SPR, /*ptag[0].QWC / BIAS*/ 4 );
|
||||
return;
|
||||
//DevCon.Warning(L"SPR1 QWC on Chain " + spr1->chcr.desc());
|
||||
if(((spr1->chcr.TAG >> 12) & 0x7) == 0x7 || ((spr1->chcr.TAG >> 12) & 0x7) == 0x0)
|
||||
{
|
||||
spr1finished = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
spr1finished = false;
|
||||
}
|
||||
}
|
||||
if(spr1->chcr.MOD == CHAIN_MODE && spr1->qwc > 0) DevCon.Warning(L"SPR1 QWC on Chain " + spr1->chcr.desc());
|
||||
// COMPLETE HACK!!! For now at least.. FFX Videos dont rely on interrupts or reading DMA values
|
||||
// It merely assumes that the last one has finished then starts another one (broke with the DMA fix)
|
||||
// This "shouldn't" cause any problems as SPR is generally faster than the other DMAS anyway. (Refraction)
|
||||
CPU_INT(DMAC_TO_SPR, /*spr1->qwc / BIAS*/ 4 );
|
||||
|
||||
SPRTOinterrupt();
|
||||
}
|
||||
|
||||
void SPRTOinterrupt()
|
||||
{
|
||||
_dmaSPR1();
|
||||
if (!spr1finished) return;
|
||||
SPR_LOG("SPR1 Interrupt");
|
||||
if (!spr1finished || spr1->qwc > 0)
|
||||
{
|
||||
_dmaSPR1();
|
||||
return;
|
||||
}
|
||||
|
||||
SPR_LOG("SPR1 End");
|
||||
spr1->chcr.STR = false;
|
||||
hwDmacIrq(DMAC_TO_SPR);
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ static __forceinline bool WriteIOPtoFifo()
|
|||
hw_dma(9).madr += writeSize << 2;
|
||||
|
||||
// iop is 1/8th the clock rate of the EE and psxcycles is in words (not quadwords).
|
||||
sif0.iop.cycles += (writeSize >> 2) * BIAS; // fixme : should be >> 4
|
||||
sif0.iop.cycles += (writeSize >> 2)/* * BIAS*/; // fixme : should be >> 4
|
||||
sif0.iop.counter -= writeSize;
|
||||
|
||||
return true;
|
||||
|
@ -298,15 +298,21 @@ __forceinline void SIF0Dma()
|
|||
|
||||
if (sif0.iop.busy)
|
||||
{
|
||||
if(sif0.fifo.free() > 0) BusyCheck++;
|
||||
HandleIOPTransfer();
|
||||
if(sif0.fifo.free() > 0 || (sif0.iop.end == true && sif0.iop.counter == 0))
|
||||
{
|
||||
BusyCheck++;
|
||||
HandleIOPTransfer();
|
||||
}
|
||||
}
|
||||
if (sif0.ee.busy)
|
||||
{
|
||||
if(sif0.fifo.size >= 4) BusyCheck++;
|
||||
HandleEETransfer();
|
||||
if(sif0.fifo.size >= 4 || (sif0.ee.end == true && sif0dma->qwc == 0))
|
||||
{
|
||||
BusyCheck++;
|
||||
HandleEETransfer();
|
||||
}
|
||||
}
|
||||
} while (!done && BusyCheck > 0); // Substituting (sif0.ee.busy || sif0.iop.busy) breaks things.
|
||||
} while (/*!done && */BusyCheck > 0); // Substituting (sif0.ee.busy || sif0.iop.busy) breaks things.
|
||||
|
||||
Sif0End();
|
||||
}
|
||||
|
@ -332,17 +338,17 @@ __forceinline void dmaSIF0()
|
|||
SIF_LOG("warning, sif0.fifoReadPos != sif0.fifoWritePos");
|
||||
}
|
||||
|
||||
if(sif0dma->chcr.MOD == CHAIN_MODE && sif0dma->qwc > 0) DevCon.Warning(L"SIF0 QWC on Chain CHCR " + sif0dma->chcr.desc());
|
||||
//if(sif0dma->chcr.MOD == CHAIN_MODE && sif0dma->qwc > 0) DevCon.Warning(L"SIF0 QWC on Chain CHCR " + sif0dma->chcr.desc());
|
||||
psHu32(SBUS_F240) |= 0x2000;
|
||||
sif0.ee.busy = true;
|
||||
|
||||
if (sif0.iop.busy)
|
||||
{
|
||||
/*if (sif0.iop.busy)
|
||||
{*/
|
||||
XMMRegisters::Freeze();
|
||||
hwIntcIrq(INTC_SBUS);
|
||||
SIF0Dma();
|
||||
psHu32(SBUS_F240) &= ~0x20;
|
||||
psHu32(SBUS_F240) &= ~0x2000;
|
||||
XMMRegisters::Thaw();
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
|
|
@ -176,7 +176,7 @@ static __forceinline void EndEE()
|
|||
}
|
||||
|
||||
|
||||
CPU_INT(DMAC_SIF1, min((int)(sif1.ee.cycles*BIAS), 384));
|
||||
CPU_INT(DMAC_SIF1, /*min((int)(*/sif1.ee.cycles*BIAS/*), 384)*/);
|
||||
}
|
||||
|
||||
// Stop processing IOP, and signal an interrupt.
|
||||
|
@ -197,7 +197,7 @@ static __forceinline void EndIOP()
|
|||
sif1.iop.cycles = 1;
|
||||
}
|
||||
// iop is 1/8th the clock rate of the EE and psxcycles is in words (not quadwords)
|
||||
PSX_INT(IopEvt_SIF1, min((sif1.iop.cycles * 26), 1024));
|
||||
PSX_INT(IopEvt_SIF1, /*min((*/sif1.iop.cycles/* * 26*//*), 1024)*/);
|
||||
}
|
||||
|
||||
// Handle the EE transfer.
|
||||
|
@ -292,17 +292,23 @@ __forceinline void SIF1Dma()
|
|||
|
||||
if (sif1.ee.busy)
|
||||
{
|
||||
if(sif1.fifo.free() > 0) BusyCheck++;
|
||||
HandleEETransfer();
|
||||
if(sif1.fifo.free() > 0 || (sif1.ee.end == true && sif1dma->qwc == 0))
|
||||
{
|
||||
BusyCheck++;
|
||||
HandleEETransfer();
|
||||
}
|
||||
}
|
||||
|
||||
if (sif1.iop.busy)
|
||||
{
|
||||
if(sif1.fifo.size >= 4) BusyCheck++;
|
||||
HandleIOPTransfer();
|
||||
if(sif1.fifo.size >= 4 || (sif1.iop.end == true && sif1.iop.counter == 0))
|
||||
{
|
||||
BusyCheck++;
|
||||
HandleIOPTransfer();
|
||||
}
|
||||
}
|
||||
|
||||
} while (!done && BusyCheck > 0);
|
||||
} while (/*!done &&*/ BusyCheck > 0);
|
||||
|
||||
Sif1End();
|
||||
}
|
||||
|
@ -330,18 +336,18 @@ __forceinline void dmaSIF1()
|
|||
SIF_LOG("warning, sif1.fifoReadPos != sif1.fifoWritePos");
|
||||
}
|
||||
|
||||
if(sif1dma->chcr.MOD == CHAIN_MODE && sif1dma->qwc > 0) DevCon.Warning(L"SIF1 QWC on Chain CHCR " + sif1dma->chcr.desc());
|
||||
//if(sif1dma->chcr.MOD == CHAIN_MODE && sif1dma->qwc > 0) DevCon.Warning(L"SIF1 QWC on Chain CHCR " + sif1dma->chcr.desc());
|
||||
|
||||
psHu32(SBUS_F240) |= 0x4000;
|
||||
sif1.ee.busy = true;
|
||||
|
||||
if (sif1.iop.busy)
|
||||
{
|
||||
/*if (sif1.iop.busy)
|
||||
{*/
|
||||
XMMRegisters::Freeze();
|
||||
SIF1Dma();
|
||||
psHu32(SBUS_F240) &= ~0x40;
|
||||
psHu32(SBUS_F240) &= ~0x100;
|
||||
psHu32(SBUS_F240) &= ~0x4000;
|
||||
XMMRegisters::Thaw();
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
|
|
@ -2057,7 +2057,7 @@ void _vuXGKICK(VURegs * VU)
|
|||
|
||||
u8* data = ((u8*)VU->Mem + ((VU->VI[_Is_].US[0]*16) & 0x3fff));
|
||||
u32 size;
|
||||
size = GetMTGS().PrepDataPacket( GIF_PATH_1, data, (0x4000-((VU->VI[_Is_].US[0]*16) & 0x3fff)) >> 4);
|
||||
size = GetMTGS().PrepDataPacket( GIF_PATH_1, data, (0x4000-((VU->VI[_Is_].US[0]*16) & 0x3fff)) >> 4, false);
|
||||
u8* pmem = GetMTGS().GetDataPacketPtr();
|
||||
|
||||
if((size << 4) > (u32)(0x4000-((VU->VI[_Is_].US[0]*16) & 0x3fff)))
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
vifStruct vif0;
|
||||
vifStruct vif1;
|
||||
tGSTransferStatus GSTransferStatus((STOPPED_MODE<<4) | (STOPPED_MODE<<2) | STOPPED_MODE);
|
||||
tGSTransferStatus GSTransferStatus((STOPPED_MODE<<8) | (STOPPED_MODE<<4) | STOPPED_MODE);
|
||||
|
||||
void vif0Reset()
|
||||
{
|
||||
|
@ -140,8 +140,8 @@ _f void vif0FBRST(u32 value) {
|
|||
g_vifCycles = 0;
|
||||
|
||||
// loop necessary for spiderman
|
||||
vif0ch->chcr.STR = true;
|
||||
CPU_INT(DMAC_VIF0, 0); // Gets the timing right - Flatout
|
||||
//vif0ch->chcr.STR = true;
|
||||
if(vif0ch->chcr.STR == true) CPU_INT(DMAC_VIF0, 0); // Gets the timing right - Flatout
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -153,21 +153,28 @@ _f void vif1FBRST(u32 value) {
|
|||
if (FBRST(value).RST) // Reset Vif.
|
||||
{
|
||||
memzero(vif1);
|
||||
cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's
|
||||
vif1ch->qwc = 0; //?
|
||||
//cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's
|
||||
vif1ch->qwc -= min((int)vif1ch->qwc, 16); //?
|
||||
psHu64(VIF1_FIFO) = 0;
|
||||
psHu64(VIF1_FIFO + 8) = 0;
|
||||
vif1.done = false;
|
||||
//vif1.done = false;
|
||||
|
||||
if(vif1Regs->mskpath3)
|
||||
|
||||
//DevCon.Warning("VIF FBRST Reset MSK = %x", vif1Regs->mskpath3);
|
||||
if(vif1Regs->mskpath3 == 1 && GSTransferStatus.PTH3 == STOPPED_MODE && gif->chcr.STR == true)
|
||||
{
|
||||
vif1Regs->mskpath3 = 0;
|
||||
gifRegs->stat.IMT = false;
|
||||
if (gif->chcr.STR) CPU_INT(DMAC_GIF, 4);
|
||||
//DevCon.Warning("VIF Path3 Resume on FBRST MSK = %x", vif1Regs->mskpath3);
|
||||
gsInterrupt();
|
||||
vif1Regs->mskpath3 = false;
|
||||
gifRegs->stat.M3P = 0;
|
||||
}
|
||||
|
||||
vif1Regs->mskpath3 = false;
|
||||
gifRegs->stat.M3P = 0;
|
||||
vif1Regs->err.reset();
|
||||
vif1.inprogress = 0;
|
||||
vif1.cmd = 0;
|
||||
vif1.vifstalled = false;
|
||||
vif1Regs->stat.FQC = 0;
|
||||
vif1Regs->stat.clear_flags(VIF1_STAT_FDR | VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS | VIF1_STAT_VPS);
|
||||
}
|
||||
|
@ -217,18 +224,18 @@ _f void vif1FBRST(u32 value) {
|
|||
{
|
||||
case MFD_VIF1:
|
||||
//Console.WriteLn("MFIFO Stall");
|
||||
CPU_INT(10, 0);
|
||||
if(vif1ch->chcr.STR == true) CPU_INT(10, 0);
|
||||
break;
|
||||
|
||||
case NO_MFD:
|
||||
case MFD_RESERVED:
|
||||
case MFD_GIF: // Wonder if this should be with VIF?
|
||||
// Gets the timing right - Flatout
|
||||
CPU_INT(DMAC_VIF1, 0);
|
||||
if(vif1ch->chcr.STR == true) CPU_INT(DMAC_VIF1, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
vif1ch->chcr.STR = true;
|
||||
//vif1ch->chcr.STR = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -227,6 +227,7 @@ extern VIFregisters *vifRegs;
|
|||
extern void dmaVIF0();
|
||||
extern void dmaVIF1();
|
||||
extern void mfifoVIF1transfer(int qwc);
|
||||
extern bool VIF0transfer(u32 *data, int size, bool istag);
|
||||
extern bool VIF1transfer(u32 *data, int size, bool istag);
|
||||
extern bool VIF0transfer(u32 *data, int size);
|
||||
extern bool VIF1transfer(u32 *data, int size);
|
||||
extern void vifMFIFOInterrupt();
|
||||
extern bool CheckPath2GIF(int channel);
|
||||
|
|
|
@ -23,10 +23,31 @@
|
|||
// because its vif stalling not the EE core...
|
||||
__forceinline void vif0FLUSH()
|
||||
{
|
||||
if(g_packetsizeonvu > vif0.vifpacketsize && g_vu0Cycles > 0)
|
||||
{
|
||||
//DevCon.Warning("Adding on same packet");
|
||||
if( ((g_packetsizeonvu - vif0.vifpacketsize) >> 1) > g_vu0Cycles)
|
||||
g_vu0Cycles -= (g_packetsizeonvu - vif0.vifpacketsize) >> 1;
|
||||
else g_vu0Cycles = 0;
|
||||
}
|
||||
if(g_vu0Cycles > 0)
|
||||
{
|
||||
//DevCon.Warning("Adding %x cycles to VIF0", g_vu1Cycles * BIAS);
|
||||
g_vifCycles += g_vu0Cycles;
|
||||
g_vu0Cycles = 0;
|
||||
}
|
||||
g_vu0Cycles = 0;
|
||||
if (!(VU0.VI[REG_VPU_STAT].UL & 1)) return;
|
||||
if(VU0.flags & VUFLAG_MFLAGSET)
|
||||
{
|
||||
vif0.vifstalled = true;
|
||||
return;
|
||||
}
|
||||
int _cycles = VU0.cycle;
|
||||
vu0Finish();
|
||||
//DevCon.Warning("VIF0 adding %x cycles", (VU0.cycle - _cycles) * BIAS);
|
||||
g_vifCycles += (VU0.cycle - _cycles) * BIAS;
|
||||
return;
|
||||
}
|
||||
|
||||
bool _VIF0chain()
|
||||
|
@ -52,9 +73,9 @@ bool _VIF0chain()
|
|||
vif0ch->qwc, vif0ch->madr, vif0ch->tadr);
|
||||
|
||||
if (vif0.vifstalled)
|
||||
return VIF0transfer(pMem + vif0.irqoffset, vif0ch->qwc * 4 - vif0.irqoffset, false);
|
||||
return VIF0transfer(pMem + vif0.irqoffset, vif0ch->qwc * 4 - vif0.irqoffset);
|
||||
else
|
||||
return VIF0transfer(pMem, vif0ch->qwc * 4, false);
|
||||
return VIF0transfer(pMem, vif0ch->qwc * 4);
|
||||
}
|
||||
|
||||
__forceinline void vif0SetupTransfer()
|
||||
|
@ -89,9 +110,9 @@ __forceinline void vif0SetupTransfer()
|
|||
bool ret;
|
||||
|
||||
if (vif0.vifstalled)
|
||||
ret = VIF0transfer((u32*)ptag + (2 + vif0.irqoffset), 2 - vif0.irqoffset, true); //Transfer Tag on stall
|
||||
ret = VIF0transfer((u32*)ptag + (2 + vif0.irqoffset), 2 - vif0.irqoffset); //Transfer Tag on stall
|
||||
else
|
||||
ret = VIF0transfer((u32*)ptag + 2, 2, true); //Transfer Tag
|
||||
ret = VIF0transfer((u32*)ptag + 2, 2); //Transfer Tag
|
||||
|
||||
if ((ret == false) && vif0.irqoffset < 2)
|
||||
{
|
||||
|
@ -124,6 +145,15 @@ __forceinline void vif0Interrupt()
|
|||
|
||||
if (!(vif0ch->chcr.STR)) Console.WriteLn("vif0 running when CHCR == %x", vif0ch->chcr._u32);
|
||||
|
||||
if (vif0.cmd)
|
||||
{
|
||||
if(vif0.done == true && vif0ch->qwc == 0) vif0Regs->stat.VPS = VPS_WAITING;
|
||||
}
|
||||
else
|
||||
{
|
||||
vif0Regs->stat.VPS = VPS_IDLE;
|
||||
}
|
||||
|
||||
if (vif0.irq && vif0.tag.size == 0)
|
||||
{
|
||||
vif0Regs->stat.INT = true;
|
||||
|
@ -134,25 +164,15 @@ __forceinline void vif0Interrupt()
|
|||
vif0Regs->stat.FQC = 0;
|
||||
|
||||
// One game doesn't like vif stalling at end, can't remember what. Spiderman isn't keen on it tho
|
||||
vif0ch->chcr.STR = false;
|
||||
return;
|
||||
}
|
||||
else if ((vif0ch->qwc > 0) || (vif0.irqoffset > 0))
|
||||
{
|
||||
if (vif0.stallontag)
|
||||
vif0SetupTransfer();
|
||||
else
|
||||
_VIF0chain();//CPU_INT(DMAC_STALL_SIS, vif0ch->qwc * BIAS);
|
||||
//vif0ch->chcr.STR = false;
|
||||
if(vif0ch->qwc > 0 || !vif0.done) return;
|
||||
}
|
||||
}
|
||||
|
||||
if (vif0.inprogress & 0x1)
|
||||
{
|
||||
_VIF0chain();
|
||||
// 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);
|
||||
CPU_INT(DMAC_VIF0, g_vifCycles);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -182,7 +202,6 @@ __forceinline void vif0Interrupt()
|
|||
if (vif0.cmd != 0) Console.WriteLn("vif0.cmd still set %x tag size %x", vif0.cmd, vif0.tag.size);
|
||||
#endif
|
||||
|
||||
vif0Regs->stat.VPS = VPS_IDLE; //Vif goes idle as the stall happened between commands;
|
||||
vif0ch->chcr.STR = false;
|
||||
g_vifCycles = 0;
|
||||
hwDmacIrq(DMAC_VIF0);
|
||||
|
@ -197,24 +216,35 @@ void dmaVIF0()
|
|||
vif0ch->tadr, vif0ch->asr0, vif0ch->asr1);
|
||||
|
||||
g_vifCycles = 0;
|
||||
g_vu0Cycles = 0;
|
||||
if(vif0.irqoffset != 0 && vif0.vifstalled == true) DevCon.Warning("Offset on VIF0 start!");
|
||||
vif0.irqoffset = 0;
|
||||
vif0.vifstalled = false;
|
||||
vif0.inprogress = 0;
|
||||
vif0.done = false;
|
||||
|
||||
if ((vif0ch->chcr.MOD == NORMAL_MODE) || vif0ch->qwc > 0) // Normal Mode
|
||||
{
|
||||
vif0.dmamode = VIF_NORMAL_TO_MEM_MODE;
|
||||
if(vif0ch->chcr.MOD == CHAIN_MODE && vif0ch->qwc > 0) DevCon.Warning(L"VIF0 QWC on Chain CHCR " + vif0ch->chcr.desc());
|
||||
|
||||
if(vif0ch->chcr.MOD == CHAIN_MODE && vif0ch->qwc > 0)
|
||||
{
|
||||
vif0.dmamode = VIF_CHAIN_MODE;
|
||||
//DevCon.Warning(L"VIF0 QWC on Chain CHCR " + vif0ch->chcr.desc());
|
||||
vif0.inprogress |= 0x1;
|
||||
if(((vif0ch->chcr.TAG >> 12) & 0x7) == 0x0 || ((vif0ch->chcr.TAG >> 12) & 0x7) == 0x7)
|
||||
{
|
||||
vif0.done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vif0.dmamode = VIF_CHAIN_MODE;
|
||||
}
|
||||
|
||||
if (vif0.dmamode != VIF_NORMAL_FROM_MEM_MODE)
|
||||
vif0Regs->stat.FQC = 0x8;
|
||||
else
|
||||
vif0Regs->stat.FQC = min((u16)0x8, vif0ch->qwc);
|
||||
vif0Regs->stat.FQC = min((u16)0x8, vif0ch->qwc);
|
||||
|
||||
// Chain Mode
|
||||
vif0.done = false;
|
||||
vif0Interrupt();
|
||||
}
|
||||
|
|
|
@ -21,12 +21,38 @@
|
|||
#include "VUmicro.h"
|
||||
#include "newVif.h"
|
||||
|
||||
|
||||
__forceinline void vif1FLUSH()
|
||||
{
|
||||
if (!(VU0.VI[REG_VPU_STAT].UL & 0x100)) return;
|
||||
int _cycles = VU1.cycle;
|
||||
vu1Finish();
|
||||
g_vifCycles += (VU1.cycle - _cycles) * BIAS;
|
||||
if(g_packetsizeonvu > vif1.vifpacketsize && g_vu1Cycles > 0)
|
||||
{
|
||||
//DevCon.Warning("Adding on same packet");
|
||||
if( ((g_packetsizeonvu - vif1.vifpacketsize) >> 1) > g_vu1Cycles)
|
||||
g_vu1Cycles -= (g_packetsizeonvu - vif1.vifpacketsize) >> 1;
|
||||
else g_vu1Cycles = 0;
|
||||
}
|
||||
if(g_vu1Cycles > 0)
|
||||
{
|
||||
//DevCon.Warning("Adding %x cycles to VIF1", g_vu1Cycles * BIAS);
|
||||
g_vifCycles += g_vu1Cycles;
|
||||
g_vu1Cycles = 0;
|
||||
|
||||
}
|
||||
g_vu1Cycles = 0;//else DevCon.Warning("VIF1 Different Packet, how can i work this out :/");
|
||||
if (VU0.VI[REG_VPU_STAT].UL & 0x100)
|
||||
{
|
||||
int _cycles = VU1.cycle;
|
||||
vu1Finish();
|
||||
//DevCon.Warning("VIF1 adding %x cycles", (VU1.cycle - _cycles) * BIAS);
|
||||
g_vifCycles += (VU1.cycle - _cycles) * BIAS;
|
||||
}
|
||||
if(gifRegs->stat.P1Q == true && (vif1.cmd & 0x7f) != 0x14 && (vif1.cmd & 0x7f) != 0x17)
|
||||
{
|
||||
vif1.vifstalled = true;
|
||||
vif1Regs->stat.VGW = true;
|
||||
vif1.GifWaitState = 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void vif1TransferToMemory()
|
||||
|
@ -128,6 +154,7 @@ bool _VIF1chain()
|
|||
if (vif1ch->qwc == 0)
|
||||
{
|
||||
vif1.inprogress = 0;
|
||||
vif1.irqoffset = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -152,9 +179,9 @@ bool _VIF1chain()
|
|||
vif1ch->qwc, vif1ch->madr, vif1ch->tadr);
|
||||
|
||||
if (vif1.vifstalled)
|
||||
return VIF1transfer(pMem + vif1.irqoffset, vif1ch->qwc * 4 - vif1.irqoffset, false);
|
||||
return VIF1transfer(pMem + vif1.irqoffset, vif1ch->qwc * 4 - vif1.irqoffset);
|
||||
else
|
||||
return VIF1transfer(pMem, vif1ch->qwc * 4, false);
|
||||
return VIF1transfer(pMem, vif1ch->qwc * 4);
|
||||
}
|
||||
|
||||
__forceinline void vif1SetupTransfer()
|
||||
|
@ -201,15 +228,16 @@ __forceinline void vif1SetupTransfer()
|
|||
bool ret;
|
||||
|
||||
if (vif1.vifstalled)
|
||||
ret = VIF1transfer((u32*)ptag + (2 + vif1.irqoffset), 2 - vif1.irqoffset, true); //Transfer Tag on stall
|
||||
ret = VIF1transfer((u32*)ptag + (2 + vif1.irqoffset), 2 - vif1.irqoffset); //Transfer Tag on stall
|
||||
else
|
||||
ret = VIF1transfer((u32*)ptag + 2, 2, true); //Transfer Tag
|
||||
|
||||
ret = VIF1transfer((u32*)ptag + 2, 2); //Transfer Tag
|
||||
|
||||
if ((ret == false) && vif1.irqoffset < 2)
|
||||
{
|
||||
vif1.inprogress = 0; //Better clear this so it has to do it again (Jak 1)
|
||||
return; //There has been an error or an interrupt
|
||||
}
|
||||
return; //IRQ set by VIFTransfer
|
||||
|
||||
} //else vif1.vifstalled = false;
|
||||
}
|
||||
|
||||
vif1.irqoffset = 0;
|
||||
|
@ -228,12 +256,92 @@ __forceinline void vif1SetupTransfer()
|
|||
}
|
||||
}
|
||||
|
||||
bool CheckPath2GIF(int channel)
|
||||
{
|
||||
if ((vif1Regs->stat.VGW))
|
||||
{
|
||||
if( vif1.GifWaitState == 0 ) //DIRECT/HL Check
|
||||
{
|
||||
if(GSTransferStatus.PTH3 < IDLE_MODE || gifRegs->stat.P1Q == true)
|
||||
{
|
||||
if(gifRegs->stat.IMT && GSTransferStatus.PTH3 <= IMAGE_MODE && (vif1.cmd & 0x7f) == 0x50 && gifRegs->stat.P1Q == false)
|
||||
{
|
||||
vif1Regs->stat.VGW = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//DevCon.Warning("VIF1-0 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs->stat.P1Q, gifRegs->stat.P2Q, gifRegs->stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
|
||||
CPU_INT(channel, 8);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vif1Regs->stat.VGW = false;
|
||||
}
|
||||
}
|
||||
else if( vif1.GifWaitState == 1 ) // Else we're flushing path3 :), but of course waiting for the microprogram to finish
|
||||
{
|
||||
if(gifRegs->stat.P1Q == true)
|
||||
{
|
||||
//DevCon.Warning("VIF1-1 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs->stat.P1Q, gifRegs->stat.P2Q, gifRegs->stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
|
||||
CPU_INT(channel, 8);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GSTransferStatus.PTH3 < PENDINGSTOP_MODE)
|
||||
{
|
||||
//DevCon.Warning("VIF1-11 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs->stat.P1Q, gifRegs->stat.P2Q, gifRegs->stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
|
||||
//DevCon.Warning("PTH3 %x P1Q %x P3Q %x IP3 %x", GSTransferStatus.PTH3, gifRegs->stat.P1Q, gifRegs->stat.P3Q, gifRegs->stat.IP3 );
|
||||
CPU_INT(channel, 8);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
vif1Regs->stat.VGW = false;
|
||||
}
|
||||
}
|
||||
else if( vif1.GifWaitState == 3 ) // Else we're flushing path3 :), but of course waiting for the microprogram to finish
|
||||
{
|
||||
if (gifRegs->ctrl.PSE)
|
||||
{
|
||||
//DevCon.Warning("VIF1-1 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs->stat.P1Q, gifRegs->stat.P2Q, gifRegs->stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
|
||||
CPU_INT(channel, 8);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
vif1Regs->stat.VGW = false;
|
||||
}
|
||||
}
|
||||
else //Normal Flush
|
||||
{
|
||||
if(gifRegs->stat.P1Q == true)
|
||||
{
|
||||
//DevCon.Warning("VIF1-2 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs->stat.P1Q, gifRegs->stat.P2Q, gifRegs->stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
|
||||
CPU_INT(channel, 8);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
vif1Regs->stat.VGW = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
__forceinline void vif1Interrupt()
|
||||
{
|
||||
VIF_LOG("vif1Interrupt: %8.8x", cpuRegs.cycle);
|
||||
|
||||
g_vifCycles = 0;
|
||||
|
||||
if (schedulepath3msk & 0x10)
|
||||
{
|
||||
Vif1MskPath3();
|
||||
CPU_INT(DMAC_VIF1, 8);
|
||||
return;
|
||||
}
|
||||
//Some games (Fahrenheit being one) start vif first, let it loop through blankness while it sets MFIFO mode, so we need to check it here.
|
||||
if (dmacRegs->ctrl.MFD == MFD_VIF1) // VIF MFIFO
|
||||
{
|
||||
|
@ -245,31 +353,31 @@ __forceinline void vif1Interrupt()
|
|||
return;
|
||||
}
|
||||
|
||||
if(vif1ch->chcr.DIR && CheckPath2GIF(DMAC_VIF1) == false) return;
|
||||
//We need to check the direction, if it is downloading from the GS, we handle that seperately (KH2 for testing)
|
||||
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)
|
||||
|
||||
if(GSTransferStatus.PTH2 == PENDINGSTOP_MODE)
|
||||
{
|
||||
gifRegs->stat.APATH = GIF_APATH_IDLE;
|
||||
GSTransferStatus.PTH2 = STOPPED_MODE;
|
||||
/*gifRegs->stat.APATH = GIF_APATH_IDLE;
|
||||
if(gifRegs->stat.DIR == 0)gifRegs->stat.OPH = false;*/
|
||||
}
|
||||
|
||||
if (schedulepath3msk & 0x10) Vif1MskPath3();
|
||||
|
||||
if ((vif1Regs->stat.VGW))
|
||||
{
|
||||
if (GSTransferStatus.PTH3 < STOPPED_MODE || GSTransferStatus.PTH1 != STOPPED_MODE)
|
||||
{
|
||||
CPU_INT(DMAC_VIF1, 4);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
vif1Regs->stat.VGW = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!(vif1ch->chcr.STR)) Console.WriteLn("Vif1 running when CHCR == %x", vif1ch->chcr._u32);
|
||||
|
||||
if (vif1.cmd)
|
||||
{
|
||||
if(vif1.done == true && vif1ch->qwc == 0) vif1Regs->stat.VPS = VPS_WAITING;
|
||||
}
|
||||
else
|
||||
{
|
||||
vif1Regs->stat.VPS = VPS_IDLE;
|
||||
}
|
||||
|
||||
if (vif1.irq && vif1.tag.size == 0)
|
||||
{
|
||||
vif1Regs->stat.INT = true;
|
||||
|
@ -279,16 +387,9 @@ __forceinline void vif1Interrupt()
|
|||
{
|
||||
//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;
|
||||
return;
|
||||
}
|
||||
else if ((vif1ch->qwc > 0) || (vif1.irqoffset > 0))
|
||||
{
|
||||
if (vif1.stallontag)
|
||||
vif1SetupTransfer();
|
||||
else
|
||||
_VIF1chain();//CPU_INT(DMAC_STALL_SIS, vif1ch->qwc * BIAS);
|
||||
//NFSHPS stalls when the whole packet has gone across (it stalls int he last 32bit cmd)
|
||||
//In this case VIF will end
|
||||
if(vif1ch->qwc > 0 || !vif1.done) return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -330,13 +431,15 @@ __forceinline void vif1Interrupt()
|
|||
if (vif1.cmd != 0) Console.WriteLn("vif1.cmd still set %x tag size %x", vif1.cmd, vif1.tag.size);
|
||||
#endif
|
||||
|
||||
vif1Regs->stat.VPS = VPS_IDLE; //Vif goes idle as the stall happened between commands;
|
||||
|
||||
if((vif1ch->chcr.DIR == VIF_NORMAL_TO_MEM_MODE) && vif1.GSLastDownloadSize <= 16)
|
||||
{ //Reverse fifo has finished and nothing is left, so lets clear the outputting flag
|
||||
gifRegs->stat.OPH = false;
|
||||
}
|
||||
vif1ch->chcr.STR = false;
|
||||
vif1.vifstalled = false;
|
||||
g_vifCycles = 0;
|
||||
g_vu1Cycles = 0;
|
||||
VIF_LOG("VIF1 End");
|
||||
hwDmacIrq(DMAC_VIF1);
|
||||
|
||||
|
@ -350,7 +453,12 @@ void dmaVIF1()
|
|||
vif1ch->tadr, vif1ch->asr0, vif1ch->asr1);
|
||||
|
||||
vif1.done = false;
|
||||
|
||||
if(vif1.irqoffset != 0 && vif1.vifstalled == true) DevCon.Warning("Offset on VIF1 start!");
|
||||
vif1.irqoffset = 0;
|
||||
vif1.vifstalled = false;
|
||||
g_vifCycles = 0;
|
||||
g_vu1Cycles = 0;
|
||||
vif1.inprogress = 0;
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
|
@ -371,7 +479,16 @@ void dmaVIF1()
|
|||
else
|
||||
vif1.dmamode = VIF_NORMAL_TO_MEM_MODE;
|
||||
|
||||
if(vif1ch->chcr.MOD == CHAIN_MODE && vif1ch->qwc > 0) DevCon.Warning(L"VIF1 QWC on Chain CHCR " + vif1ch->chcr.desc());
|
||||
if(vif1ch->chcr.MOD == CHAIN_MODE && vif1ch->qwc > 0)
|
||||
{
|
||||
vif1.dmamode = VIF_CHAIN_MODE;
|
||||
//DevCon.Warning(L"VIF1 QWC on Chain CHCR " + vif1ch->chcr.desc());
|
||||
vif1.inprogress |= 0x1;
|
||||
if(((vif1ch->chcr.TAG >> 12) & 0x7) == 0x0 || ((vif1ch->chcr.TAG >> 12) & 0x7) == 0x7)
|
||||
{
|
||||
vif1.done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -22,11 +22,19 @@
|
|||
VIFregisters *vifRegs;
|
||||
vifStruct *vif;
|
||||
u16 vifqwc = 0;
|
||||
int g_vifCycles = 0;
|
||||
u32 g_vifCycles = 0;
|
||||
u32 g_vu0Cycles = 0;
|
||||
u32 g_vu1Cycles = 0;
|
||||
u32 g_packetsizeonvu = 0;
|
||||
|
||||
__aligned16 VifMaskTypes g_vifmask;
|
||||
|
||||
extern int g_vifCycles;
|
||||
extern u32 g_vifCycles;
|
||||
|
||||
static u32 qwctag(u32 mask)
|
||||
{
|
||||
return (dmacRegs->rbor.ADDR + (mask & dmacRegs->rbsr.RMSK));
|
||||
}
|
||||
|
||||
static __forceinline bool mfifoVIF1rbTransfer()
|
||||
{
|
||||
|
@ -48,10 +56,12 @@ static __forceinline bool mfifoVIF1rbTransfer()
|
|||
if (src == NULL) return false;
|
||||
|
||||
if (vif1.vifstalled)
|
||||
ret = VIF1transfer(src + vif1.irqoffset, s1 - vif1.irqoffset, false);
|
||||
ret = VIF1transfer(src + vif1.irqoffset, s1 - vif1.irqoffset);
|
||||
else
|
||||
ret = VIF1transfer(src, s1, false);
|
||||
ret = VIF1transfer(src, s1);
|
||||
|
||||
vif1ch->madr = qwctag(vif1ch->madr);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
/* and second copy 's2' bytes from 'maddr' to '&data[s1]' */
|
||||
|
@ -59,8 +69,10 @@ static __forceinline bool mfifoVIF1rbTransfer()
|
|||
|
||||
src = (u32*)PSM(maddr);
|
||||
if (src == NULL) return false;
|
||||
VIF1transfer(src, ((mfifoqwc << 2) - s1), false);
|
||||
VIF1transfer(src, ((mfifoqwc << 2) - s1));
|
||||
}
|
||||
vif1ch->madr = qwctag(vif1ch->madr);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -71,9 +83,12 @@ static __forceinline bool mfifoVIF1rbTransfer()
|
|||
if (src == NULL) return false;
|
||||
|
||||
if (vif1.vifstalled)
|
||||
ret = VIF1transfer(src + vif1.irqoffset, mfifoqwc * 4 - vif1.irqoffset, false);
|
||||
ret = VIF1transfer(src + vif1.irqoffset, mfifoqwc * 4 - vif1.irqoffset);
|
||||
else
|
||||
ret = VIF1transfer(src, mfifoqwc << 2, false);
|
||||
ret = VIF1transfer(src, mfifoqwc << 2);
|
||||
|
||||
vif1ch->madr = qwctag(vif1ch->madr);
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -83,7 +98,7 @@ static __forceinline bool mfifo_VIF1chain()
|
|||
bool ret;
|
||||
|
||||
/* Is QWC = 0? if so there is nothing to transfer */
|
||||
if ((vif1ch->qwc == 0) && (!vif1.vifstalled))
|
||||
if ((vif1ch->qwc == 0))
|
||||
{
|
||||
vif1.inprogress &= ~1;
|
||||
return true;
|
||||
|
@ -95,6 +110,7 @@ static __forceinline bool mfifo_VIF1chain()
|
|||
u16 startqwc = vif1ch->qwc;
|
||||
ret = mfifoVIF1rbTransfer();
|
||||
vifqwc -= startqwc - vif1ch->qwc;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -104,17 +120,14 @@ static __forceinline bool mfifo_VIF1chain()
|
|||
if (pMem == NULL) return false;
|
||||
|
||||
if (vif1.vifstalled)
|
||||
ret = VIF1transfer((u32*)pMem + vif1.irqoffset, vif1ch->qwc * 4 - vif1.irqoffset, false);
|
||||
ret = VIF1transfer((u32*)pMem + vif1.irqoffset, vif1ch->qwc * 4 - vif1.irqoffset);
|
||||
else
|
||||
ret = VIF1transfer((u32*)pMem, vif1ch->qwc << 2, false);
|
||||
ret = VIF1transfer((u32*)pMem, vif1ch->qwc << 2);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32 qwctag(u32 mask)
|
||||
{
|
||||
return (dmacRegs->rbor.ADDR + (mask & dmacRegs->rbsr.RMSK));
|
||||
}
|
||||
|
||||
|
||||
void mfifoVIF1transfer(int qwc)
|
||||
{
|
||||
|
@ -148,19 +161,20 @@ void mfifoVIF1transfer(int qwc)
|
|||
{
|
||||
bool ret;
|
||||
|
||||
if (vif1.stallontag)
|
||||
ret = VIF1transfer((u32*)ptag + (2 + vif1.irqoffset), 2 - vif1.irqoffset, true); //Transfer Tag on Stall
|
||||
if (vif1.vifstalled)
|
||||
ret = VIF1transfer((u32*)ptag + (2 + vif1.irqoffset), 2 - vif1.irqoffset); //Transfer Tag on Stall
|
||||
else
|
||||
ret = VIF1transfer((u32*)ptag + 2, 2, true); //Transfer Tag
|
||||
ret = VIF1transfer((u32*)ptag + 2, 2); //Transfer Tag
|
||||
|
||||
if (!(ret))
|
||||
if ((ret == false) && vif1.irqoffset < 2)
|
||||
{
|
||||
VIF_LOG("MFIFO Stall on tag");
|
||||
vif1.stallontag = true;
|
||||
return; //IRQ set by VIFTransfer
|
||||
}
|
||||
|
||||
} //else vif1.vifstalled = false;
|
||||
}
|
||||
|
||||
vif1.irqoffset = 0;
|
||||
|
||||
vif1ch->unsafeTransfer(ptag);
|
||||
|
||||
vif1ch->madr = ptag[1]._u32;
|
||||
|
@ -224,29 +238,25 @@ void vifMFIFOInterrupt()
|
|||
|
||||
if (schedulepath3msk & 0x10) Vif1MskPath3();
|
||||
|
||||
if(gifRegs->stat.APATH == GIF_APATH2 && (vif1.cmd & 0x70) != 0x50)
|
||||
if(vif1ch->chcr.DIR && CheckPath2GIF(10) == false) return;
|
||||
//We need to check the direction, if it is downloading from the GS, we handle that seperately (KH2 for testing)
|
||||
|
||||
//Simulated GS transfer time done, clear the flags
|
||||
|
||||
if(GSTransferStatus.PTH2 == PENDINGSTOP_MODE)
|
||||
{
|
||||
gifRegs->stat.APATH = GIF_APATH_IDLE;
|
||||
GSTransferStatus.PTH2 = STOPPED_MODE;
|
||||
/*gifRegs->stat.APATH = GIF_APATH_IDLE;
|
||||
if(gifRegs->stat.DIR == 0)gifRegs->stat.OPH = false;*/
|
||||
}
|
||||
|
||||
if ((vif1Regs->stat.VGW))
|
||||
if (vif1.cmd)
|
||||
{
|
||||
if (GSTransferStatus.PTH3 < STOPPED_MODE || GSTransferStatus.PTH1 != STOPPED_MODE)
|
||||
{
|
||||
CPU_INT(10, 4);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
vif1Regs->stat.VGW = false;
|
||||
}
|
||||
|
||||
if(vif1.done == true && vif1ch->qwc == 0) vif1Regs->stat.VPS = VPS_WAITING;
|
||||
}
|
||||
|
||||
if ((spr0->chcr.STR) && (spr0->qwc == 0))
|
||||
else
|
||||
{
|
||||
spr0->chcr.STR = false;
|
||||
hwDmacIrq(DMAC_FROM_SPR);
|
||||
vif1Regs->stat.VPS = VPS_IDLE;
|
||||
}
|
||||
|
||||
if (vif1.irq && vif1.tag.size == 0)
|
||||
|
@ -257,9 +267,9 @@ void vifMFIFOInterrupt()
|
|||
|
||||
if (vif1Regs->stat.test(VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS))
|
||||
{
|
||||
vif1Regs->stat.FQC = 0; // FQC=0
|
||||
vif1ch->chcr.STR = false;
|
||||
return;
|
||||
/*vif1Regs->stat.FQC = 0; // FQC=0
|
||||
vif1ch->chcr.STR = false;*/
|
||||
if(vif1ch->qwc > 0 || !vif1.done) return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -302,6 +312,7 @@ void vifMFIFOInterrupt()
|
|||
hwDmacIrq(DMAC_MFIFO_EMPTY);
|
||||
}*/
|
||||
|
||||
vif1.vifstalled = false;
|
||||
vif1.done = 1;
|
||||
g_vifCycles = 0;
|
||||
vif1ch->chcr.STR = false;
|
||||
|
|
|
@ -39,7 +39,10 @@ static _f void vifFlush(int idx) {
|
|||
|
||||
static _f void vuExecMicro(int idx, u32 addr) {
|
||||
VURegs* VU = nVif[idx].VU;
|
||||
vifFlush(idx);
|
||||
int startcycles = 0;
|
||||
//vifFlush(idx);
|
||||
|
||||
//if(vifX.vifstalled == true) return;
|
||||
|
||||
if (VU->vifRegs->itops > (idx ? 0x3ffu : 0xffu)) {
|
||||
Console.WriteLn("VIF%d ITOP overrun! %x", idx, VU->vifRegs->itops);
|
||||
|
@ -65,8 +68,16 @@ static _f void vuExecMicro(int idx, u32 addr) {
|
|||
}
|
||||
}
|
||||
|
||||
if(!idx)startcycles = VU0.cycle;
|
||||
else startcycles = VU1.cycle;
|
||||
|
||||
if (!idx) vu0ExecMicro(addr);
|
||||
else vu1ExecMicro(addr);
|
||||
|
||||
if(!idx) { g_vu0Cycles += (VU0.cycle-startcycles) * BIAS; g_packetsizeonvu = vif0.vifpacketsize; }
|
||||
else { g_vu1Cycles += (VU1.cycle-startcycles) * BIAS; g_packetsizeonvu = vif1.vifpacketsize; }
|
||||
//DevCon.Warning("Ran VU%x, VU0 Cycles %x, VU1 Cycles %x", idx, g_vu0Cycles, g_vu1Cycles);
|
||||
vifX.vifstalled = true;
|
||||
}
|
||||
|
||||
u8 schedulepath3msk = 0;
|
||||
|
@ -74,17 +85,20 @@ u8 schedulepath3msk = 0;
|
|||
void Vif1MskPath3() {
|
||||
|
||||
vif1Regs->mskpath3 = schedulepath3msk & 0x1;
|
||||
//Console.WriteLn("VIF MSKPATH3 %x", vif1Regs->mskpath3);
|
||||
//Console.WriteLn("VIF MSKPATH3 %x gif str %x path3 status %x", vif1Regs->mskpath3, gif->chcr.STR, GSTransferStatus.PTH3);
|
||||
gifRegs->stat.M3P = vif1Regs->mskpath3;
|
||||
if (!vif1Regs->mskpath3) {
|
||||
//Let the Gif know it can transfer again (making sure any vif stall isnt unset prematurely)
|
||||
if(gif->chcr.STR == true)
|
||||
{
|
||||
GSTransferStatus.PTH3 = 3;
|
||||
CPU_INT(DMAC_GIF, 4);
|
||||
}
|
||||
|
||||
}
|
||||
if (!vif1Regs->mskpath3)
|
||||
{
|
||||
//if(GSTransferStatus.PTH3 > TRANSFER_MODE && gif->chcr.STR) GSTransferStatus.PTH3 = TRANSFER_MODE;
|
||||
//DevCon.Warning("Mask off");
|
||||
if(GSTransferStatus.PTH3 >= PENDINGSTOP_MODE) GSTransferStatus.PTH3 = IDLE_MODE;
|
||||
if(gifRegs->stat.P3Q)
|
||||
{
|
||||
gsInterrupt();//gsInterrupt();
|
||||
}
|
||||
|
||||
} else if(!gif->chcr.STR && GSTransferStatus.PTH3 == IDLE_MODE) GSTransferStatus.PTH3 = STOPPED_MODE;//else DevCon.Warning("Mask on");
|
||||
|
||||
schedulepath3msk = 0;
|
||||
}
|
||||
|
@ -105,24 +119,46 @@ template<int idx> _f int _vifCode_Direct(int pass, u8* data, bool isDirectHL) {
|
|||
vif1Only();
|
||||
int vifImm = (u16)vif1Regs->code;
|
||||
vif1.tag.size = vifImm ? (vifImm*4) : (65536*4);
|
||||
return 1;
|
||||
vif1.vifstalled = true;
|
||||
gifRegs->stat.P2Q = true;
|
||||
if (gifRegs->stat.PSE) // temporarily stop
|
||||
{
|
||||
Console.WriteLn("Gif dma temp paused? VIF DIRECT");
|
||||
vif1.GifWaitState = 3;
|
||||
vif1Regs->stat.VGW = true;
|
||||
}
|
||||
//Should cause this to split here to try and time PATH3 right.
|
||||
return 0;
|
||||
}
|
||||
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 (GSTransferStatus.PTH3 < STOPPED_MODE || GSTransferStatus.PTH1 != STOPPED_MODE)
|
||||
|
||||
if (GSTransferStatus.PTH3 < IDLE_MODE || gifRegs->stat.P1Q == true)
|
||||
{
|
||||
/*if(!isDirectHL) DevCon.WriteLn("Direct: Waiting for Path3 to finish!");
|
||||
else DevCon.WriteLn("DirectHL: Waiting for Path3 to finish!");*/
|
||||
//VIF_LOG("Mask %x, GIF STR %x, PTH1 %x, PTH2 %x, PTH3 %x", vif1Regs->mskpath3, gif->chcr.STR, GSTransferStatus.PTH1, GSTransferStatus.PTH2, GSTransferStatus.PTH3);
|
||||
vif1Regs->stat.VGW = true; // PATH3 is in image mode, so wait for end of transfer
|
||||
vif1.vifstalled = true;
|
||||
if(gifRegs->stat.APATH == GIF_APATH2 || ((GSTransferStatus.PTH3 <= IMAGE_MODE && gifRegs->stat.IMT && (vif1.cmd & 0x7f) == 0x50)) && gifRegs->stat.P1Q == false)
|
||||
{
|
||||
//Do nothing, allow it
|
||||
vif1Regs->stat.VGW = false;
|
||||
//if(gifRegs->stat.APATH != GIF_APATH2)DevCon.Warning("Continue DIRECT/HL %x P3 %x APATH %x P1Q %x", vif1.cmd, GSTransferStatus.PTH3, gifRegs->stat.APATH, gifRegs->stat.P1Q);
|
||||
}
|
||||
else
|
||||
{
|
||||
//DevCon.Warning("Stall DIRECT/HL %x P3 %x APATH %x P1Q %x", vif1.cmd, GSTransferStatus.PTH3, gifRegs->stat.APATH, gifRegs->stat.P1Q);
|
||||
vif1Regs->stat.VGW = true; // PATH3 is in image mode (DIRECTHL), or busy (BOTH no IMT)
|
||||
vif1.GifWaitState = 0;
|
||||
vif1.vifstalled = true;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (gifRegs->stat.PSE) // temporarily stop
|
||||
{
|
||||
Console.WriteLn("Gif dma temp paused? VIF DIRECT");
|
||||
vif1.GifWaitState = 3;
|
||||
vif1Regs->stat.VGW = true;
|
||||
return 0;
|
||||
}
|
||||
//}
|
||||
|
||||
|
||||
gifRegs->stat.clear_flags(GIF_STAT_P2Q);
|
||||
|
||||
Registers::Freeze();
|
||||
|
@ -131,31 +167,72 @@ template<int idx> _f int _vifCode_Direct(int pass, u8* data, bool isDirectHL) {
|
|||
u32 size = ret << 2;
|
||||
|
||||
gifRegs->stat.APATH = GIF_APATH2; //Flag is cleared in vif1interrupt to simulate it being in progress.
|
||||
|
||||
if (ret == v.vif->tag.size) { // Full Transfer
|
||||
if (v.bSize) { // Last transfer was partial
|
||||
memcpy_fast(&v.buffer[v.bSize], data, size);
|
||||
v.bSize += size;
|
||||
data = v.buffer;
|
||||
size = v.bSize;
|
||||
}
|
||||
|
||||
//In the original code we were saving this data, it seems if it does happen, its just blank, so we ignore it.
|
||||
|
||||
if (!size) { DevCon.WriteLn("Path2: No Data Transfer?"); }
|
||||
const uint count = GetMTGS().PrepDataPacket(GIF_PATH_2, data, size >> 4);
|
||||
memcpy_fast(GetMTGS().GetDataPacketPtr(), data, count << 4);
|
||||
GetMTGS().SendDataPacket();
|
||||
vif1.tag.size = 0;
|
||||
vif1.cmd = 0;
|
||||
v.bSize = 0;
|
||||
}
|
||||
else { // Partial Transfer
|
||||
//DevCon.WriteLn("DirectHL: Partial Transfer [%d]", size);
|
||||
memcpy_fast(&v.buffer[v.bSize], data, size);
|
||||
v.bSize += size;
|
||||
vif1.tag.size -= ret;
|
||||
}
|
||||
|
||||
|
||||
Registers::Thaw();
|
||||
return ret;
|
||||
if(vif1.vifpacketsize < 4 && v.bSize < 16)
|
||||
{
|
||||
nVifStruct& v = nVif[idx];
|
||||
|
||||
memcpy(&v.buffer[v.bPtr], data, vif1.vifpacketsize << 2);
|
||||
v.bSize += vif1.vifpacketsize << 2;
|
||||
v.bPtr += vif1.vifpacketsize << 2;
|
||||
vif1.tag.size -= vif1.vifpacketsize;
|
||||
Registers::Thaw();
|
||||
if(vif1.tag.size == 0)
|
||||
{
|
||||
DevCon.Warning("Missaligned packet on DIRECT end!");
|
||||
vif1.cmd = 0;
|
||||
}
|
||||
return vif1.vifpacketsize;
|
||||
}
|
||||
else
|
||||
{
|
||||
nVifStruct& v = nVif[idx];
|
||||
if(v.bSize)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if(v.bSize < 16)
|
||||
{
|
||||
if(((16 - v.bSize) >> 2) > vif1.vifpacketsize) DevCon.Warning("Not Enough Data!");
|
||||
ret = (16 - v.bSize) >> 2;
|
||||
memcpy(&v.buffer[v.bPtr], data, ret << 2);
|
||||
vif1.tag.size -= ret;
|
||||
v.bSize = 0;
|
||||
v.bPtr = 0;
|
||||
}
|
||||
const uint count = GetMTGS().PrepDataPacket(GIF_PATH_2, v.buffer, 1, false);
|
||||
memcpy_fast(GetMTGS().GetDataPacketPtr(), v.buffer, count << 4);
|
||||
GetMTGS().SendDataPacket();
|
||||
|
||||
if(vif1.tag.size == 0)
|
||||
{
|
||||
vif1.cmd = 0;
|
||||
}
|
||||
vif1.vifstalled = true;
|
||||
Registers::Thaw();
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint count = GetMTGS().PrepDataPacket(GIF_PATH_2, data, size >> 4, false);
|
||||
memcpy_fast(GetMTGS().GetDataPacketPtr(), data, count << 4);
|
||||
GetMTGS().SendDataPacket();
|
||||
vif1.tag.size -= count << 2;
|
||||
if(vif1.tag.size == 0)
|
||||
{
|
||||
vif1.cmd = 0;
|
||||
}
|
||||
vif1.vifstalled = true;
|
||||
Registers::Thaw();
|
||||
return count << 2;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -173,7 +250,7 @@ vifOp(vifCode_DirectHL) {
|
|||
// ToDo: FixMe
|
||||
vifOp(vifCode_Flush) {
|
||||
vif1Only();
|
||||
pass1 { vifFlush(idx); vifX.cmd = 0; }
|
||||
pass1 { vifFlush(idx); vifX.cmd = 0; }
|
||||
pass3 { DevCon.WriteLn("vifCode_Flush"); }
|
||||
return 0;
|
||||
}
|
||||
|
@ -182,16 +259,22 @@ vifOp(vifCode_Flush) {
|
|||
vifOp(vifCode_FlushA) {
|
||||
vif1Only();
|
||||
pass1 {
|
||||
vifFlush(idx);
|
||||
// Gif is already transferring so wait for it.
|
||||
if (GSTransferStatus.PTH3 < STOPPED_MODE) {
|
||||
if (gifRegs->stat.P1Q == true || GSTransferStatus.PTH3 < PENDINGSTOP_MODE) {
|
||||
//DevCon.Warning("VIF FlushA Wait MSK = %x", vif1Regs->mskpath3);
|
||||
//
|
||||
|
||||
//DevCon.WriteLn("FlushA path3 Wait! PTH3 MD %x STR %x", GSTransferStatus.PTH3, gif->chcr.STR);
|
||||
vif1Regs->stat.VGW = true;
|
||||
vif1.GifWaitState = 1;
|
||||
vifX.vifstalled = true;
|
||||
}
|
||||
vifFlush(idx);
|
||||
vifX.cmd = 0;
|
||||
} // else DevCon.WriteLn("FlushA path3 no Wait! PTH3 MD %x STR %x", GSTransferStatus.PTH3, gif->chcr.STR);
|
||||
|
||||
|
||||
}
|
||||
pass3 { DevCon.WriteLn("vifCode_FlushA"); }
|
||||
vifX.cmd = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -234,10 +317,10 @@ vifOp(vifCode_MPG) {
|
|||
int vifNum = (u8)(vifXRegs->code >> 16);
|
||||
vifX.tag.addr = (u16)(vifXRegs->code << 3) & (idx ? 0x3fff : 0xfff);
|
||||
vifX.tag.size = vifNum ? (vifNum*2) : 512;
|
||||
//vifFlush(idx);
|
||||
return 1;
|
||||
}
|
||||
pass2 {
|
||||
vifFlush(idx);
|
||||
if (vifX.vifpacketsize < vifX.tag.size) { // Partial Transfer
|
||||
if((vifX.tag.addr + vifX.vifpacketsize) > (idx ? 0x4000 : 0x1000)) {
|
||||
DevCon.Warning("Vif%d MPG Split Overflow", idx);
|
||||
|
@ -263,19 +346,19 @@ vifOp(vifCode_MPG) {
|
|||
}
|
||||
|
||||
vifOp(vifCode_MSCAL) {
|
||||
pass1 { vuExecMicro(idx, (u16)(vifXRegs->code) << 3); vifX.cmd = 0; }
|
||||
pass1 { vifFlush(idx); vuExecMicro(idx, (u16)(vifXRegs->code) << 3); vifX.cmd = 0;}
|
||||
pass3 { DevCon.WriteLn("vifCode_MSCAL"); }
|
||||
return 0;
|
||||
}
|
||||
|
||||
vifOp(vifCode_MSCALF) {
|
||||
pass1 { vuExecMicro(idx, (u16)(vifXRegs->code) << 3); vifX.cmd = 0; }
|
||||
pass1 { vifFlush(idx); vuExecMicro(idx, (u16)(vifXRegs->code) << 3); vifX.cmd = 0; }
|
||||
pass3 { DevCon.WriteLn("vifCode_MSCALF"); }
|
||||
return 0;
|
||||
}
|
||||
|
||||
vifOp(vifCode_MSCNT) {
|
||||
pass1 { vuExecMicro(idx, -1); vifX.cmd = 0; }
|
||||
pass1 { vifFlush(idx); vuExecMicro(idx, -1); vifX.cmd = 0; }
|
||||
pass3 { DevCon.WriteLn("vifCode_MSCNT"); }
|
||||
return 0;
|
||||
}
|
||||
|
@ -284,7 +367,7 @@ vifOp(vifCode_MSCNT) {
|
|||
vifOp(vifCode_MskPath3) {
|
||||
vif1Only();
|
||||
pass1 {
|
||||
if (vif1ch->chcr.STR) {
|
||||
if (vif1ch->chcr.STR && vifX.lastcmd != 0x13) {
|
||||
schedulepath3msk = 0x10 | ((vif1Regs->code >> 15) & 0x1);
|
||||
vif1.vifstalled = true;
|
||||
}
|
||||
|
|
|
@ -75,7 +75,9 @@ struct vifStruct {
|
|||
u32 savedtag; // need this for backwards compat with save states
|
||||
u32 vifpacketsize;
|
||||
u8 inprogress;
|
||||
u32 lastcmd;
|
||||
u8 dmamode;
|
||||
u8 GifWaitState; // 0 = General PATH checking, 1 = Flush path 3, 2 == Wait for VU1
|
||||
};
|
||||
|
||||
extern vifStruct* vif;
|
||||
|
@ -110,8 +112,10 @@ enum VifModes
|
|||
static const unsigned int VIF0intc = 4;
|
||||
static const unsigned int VIF1intc = 5;
|
||||
|
||||
extern int g_vifCycles;
|
||||
|
||||
extern u32 g_vifCycles;
|
||||
extern u32 g_vu0Cycles;
|
||||
extern u32 g_vu1Cycles;
|
||||
extern u32 g_packetsizeonvu;
|
||||
extern void vif0FLUSH();
|
||||
extern void vif1FLUSH();
|
||||
|
||||
|
|
|
@ -69,6 +69,7 @@ _vifT void vifTransferLoop(u32* &data) {
|
|||
while (pSize > 0 && !vifX.vifstalled) {
|
||||
|
||||
if(!vifX.cmd) { // Get new VifCode
|
||||
vifX.lastcmd = (vifXRegs->code >> 24) & 0x7f;
|
||||
vifXRegs->code = data[0];
|
||||
vifX.cmd = data[0] >> 24;
|
||||
iBit = data[0] >> 31;
|
||||
|
@ -84,8 +85,7 @@ _vifT void vifTransferLoop(u32* &data) {
|
|||
pSize -= ret;
|
||||
if (analyzeIbit<idx>(data, iBit)) break;
|
||||
}
|
||||
if (vifX.cmd) vifXRegs->stat.VPS = VPS_WAITING;
|
||||
else vifXRegs->stat.VPS = VPS_IDLE;
|
||||
|
||||
if (pSize) vifX.vifstalled = true;
|
||||
}
|
||||
|
||||
|
@ -97,14 +97,30 @@ _vifT _f bool vifTransfer(u32 *data, int size) {
|
|||
vifX.vifstalled = false;
|
||||
vifX.stallontag = false;
|
||||
vifX.vifpacketsize = size;
|
||||
|
||||
g_packetsizeonvu = size;
|
||||
vifTransferLoop<idx>(data);
|
||||
|
||||
|
||||
transferred += size - vifX.vifpacketsize;
|
||||
g_vifCycles +=(transferred >> 2) * BIAS; /* guessing */
|
||||
|
||||
g_vifCycles +=((transferred * BIAS) >> 2) ; /* guessing */
|
||||
|
||||
if(!idx && g_vu0Cycles > 0)
|
||||
{
|
||||
if(g_vifCycles < g_vu0Cycles) g_vu0Cycles -= g_vifCycles;
|
||||
else if(g_vifCycles >= g_vu0Cycles)g_vu0Cycles = 0;
|
||||
}
|
||||
else if(idx && g_vu1Cycles > 0)
|
||||
{
|
||||
if(g_vifCycles < g_vu1Cycles) g_vu1Cycles -= g_vifCycles;
|
||||
else if(g_vifCycles >= g_vu1Cycles)g_vu1Cycles = 0;
|
||||
}
|
||||
|
||||
|
||||
vifX.irqoffset = transferred % 4; // cannot lose the offset
|
||||
|
||||
transferred = transferred >> 2;
|
||||
|
||||
vifXch->madr +=(transferred << 4);
|
||||
vifXch->qwc -= transferred;
|
||||
|
||||
|
@ -125,9 +141,9 @@ _vifT _f bool vifTransfer(u32 *data, int size) {
|
|||
return !vifX.vifstalled;
|
||||
}
|
||||
|
||||
bool VIF0transfer(u32 *data, int size, bool istag) {
|
||||
bool VIF0transfer(u32 *data, int size) {
|
||||
return vifTransfer<0>(data, size);
|
||||
}
|
||||
bool VIF1transfer(u32 *data, int size, bool istag) {
|
||||
bool VIF1transfer(u32 *data, int size) {
|
||||
return vifTransfer<1>(data, size);
|
||||
}
|
||||
|
|
|
@ -306,7 +306,8 @@ _vifT void vifUnpackSetup(u32 *data) {
|
|||
return; // Skipping write and 0 write-cycles, so do nothing!
|
||||
}
|
||||
|
||||
if (!idx) vif0FLUSH(); // Only VU0?
|
||||
|
||||
//if (!idx) vif0FLUSH(); // Only VU0?
|
||||
|
||||
vifX.usn = (vifXRegs->code >> 14) & 0x01;
|
||||
int vifNum = (vifXRegs->code >> 16) & 0xff;
|
||||
|
@ -330,6 +331,8 @@ _vifT void vifUnpackSetup(u32 *data) {
|
|||
if (idx && ((addr>>15)&1)) addr += vif1Regs->tops;
|
||||
vifX.tag.addr = (addr<<4) & (idx ? 0x3ff0 : 0xff0);
|
||||
|
||||
VIF_LOG("Unpack VIF%x, QWC %x tagsize %x", idx, vifNum, vif0.tag.size);
|
||||
|
||||
vifX.cl = 0;
|
||||
vifX.tag.cmd = vifX.cmd;
|
||||
vifXRegs->offset = 0;
|
||||
|
|
|
@ -100,7 +100,7 @@ struct GIFPath
|
|||
bool StepReg();
|
||||
u8 GetReg();
|
||||
|
||||
int ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size);
|
||||
int ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size, bool TestOnly);
|
||||
};
|
||||
|
||||
typedef void (__fastcall *GIFRegHandler)(const u32* data);
|
||||
|
@ -280,9 +280,13 @@ static __forceinline void gsHandler(const u8* pMem)
|
|||
const int reg = pMem[8];
|
||||
|
||||
if (reg == 0x50)
|
||||
{
|
||||
vif1.BITBLTBUF._u64 = *(u64*)pMem;
|
||||
}
|
||||
else if (reg == 0x52)
|
||||
{
|
||||
vif1.TRXREG._u64 = *(u64*)pMem;
|
||||
}
|
||||
else if (reg == 0x53)
|
||||
{
|
||||
// local -> host
|
||||
|
@ -316,7 +320,6 @@ static __forceinline void gsHandler(const u8* pMem)
|
|||
// qwords, rounded down; any extra bits are lost
|
||||
// games must take care to ensure transfer rectangles are exact multiples of a qword
|
||||
vif1.GSLastDownloadSize = vif1.TRXREG.RRW * vif1.TRXREG.RRH * bpp >> 7;
|
||||
VIF_LOG("GS Download size %x", vif1.GSLastDownloadSize);
|
||||
gifRegs->stat.OPH = true;
|
||||
}
|
||||
}
|
||||
|
@ -341,10 +344,9 @@ static __forceinline void gsHandler(const u8* pMem)
|
|||
// Parameters:
|
||||
// size (path1) - difference between the end of VU memory and pMem.
|
||||
// size (path2/3) - max size of incoming data stream, in qwc (simd128)
|
||||
__forceinline int GIFPath::ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size)
|
||||
__forceinline int GIFPath::ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size, bool TestOnly)
|
||||
{
|
||||
const u8* vuMemEnd = pMem + (size<<4); // End of VU1 Mem
|
||||
if (pathidx==GIF_PATH_1) size = 0x400; // VU1 mem size
|
||||
u32 startSize = size; // Start Size
|
||||
|
||||
while (size > 0) {
|
||||
|
@ -352,27 +354,36 @@ __forceinline int GIFPath::ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size)
|
|||
|
||||
SetTag(pMem);
|
||||
incTag(16, 1);
|
||||
|
||||
//if (pathidx == GIF_PATH_3) {
|
||||
switch(pathidx)
|
||||
|
||||
|
||||
if(nloop > 0)
|
||||
{
|
||||
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;
|
||||
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;
|
||||
}
|
||||
if(gifRegs->stat.DIR == 0)gifRegs->stat.OPH = true;
|
||||
gifRegs->stat.APATH = pathidx + 1;
|
||||
}
|
||||
//}
|
||||
if(pathidx == GIF_PATH_3) break;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
gifRegs->stat.APATH = pathidx + 1;
|
||||
if(gifRegs->stat.DIR == 0)gifRegs->stat.OPH = true;
|
||||
switch(tag.FLG) {
|
||||
case GIF_FLG_PACKED:
|
||||
GIF_LOG("Packed Mode");
|
||||
|
@ -409,7 +420,7 @@ __forceinline int GIFPath::ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size)
|
|||
}
|
||||
if(pathidx == GIF_PATH_1)
|
||||
{
|
||||
if(nloop > 0 && size == 0 && !tag.EOP) //Need to check all of this, some cases VU will send info (like the BIOS) but be incomplete
|
||||
if(size == 0 && (!tag.EOP || nloop > 0)) //Need to check all of this, some cases VU will send info (like the BIOS) but be incomplete
|
||||
{
|
||||
switch(tag.FLG)
|
||||
{
|
||||
|
@ -433,39 +444,45 @@ __forceinline int GIFPath::ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (tag.EOP && !nloop) {
|
||||
if (pathidx != GIF_PATH_2) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tag.EOP && !nloop) break;
|
||||
}
|
||||
/*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 (tag.EOP && !nloop) {
|
||||
//Console.Warning("Finishing path %x", pathidx);
|
||||
if (tag.EOP && nloop <= 16) {
|
||||
if(pathidx == 2 && nloop > 0)
|
||||
{
|
||||
if(GSTransferStatus.PTH3 != IDLE_MODE) GSTransferStatus.PTH3 = PENDINGSTOP_MODE;
|
||||
}
|
||||
else if(nloop == 0)
|
||||
{
|
||||
if(gifRegs->stat.DIR == 0)gifRegs->stat.OPH = false;
|
||||
gifRegs->stat.APATH = GIF_APATH_IDLE;
|
||||
switch(pathidx)
|
||||
{
|
||||
case GIF_PATH_1:
|
||||
GSTransferStatus.PTH1 = STOPPED_MODE;
|
||||
break;
|
||||
case GIF_PATH_2:
|
||||
GSTransferStatus.PTH2 = STOPPED_MODE;
|
||||
GSTransferStatus.PTH2 = PENDINGSTOP_MODE;
|
||||
break;
|
||||
case GIF_PATH_3:
|
||||
GSTransferStatus.PTH3 = STOPPED_MODE;
|
||||
if(GSTransferStatus.PTH3 != IDLE_MODE) GSTransferStatus.PTH3 = STOPPED_MODE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(nloop <= 16 && GSTransferStatus.PTH3 == IMAGE_MODE && pathidx == 2)
|
||||
{
|
||||
GSTransferStatus.PTH3 = PENDINGIMAGE_MODE;
|
||||
}
|
||||
|
||||
if (pathidx == GIF_PATH_3 && gif->chcr.STR) { //Make sure we are really doing a DMA and not using FIFO
|
||||
//GIF_LOG("Path3 end EOP %x NLOOP %x Status %x", tag.EOP, nloop, GSTransferStatus.PTH3);
|
||||
gif->madr += size * 16;
|
||||
gif->qwc -= size;
|
||||
} else if (pathidx == GIF_PATH_2 && !nloop) { //Path2 is odd, but always provides the correct size
|
||||
GSTransferStatus.PTH2 = STOPPED_MODE;
|
||||
}
|
||||
|
||||
return size;
|
||||
|
@ -476,7 +493,7 @@ __forceinline int GIFPath::ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size)
|
|||
// runs potentially several frames behind.
|
||||
// Parameters:
|
||||
// size - max size of incoming data stream, in qwc (simd128)
|
||||
__forceinline int GIFPath_ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size)
|
||||
__forceinline int GIFPath_ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size, bool TestOnly)
|
||||
{
|
||||
#ifdef PCSX2_GSRING_SAMPLING_STATS
|
||||
static uptr profStartPtr = 0;
|
||||
|
@ -492,7 +509,7 @@ __forceinline int GIFPath_ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size)
|
|||
}
|
||||
#endif
|
||||
|
||||
int retSize = s_gifPath[pathidx].ParseTag(pathidx, pMem, size);
|
||||
int retSize = s_gifPath[pathidx].ParseTag(pathidx, pMem, size, TestOnly);
|
||||
|
||||
#ifdef PCSX2_GSRING_SAMPLING_STATS
|
||||
__asm
|
||||
|
@ -515,6 +532,8 @@ void GIFPath_Reset()
|
|||
__forceinline void GIFPath_Clear( GIF_PATH pathidx )
|
||||
{
|
||||
memzero(s_gifPath.path[pathidx]);
|
||||
GSTransferStatus._u32 &= ~(0xf << (pathidx * 4));
|
||||
GSTransferStatus._u32 |= (0x5 << (pathidx * 4));
|
||||
if( GSgifSoftReset == NULL ) return;
|
||||
GetMTGS().SendSimplePacket( GS_RINGTYPE_SOFTRESET, (1<<pathidx), 0, 0 );
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "Gif.h"
|
||||
//------------------------------------------------------------------
|
||||
// Micro VU Micromode Lower instructions
|
||||
//------------------------------------------------------------------
|
||||
|
@ -1106,22 +1107,53 @@ void __fastcall mVU_XGKICK_(u32 addr) {
|
|||
addr &= 0x3ff;
|
||||
u8* data = microVU1.regs->Mem + (addr*16);
|
||||
u32 diff = 0x400 - addr;
|
||||
u32 size = GetMTGS().PrepDataPacket(GIF_PATH_1, data, diff);
|
||||
u8* pDest = GetMTGS().GetDataPacketPtr();
|
||||
u32 size;
|
||||
u8* pDest;
|
||||
|
||||
if (size > diff) {
|
||||
// fixme: one of these days the following *16's will get cleaned up when we introduce
|
||||
// a special qwc/simd16 optimized version of memcpy_aligned. :)
|
||||
//DevCon.Status("XGkick Wrap!");
|
||||
memcpy_aligned(pDest, microVU1.regs->Mem + (addr*16), diff*16);
|
||||
size -= diff;
|
||||
pDest += diff*16;
|
||||
memcpy_aligned(pDest, microVU1.regs->Mem, size*16);
|
||||
if(gifRegs->stat.APATH == GIF_APATH_IDLE)
|
||||
{
|
||||
size = GetMTGS().PrepDataPacket(GIF_PATH_1, data, diff, false);
|
||||
pDest = GetMTGS().GetDataPacketPtr();
|
||||
if (size > diff) {
|
||||
// fixme: one of these days the following *16's will get cleaned up when we introduce
|
||||
// a special qwc/simd16 optimized version of memcpy_aligned. :)
|
||||
//DevCon.Status("XGkick Wrap!");
|
||||
memcpy_aligned(pDest, microVU1.regs->Mem + (addr*16), diff*16);
|
||||
size -= diff;
|
||||
pDest += diff*16;
|
||||
memcpy_aligned(pDest, microVU1.regs->Mem, size*16);
|
||||
}
|
||||
else {
|
||||
memcpy_aligned(pDest, microVU1.regs->Mem + (addr*16), size*16);
|
||||
}
|
||||
GetMTGS().SendDataPacket();
|
||||
}
|
||||
else {
|
||||
memcpy_aligned(pDest, microVU1.regs->Mem + (addr*16), size*16);
|
||||
else
|
||||
{
|
||||
//DevCon.Warning("GIF APATH busy %x Holding for later W %x, R %x", gifRegs->stat.APATH, Path1WritePos, Path1ReadPos);
|
||||
size = GetMTGS().PrepDataPacket(GIF_PATH_1, data, diff, true);
|
||||
pDest = &Path1Buffer[Path1WritePos*16];
|
||||
|
||||
|
||||
|
||||
//DevCon.Warning("Storing size %x PATH 1", size);
|
||||
if (size > diff) {
|
||||
// fixme: one of these days the following *16's will get cleaned up when we introduce
|
||||
// a special qwc/simd16 optimized version of memcpy_aligned. :)
|
||||
//DevCon.Status("XGkick Wrap!");
|
||||
memcpy_aligned(pDest, microVU1.regs->Mem + (addr*16), diff*16);
|
||||
Path1WritePos += size;
|
||||
size -= diff;
|
||||
pDest += diff*16;
|
||||
memcpy_aligned(pDest, microVU1.regs->Mem, size*16);
|
||||
}
|
||||
else {
|
||||
memcpy_aligned(pDest, microVU1.regs->Mem + (addr*16), size*16);
|
||||
Path1WritePos += size;
|
||||
}
|
||||
if(!gifRegs->stat.P1Q) CPU_INT(28, 16);
|
||||
gifRegs->stat.P1Q = true;
|
||||
}
|
||||
GetMTGS().SendDataPacket();
|
||||
}
|
||||
|
||||
_f void mVU_XGKICK_DELAY(mV, bool memVI) {
|
||||
|
|
|
@ -87,6 +87,7 @@ struct nVifStruct {
|
|||
u8* vuMemEnd; // End of VU Memory
|
||||
u32 vuMemLimit; // Use for fast AND
|
||||
u32 bSize; // Size of 'buffer'
|
||||
u32 bPtr;
|
||||
u8 buffer[_1mb]; // Buffer for partial transfers
|
||||
u8* recPtr; // Cur Pos to recompile to
|
||||
u8* recEnd; // 'Safe' End of Rec Cache
|
||||
|
|
|
@ -173,7 +173,7 @@ void VifUnpackSSE_Dynarec::CompileRoutine() {
|
|||
if (++vCL == blockSize) vCL = 0;
|
||||
}
|
||||
else if (isFill) {
|
||||
DevCon.WriteLn("filling mode!");
|
||||
//DevCon.WriteLn("filling mode!");
|
||||
VifUnpackSSE_Dynarec fill( VifUnpackSSE_Dynarec::FillingWrite( *this ) );
|
||||
fill.xUnpack(upkNum);
|
||||
fill.xMovDest();
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "sVU_Micro.h"
|
||||
#include "sVU_Debug.h"
|
||||
#include "sVU_zerorec.h"
|
||||
#include "Gif.h"
|
||||
//------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
@ -1971,27 +1972,57 @@ void recVUMI_XTOP( VURegs *VU, int info )
|
|||
//------------------------------------------------------------------
|
||||
void __fastcall VU1XGKICK_MTGSTransfer(u32 *pMem, u32 addr)
|
||||
{
|
||||
addr &= 0x3fff;
|
||||
u8* data = VU1.Mem + (addr);
|
||||
u32 diff = 0x400 - (addr / 16);
|
||||
u32 size;
|
||||
u8* data = ((u8*)pMem + (addr&0x3fff));
|
||||
u8* pDest;
|
||||
|
||||
size = GetMTGS().PrepDataPacket(GIF_PATH_1, data, (0x4000-(addr&0x3fff)) / 16);
|
||||
jASSUME( size > 0 );
|
||||
|
||||
u8* pmem = GetMTGS().GetDataPacketPtr();
|
||||
|
||||
if((size << 4) > (0x4000-(addr&0x3fff)))
|
||||
if(gifRegs->stat.APATH == GIF_APATH_IDLE)
|
||||
{
|
||||
//DevCon.Warning("addr + Size = 0x%x, transferring %x then doing %x", (addr&0x3fff) + (size << 4), (0x4000-(addr&0x3fff)) >> 4, size - ((0x4000-(addr&0x3fff)) >> 4));
|
||||
memcpy_aligned(pmem, (u8*)pMem+addr, 0x4000-(addr&0x3fff));
|
||||
size -= (0x4000-(addr&0x3fff)) >> 4;
|
||||
//DevCon.Warning("Size left %x", size);
|
||||
pmem += 0x4000-(addr&0x3fff);
|
||||
memcpy_aligned(pmem, (u8*)pMem, size<<4);
|
||||
size = GetMTGS().PrepDataPacket(GIF_PATH_1, data, diff, false);
|
||||
pDest = GetMTGS().GetDataPacketPtr();
|
||||
if (size > diff) {
|
||||
// fixme: one of these days the following *16's will get cleaned up when we introduce
|
||||
// a special qwc/simd16 optimized version of memcpy_aligned. :)
|
||||
|
||||
memcpy_aligned(pDest, VU1.Mem + addr, diff*16);
|
||||
size -= diff;
|
||||
pDest += diff*16;
|
||||
memcpy_aligned(pDest, VU1.Mem, size*16);
|
||||
}
|
||||
else {
|
||||
memcpy_aligned(pDest, VU1.Mem + addr, size*16);
|
||||
}
|
||||
GetMTGS().SendDataPacket();
|
||||
}
|
||||
else {
|
||||
memcpy_aligned(pmem, (u8*)pMem+addr, size<<4);
|
||||
else
|
||||
{
|
||||
//DevCon.Warning("GIF APATH busy %x Holding for later W %x, R %x", gifRegs->stat.APATH, Path1WritePos, Path1ReadPos);
|
||||
size = GetMTGS().PrepDataPacket(GIF_PATH_1, data, diff, true);
|
||||
pDest = &Path1Buffer[Path1WritePos*16];
|
||||
|
||||
|
||||
|
||||
//DevCon.Warning("Storing size %x PATH 1", size);
|
||||
if (size > diff) {
|
||||
// fixme: one of these days the following *16's will get cleaned up when we introduce
|
||||
// a special qwc/simd16 optimized version of memcpy_aligned. :)
|
||||
//DevCon.Status("XGkick Wrap!");
|
||||
memcpy_aligned(pDest, VU1.Mem + addr, diff*16);
|
||||
Path1WritePos += size;
|
||||
size -= diff;
|
||||
pDest += diff*16;
|
||||
memcpy_aligned(pDest, VU1.Mem, size*16);
|
||||
}
|
||||
else {
|
||||
memcpy_aligned(pDest, VU1.Mem + addr, size*16);
|
||||
Path1WritePos += size;
|
||||
}
|
||||
if(!gifRegs->stat.P1Q) CPU_INT(28, 16);
|
||||
gifRegs->stat.P1Q = true;
|
||||
}
|
||||
|
||||
GetMTGS().SendDataPacket();
|
||||
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
|
|
Loading…
Reference in New Issue