Found wizardry / growlanser 2 & 3 hanging bug thanks to rama. OPH flag in GIF_STAT was misinterpreted (probably). It needs to be set on download, not upload.

Also clean-up/fix of GS download logic.  Might fix something if we're very lucky.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2954 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
sudonim1 2010-05-06 00:43:13 +00:00
parent d474febcd6
commit 7c6f8877e8
7 changed files with 72 additions and 54 deletions

View File

@ -210,7 +210,6 @@ void GIFdma()
}
gifRegs->stat.clear_flags(GIF_STAT_P3Q);
gifRegs->stat.APATH = GIF_APATH3;
gifRegs->stat.OPH = true;
if (vif1Regs->mskpath3 || gifRegs->mode.M3R)
{

View File

@ -256,11 +256,11 @@ _f void vif1STAT(u32 value) {
// 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
// As far as the GS is concerned, the transfer starts as soon as TRXDIR 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 = min((u32)16, vif1.GSLastTRXPOS);
//Console.Warning("Reversing VIF Transfer for %x QWC", vif1.GSLastTRXPOS);
vif1Regs->stat.FQC = min((u32)16, vif1.GSLastDownloadSize);
//Console.Warning("Reversing VIF Transfer for %x QWC", vif1.GSLastDownloadSize);
}
else // Memory transferring to Vif.

View File

@ -81,8 +81,8 @@ void vif1TransferToMemory()
g_vifCycles += vif1ch->qwc * 2;
vif1ch->madr += vif1ch->qwc * 16; // mgs3 scene changes
if(vif1.GSLastTRXPOS > vif1ch->qwc)
vif1Regs->stat.FQC = vif1.GSLastTRXPOS - vif1ch->qwc;
if(vif1.GSLastDownloadSize > vif1ch->qwc)
vif1Regs->stat.FQC = vif1.GSLastDownloadSize - vif1ch->qwc;
else
vif1Regs->stat.FQC = 0;
@ -217,7 +217,7 @@ __forceinline void vif1Interrupt()
//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);
gifRegs->stat.APATH = GIF_APATH_IDLE;
}
if (schedulepath3msk & 0x10) Vif1MskPath3();

View File

