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