@ -124,8 +124,6 @@ template<int idx> _f int _vifCode_Direct(int pass, u8* data, bool isDirectHL) {
}
//}
gifRegs->stat.clear_flags(GIF_STAT_P2Q);
gifRegs->stat.APATH = GIF_APATH2;
gifRegs->stat.OPH = true;
Registers::Freeze();
nVifStruct& v = nVif[1];
@ -146,11 +144,11 @@ template<int idx> _f int _vifCode_Direct(int pass, u8* data, bool isDirectHL) {
vif1.tag.size = 0;
vif1.cmd = 0;
v.bSize = 0;
gifRegs->stat.clear_flags(GIF_STAT_APATH2 | GIF_STAT_OPH);
gifRegs->stat.APATH = GIF_APATH_IDLE;
}
else { // Partial Transfer
//DevCon.WriteLn("DirectHL: Partial Transfer [%d]", size);
gifRegs->stat.set_flags(GIF_STAT_APATH2 | GIF_STAT_OPH);
gifRegs->stat.APATH = GIF_APATH2;
memcpy_fast(&v.buffer[v.bSize], data, size);
v.bSize += size;
vif1.tag.size -= ret;

View File

@ -24,16 +24,32 @@ struct vifCode {
u16 cl;
};
union tBITBLT {
union tBITBLTBUF {
u64 _u64;
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 SBP : 14;
u32 pad14 : 2;
u32 SBW : 6;
u32 pad22 : 2;
u32 SPSM : 6;
u32 pad30 : 2;
u32 DBP : 14;
u32 pad46 : 2;
u32 DBW : 6;
u32 pad54 : 2;
u32 DPSM : 6;
u32 pad62 : 2;
};
u32 _u32;
};
union tTRXREG {
u64 _u64;
struct {
u32 RRW : 12;
u32 pad12 : 20;
u32 RRH : 12;
u32 pad44 : 20;
};
};
// NOTE, if debugging vif stalls, use sega classics, spyro, gt4, and taito
@ -48,9 +64,12 @@ struct vifStruct {
bool done;
bool vifstalled;
bool stallontag;
tBITBLT TRXPOS; //used for reversed fifo operations, sometimes only the GS knows how big (like on HW register fifo read)!
u32 GSLastTRXPOS;
// GS registers used for calculating the size of the last local->host transfer initiated on the GS
// Transfer size calculation should be restricted to GS emulation in the future
tBITBLTBUF BITBLTBUF;
tTRXREG TRXREG;
u32 GSLastDownloadSize;
u8 irqoffset; // 32bit offset where next vif code is
u32 savedtag; // need this for backwards compat with save states

View File

@ -277,51 +277,56 @@ void SaveStateBase::gifPathFreeze()
static __forceinline void gsHandler(const u8* pMem)
{
const int handler = pMem[8];
const int reg = pMem[8];
if(handler == 0x50)
if (reg == 0x50)
vif1.BITBLTBUF._u64 = *(u64*)pMem;
else if (reg == 0x52)
vif1.TRXREG._u64 = *(u64*)pMem;
else if (reg == 0x53)
{
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)
// local -> host
if ((pMem[0] & 3) == 1)
{
case 0x3:
VIF_LOG("8bit");
vif1.TRXPOS.BLTDIVIDE = 16; //8bit
//Onimusha does TRXREG without BLTDIVIDE first, so we "assume" 32bit for this equation, probably isnt important.
// ^ WTF, seriously? This is really important (pseudonym)
u8 bpp = 32;
switch(vif1.BITBLTBUF.SPSM & 7)
{
case 0:
bpp = 32;
break;
case 0x2:
VIF_LOG("16bit");
vif1.TRXPOS.BLTDIVIDE = 8; //16bit
case 1:
bpp = 24;
break;
case 0x1:
VIF_LOG("24bit");
vif1.TRXPOS.BLTDIVIDE = 5; //24bit
case 2:
bpp = 16;
break;
case 3:
bpp = 8;
break;
// 4 is 4 bit but this is forbidden
default:
VIF_LOG("32bit");
vif1.TRXPOS.BLTDIVIDE = 4; //32bit
break;
Console.Error("Illegal format for GS upload: SPSM=0%02o", vif1.BITBLTBUF.SPSM);
}
VIF_LOG("GS Download %dx%d SPSM= bpp=%d", vif1.TRXREG.RRW, vif1.TRXREG.RRH, vif1.BITBLTBUF.SPSM, bpp);
// 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;
gifRegs->stat.OPH = true;
}
}
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]);
//Onimusha does TRXREG without BLTDIVIDE first, so we "assume" 32bit for this equasion, probably isnt important.
if(vif1.TRXPOS.BLTDIVIDE) vif1.GSLastTRXPOS = (pMem16[0] * pMem16[2]) / (u8)vif1.TRXPOS.BLTDIVIDE;
else vif1.GSLastTRXPOS = (pMem16[0] * pMem16[2]) / 4;
}
if (handler >= 0x60)
if (reg >= 0x60)
{
// Question: What happens if an app writes to uncharted register space on real PS2
// hardware (handler 0x63 and higher)? Probably a silent ignorance, but not tested
// so just guessing... --air
s_gifPath.Handlers[handler-0x60]((const u32*)pMem);
s_gifPath.Handlers[reg-0x60]((const u32*)pMem);
}
}

View File

@ -4341,13 +4341,10 @@ void recVUMI_XGKICK_(VURegs *VU)
_freeX86regs();
_freeXMMregs();
OR32ItoM((uptr)&psHu32(GIF_STAT), (GIF_STAT_APATH1 | GIF_STAT_OPH)); // Set PATH1 GIF Status Flags
xMOV(edx, xRegister32(s_XGKICKReg));
xMOV(ecx, (uptr)VU->Mem);
xCALL(VU1XGKICK_MTGSTransfer);
AND32ItoM((uptr)&psHu32(GIF_STAT), ~(GIF_STAT_APATH1 | GIF_STAT_OPH)); // Clear PATH1 GIF Status Flags
s_ScheduleXGKICK = 0;
}