Path3 Masking mystery solved, Simpsons (Issue 24) GT4 (Issue 211), tenchu and many many other path3 masking games should be fixed. This will only work on MTGS.

Also semi-removed my gifsplit thing to resolve the tekken 5 menus Issue 209

Note: GT4 is still missing its logo, this is down to a really bizzare timing issue i cant pinpoint.

Removed redundant path3hack

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1257 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
refraction 2009-05-25 07:07:59 +00:00
parent bd9886b332
commit 44378b31f7
9 changed files with 133 additions and 132 deletions

View File

@ -571,7 +571,6 @@ int loadElfFile(const char *filename)
}
#include "VU.h"
extern bool path3hack;
int g_VUGameFixes = 0;
// fixme - this should be moved to patches or eliminated
@ -584,9 +583,5 @@ void LoadGameSpecificSettings()
case 0xb99379b7: // erementar gerad (discolored chars)
g_VUGameFixes |= VUFIX_XGKICKDELAY2; // Tested - still needed - arcum42
break;
//case 0xa08c4057: //Sprint Cars (SLUS)
//case 0x8b0725d5: //Flinstones Bedrock Racing (SLES)
//path3hack = TRUE; // We can move this to patch files right now
//break;
}
}

View File

@ -243,8 +243,6 @@ void gsReset()
memzero_obj(g_RealGSMem);
Path3transfer = FALSE;
GSCSRr = 0x551B400F; // Set the FINISH bit to 1 for now
GSIMR = 0x7f00;
psHu32(GIF_STAT) = 0;

View File

@ -28,7 +28,7 @@
using std::min;
#define gifsplit 64
#define gifsplit 0x10000
enum gifstate_t
{
GIF_STATE_READY = 0,
@ -57,6 +57,9 @@ __forceinline void gsInterrupt() {
//Console::WriteLn("Eh? why are you still interrupting! chcr %x, qwc %x, done = %x", params gif->chcr, gif->qwc, done);
return;
}
if(Path3progress == 2) vif1Regs->stat &= ~VIF1_STAT_VGW;
if (gif->qwc > 0 || gspath3done == 0) {
if (!(psHu32(DMAC_CTRL) & 0x1)) {
Console::Notice("gs dma masked, re-scheduling...");
@ -66,19 +69,11 @@ __forceinline void gsInterrupt() {
}
GIFdma();
#ifdef GSPATH3FIX
// re-raise the IRQ as part of the mysterious Path3fix.
// fixme - this hack *should* have the gs_irq raised from the VIF, I think. It would be
// more efficient and more correct. (air)
/*if (!(vif1Regs->mskpath3 && (vif1ch->chcr & 0x100)) || (psHu32(GIF_MODE) & 0x1))
CPU_INT( 2, 64 );*/
#endif
if(gspath3done == 0 || gif->qwc > 0) return;
return;
}
gspath3done = 0;
gscycles = 0;
Path3transfer = FALSE;
gif->chcr &= ~0x100;
GSCSRr &= ~0xC000; //Clear FIFO stuff
GSCSRr |= 0x4000; //FIFO empty
@ -89,12 +84,10 @@ __forceinline void gsInterrupt() {
}
static void WRITERING_DMA(u32 *pMem, u32 qwc)
static u32 WRITERING_DMA(u32 *pMem, u32 qwc)
{
psHu32(GIF_STAT) |= 0xE00;
// Path3 transfer will be set to false by the GIFtag handler.
Path3transfer = TRUE;
if( mtgsThread != NULL )
{
@ -114,15 +107,14 @@ static void WRITERING_DMA(u32 *pMem, u32 qwc)
memcpy_aligned(pgsmem, pMem, sizetoread<<4);
mtgsThread->SendDataPacket();
return sizetoread;
}
else
{
GSGIFTRANSFER3(pMem, qwc);
if (GSgetLastTag != NULL)
{
GSgetLastTag(&s_gstag);
if (s_gstag == 1) Path3transfer = FALSE; /* fixes SRS and others */
}
gif->madr+= qwc*16;
gif->qwc -= qwc;
return qwc;
}
}
@ -145,11 +137,11 @@ int _GIFchain() {
Console::Notice( "Hackfix - NULL GIFchain" );
return -1;
}
WRITERING_DMA(pMem, qwc);
qwc = WRITERING_DMA(pMem, qwc);
gif->madr+= qwc*16;
gif->qwc -= qwc;
return (qwc)*2;
/*gif->madr+= qwc*16;
gif->qwc -= qwc;*/
return (qwc);
}
static __forceinline void GIFchain()
@ -161,10 +153,7 @@ static __forceinline void GIFchain()
static __forceinline void dmaGIFend()
{
if ((psHu32(GIF_MODE) & 0x4) && gif->qwc != 0)
CPU_INT(2, min( 8, (int)gif->qwc ) /** BIAS*/);
else
CPU_INT(2, min( gifsplit, (int)gif->qwc ) /** BIAS*/);
CPU_INT(2, 2);
}
// These could probably be consolidated into one function,
@ -172,10 +161,10 @@ static __forceinline void dmaGIFend()
// not to do the gif->qwc != 0 check. --arcum42
static __forceinline void GIFdmaEnd()
{
if (psHu32(GIF_MODE) & 0x4)
CPU_INT(2, min( 8, (int)gif->qwc ) /** BIAS*/);
else
CPU_INT(2, min( gifsplit, (int)gif->qwc ) /** BIAS*/);
//if (psHu32(GIF_MODE) & 0x4)
CPU_INT(2, gscycles * BIAS);
/*else
CPU_INT(2, min( gifsplit, (int)gif->qwc ) * BIAS);*/
}
void GIFdma()
@ -183,7 +172,7 @@ void GIFdma()
u32 *ptag;
u32 id;
gscycles= prevcycles ? prevcycles: gscycles;
gscycles= prevcycles ? prevcycles: 0;
if ((psHu32(GIF_CTRL) & 8)) { // temporarily stop
Console::WriteLn("Gif dma temp paused?");
@ -219,6 +208,13 @@ void GIFdma()
GSCSRr |= 0x8000; //FIFO full
psHu32(GIF_STAT)|= 0x10000000; // FQC=31, hack ;) [ used to be 0xE00; // OPH=1 | APATH=3]
if(((psHu32(GIF_STAT) & 0x100) || (vif1.cmd & 0x7f) == 0x50) && (psHu32(GIF_MODE) & 0x4) && Path3progress == 0) //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);
dmaGIFend();
return;
}
#ifdef GSPATH3FIX
if (vif1Regs->mskpath3 || (psHu32(GIF_MODE) & 0x1)) {
if(gif->qwc == 0) {
@ -245,26 +241,24 @@ void GIFdma()
}
}
GIFchain();
if((gif->qwc == 0) && ((gspath3done == 1) || (gif->chcr & 0xc) == 0)){
gspath3done = 0;
gif->chcr &= ~0x100;
GSCSRr &= ~0xC000;
GSCSRr |= 0x4000;
Path3transfer = FALSE;
psHu32(GIF_STAT)&= ~0x1F000E00; // OPH=0 | APATH=0 | QFC=0
hwDmacIrq(DMAC_GIF);
if(Path3progress == 2/* && gif->qwc != 0*/)
{
dmaGIFend();
return;
}
//Dont unfreeze xmm regs here, Masked PATH3 can only be called by VIF, which is already handling it.
GIFchain();
GIFdmaEnd();
return;
}
#endif
// Transfer Dn_QWC from Dn_MADR to GIF
if ((gif->chcr & 0xc) == 0 || gif->qwc > 0) { // Normal Mode
if ((((psHu32(DMAC_CTRL) & 0xC0) == 0x80) && ((gif->chcr & 0xc) == 0))) {
Console::WriteLn("DMA Stall Control on GIF normal");
}
GIFchain(); //Transfers the data set by the switch
if (((gif->qwc == 0) && (gif->chcr & 0xc) == 0))
@ -273,7 +267,6 @@ void GIFdma()
{
GIFdmaEnd();
return;
}
}
if ((gif->chcr & 0xc) == 0x4 && gspath3done == 0)
@ -322,23 +315,23 @@ void GIFdma()
prevcycles = 0;
if (!(vif1Regs->mskpath3 || (psHu32(GIF_MODE) & 0x1))) {
if (gspath3done == 0 || gif->qwc > 0)
{
if (gif->qwc != 0)
{
GIFdmaEnd();
}
else
if (gspath3done == 0 && gif->qwc == 0)
{
ptag = (u32*)dmaGetAddr(gif->tadr); //Set memory pointer to TADR
gif->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag
gif->chcr = ( gif->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15
gif->madr = ptag[1];
gspath3done = hwDmacSrcChainWithStack(gif, (ptag[0] >> 28) & 0x7);
if ((gif->chcr & 0x80) && (ptag[0] >> 31)) { //Check TIE bit of CHCR and IRQ bit of tag
GIF_LOG("dmaIrq Set");
gspath3done = 1;
}
GIFdmaEnd();
gif->qwc = 0;
return;
}
}
} else GIFdmaEnd();
gscycles = 0;
}
}
@ -358,23 +351,33 @@ void dmaGIF() {
GSCSRr &= ~0xC000; //Clear FIFO stuff
GSCSRr |= 0x8000; //FIFO full
psHu32(GIF_STAT)|= 0x10000000; // FQC=31, hack ;) [used to be 0xE00; // OPH=1 | APATH=3]
Path3progress = 2;
if ((gif->qwc == 0) && ((gif->chcr & 0xc) != 0)){
u32 *ptag;
ptag = (u32*)dmaGetAddr(gif->tadr);
gif->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag
gif->chcr = ( gif->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15
gif->madr = ptag[1];
//gspath3done = hwDmacSrcChainWithStack(gif, (ptag[0] >> 28) & 0x7);
GIFdmaEnd();
gif->qwc = 0;
GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx", ptag[1], ptag[0], gif->qwc, (ptag[0] >> 28), gif->madr);
gspath3done = hwDmacSrcChainWithStack(gif, (ptag[0] >> 28) & 0x7);
if ((gif->chcr & 0x80) && (ptag[0] >> 31)) { //Check TIE bit of CHCR and IRQ bit of tag
GIF_LOG("dmaIrq Set");
gspath3done = 1;
}
GIFdma();
//gif->qwc = 0;
return;
}
//Halflife sets a QWC amount in chain mode, no tadr set.
if((gif->qwc > 0) && ((gif->chcr & 0x4) == 0x4)) gspath3done = 1;
dmaGIFend();
GIFdma();
}
// called from only one location, so forceinline it:

View File

@ -287,9 +287,11 @@ __forceinline u32 mtgsThreadObject::_gifTransferDummy( GIF_PATH pathidx, const u
pMem += sizeof(GIFTAG);
--size;
if(pathidx == 2 && path.tag.eop)
if(pathidx == 2)
{
Path3transfer = FALSE;
if(path.tag.flg != GIF_FLG_IMAGE)Path3progress = 1; //Other mode
else Path3progress = 0; //IMAGE mode
//if(pathidx == 2) GIF_LOG("Set Giftag NLoop %d EOP %x Mode %d Path3msk %x Path3progress %x ", path.tag.nloop, path.tag.eop, path.tag.flg, vif1Regs->mskpath3, Path3progress);
}
if( pathidx == 0 )
@ -305,11 +307,11 @@ __forceinline u32 mtgsThreadObject::_gifTransferDummy( GIF_PATH pathidx, const u
return ++size;
}
}
}
else
}else
{
// NOTE: size > 0 => do {} while(size > 0); should be faster than while(size > 0) {}
//if(pathidx == 2) GIF_LOG("PATH3 NLoop %d EOP %x Mode %d Path3msk %x Path3progress %x ", path.tag.nloop, path.tag.eop, path.tag.flg, vif1Regs->mskpath3, Path3progress);
switch(path.tag.flg)
{
case GIF_FLG_PACKED:
@ -372,10 +374,11 @@ __forceinline u32 mtgsThreadObject::_gifTransferDummy( GIF_PATH pathidx, const u
}
}
if(pathidx == 0)
if(pathidx == 0 || pathidx == 2)
{
if(path.tag.eop && path.tag.nloop == 0)
{
//if(pathidx == 2) GIF_LOG("BREAK PATH3 NLoop %d EOP %x Mode %d Path3msk %x Path3progress %x ", path.tag.nloop, path.tag.eop, path.tag.flg, vif1Regs->mskpath3, Path3progress);
break;
}
}
@ -392,6 +395,23 @@ __forceinline u32 mtgsThreadObject::_gifTransferDummy( GIF_PATH pathidx, const u
// along the way (often means curreg was in a bad state or something)
}
}
if(pathidx == 2)
{
if(path.tag.nloop == 0 )
{
//DevCon::Notice("Finishing Giftag NLoop %d EOP %x Mode %d nregs %d Path3progress %d Vifstat VGW %x",
//params path.tag.nloop, path.tag.eop, path.tag.flg, path.tag.nreg, Path3progress, vif1Regs->stat & VIF1_STAT_VGW);
if(path.tag.eop)
{
Path3progress = 2;
//GIF_LOG("Set progress NLoop %d EOP %x Mode %d Path3msk %x Path3progress %x ", path.tag.nloop, path.tag.eop, path.tag.flg, vif1Regs->mskpath3, Path3progress);
}
}
}
#ifdef PCSX2_GSRING_SAMPLING_STATS
__asm
{
@ -838,6 +858,11 @@ int mtgsThreadObject::PrepDataPacket( GIF_PATH pathidx, const u8* srcdata, u32 s
// enough room for size - retval:
int retval = _gifTransferDummy( pathidx, srcdata, size );
if(pathidx == 2)
{
gif->madr += (size - retval) * 16;
gif->qwc -= size - retval;
}
size = size - retval;
m_packet_size = size;
size++; // takes into account our command qword.

View File

@ -57,7 +57,6 @@ PatchTextTable commands[] =
// X - EE rounding mode (default is NEAR)
// Y - VU rounding mode (default is CHOP)
{ "zerogs", 6, patchFunc_zerogs }, // zerogs=hex
{ "path3hack", 7, patchFunc_path3hack },
{ "vunanmode",8, patchFunc_vunanmode },
{ "ffxhack",9, patchFunc_ffxhack},
{ "xkickdelay",10, patchFunc_xkickdelay},
@ -674,11 +673,6 @@ void patchFunc_vunanmode( char * cmd, char * param )
// Doesn't do anything anymore
}
void patchFunc_path3hack( char * cmd, char * param )
{
path3hack = TRUE;
}
void patchFunc_roundmode( char * cmd, char * param )
{
int index;

View File

@ -82,7 +82,6 @@ void patchFunc_comment( char * text1, char * text2 );
void patchFunc_gametitle( char * text1, char * text2 );
void patchFunc_patch( char * text1, char * text2 );
void patchFunc_fastmemory( char * text1, char * text2 );
void patchFunc_path3hack( char * text1, char * text2 );
void patchFunc_roundmode( char * text1, char * text2 );
void patchFunc_zerogs( char * text1, char * text2 );
void patchFunc_vunanmode( char * text1, char * text2 );
@ -109,7 +108,6 @@ int AddPatch(int Mode, int Place, int Address, int Size, u64 data);
extern void SetFastMemory(int); // iR5900LoadStore.c
extern bool path3hack;
//extern int g_VUGameFixes;
extern int g_ZeroGSOptions;
extern u32 g_sseMXCSR;

View File

@ -58,8 +58,7 @@ static const unsigned int VIF0dmanum = 0;
static const unsigned int VIF1dmanum = 1;
int g_vifCycles = 0;
bool path3hack = false;
bool Path3transfer = false;
int Path3progress = 2; //0 = Image Mode (DirectHL), 1 = transferring, 2 = Stopped at End of Packet
u32 splittransfer[4];
u32 splitptr = 0;
@ -1891,6 +1890,7 @@ static int __fastcall Vif1TransDirectHL(u32 *data)
}
else
{
psHu32(GIF_STAT) &= ~0x80;
ret = vif1.tag.size;
vif1.tag.size = 0;
vif1.cmd = 0;
@ -2019,22 +2019,11 @@ static void Vif1CMDMskPath3() // MSKPATH3
#ifdef GSPATH3FIX
if ((vif1Regs->code >> 15) & 0x1)
{
while ((gif->chcr & 0x100)) //Can be done 2 different ways, depends on the game/company
{
if (!path3hack && !Path3transfer && (gif->qwc == 0)) break;
gsInterrupt();
if (path3hack && (gif->qwc == 0)) break; //add games not working with it to elfheader.c to enable this instead
}
psHu32(GIF_STAT) |= 0x2;
}
else
{
// fixme: This is the *only* reason 'transferred' is global. Otherwise it'd be local to Vif1Transfer.
if (gif->chcr & 0x100) CPU_INT(2, (transferred >> 2) * BIAS); // Restart Path3 on its own, time it right!
Path3progress = 1; //Let the Gif know it can transfer again (making sure any vif stall isnt unset prematurely)
psHu32(GIF_STAT) &= ~0x2;
}
#else
@ -2068,10 +2057,9 @@ static void Vif1CMDFlush() // FLUSH/E/A
if((vif1.cmd & 0x7f) == 0x13)
{
while ((gif->chcr & 0x100))
if(Path3progress != 2 && gif->chcr & 0x100) // Gif is already transferring so wait for it.
{
if (!Path3transfer && gif->qwc == 0) break;
gsInterrupt();
vif1Regs->stat |= VIF1_STAT_VGW;
}
}
@ -2123,13 +2111,16 @@ static void Vif1CMDDirectHL() // DIRECT/HL
vif1.tag.size = vifImm << 2;
if((gif->chcr & 0x100) && (vif1.cmd & 0x7f) == 0x51)
if((vif1.cmd & 0x7f) == 0x51)
{
//if(vif1Regs->mskpath3)CPU_INT(2, vif1ch->qwc - (vif1.vifpacketsize >> 2) * BIAS);
//DirectHL flushes the lot
if(gif->chcr & 0x100 && Path3progress == 0) //PATH3 is in image mode, so wait for end of transfer
{
//DevCon::Notice("DirectHL gif chcr %x gif qwc %x mskpth3 %x", params gif->chcr, gif->qwc, vif1Regs->mskpath3);
vif1Regs->stat |= VIF1_STAT_VGW;
}
}
psHu32(GIF_STAT) |= 0x80;
}
static void Vif1CMDNull() // invalid opcode
@ -2215,7 +2206,6 @@ int VIF1transfer(u32 *data, int size, int istag)
if (vif1.tag.size != 0) DevCon::Error("no vif1 cmd but tag size is left last cmd read %x", params vif1Regs->code);
if (vif1.irq) break;
if(vif1Regs->stat & VIF1_STAT_VGW) break;
vif1.cmd = (data[0] >> 24);
vif1Regs->code = data[0];
@ -2459,7 +2449,7 @@ __forceinline void vif1SetupTransfer()
else
ret = VIF1transfer(vif1ptag + 2, 2, 1); //Transfer Tag
if (ret < 0)
if (ret < 0 && vif1.irqoffset < 2)
{
vif1.inprogress = 0; //Better clear this so it has to do it again (Jak 1)
return; //There has been an error or an interrupt
@ -2485,21 +2475,17 @@ __forceinline void vif1Interrupt()
VIF_LOG("vif1Interrupt: %8.8x", cpuRegs.cycle);
g_vifCycles = 0;
if((vif1Regs->stat & VIF1_STAT_VGW) &&
(gif->chcr & 0x100))
if((vif1Regs->stat & VIF1_STAT_VGW))
{
int delay = 0;
if ((psHu32(GIF_MODE) & 0x1))
delay = min( 8, (int)gif->qwc );
else
delay = gif->qwc * BIAS;
//else CPU_INT(2, min( 64, (int)gif->qwc ) * BIAS);
CPU_INT(1, delay);
if(gif->chcr & 0x100)
{
CPU_INT(1, 2);
return;
}
vif1Regs->stat &= ~VIF1_STAT_VGW;
else vif1Regs->stat &= ~VIF1_STAT_VGW;
}
if ((vif1ch->chcr & 0x100) == 0) Console::WriteLn("Vif1 running when CHCR == %x", params vif1ch->chcr);
@ -2539,7 +2525,7 @@ __forceinline void vif1Interrupt()
if ((vif1.inprogress & 0x1) == 0) vif1SetupTransfer();
CPU_INT(1, (vif1ch->qwc * BIAS) - (vif1.vifpacketsize >> 1));
CPU_INT(1, g_vifCycles);
return;
}
@ -2606,7 +2592,7 @@ void dmaVIF1()
// Chain Mode
vif1.done = false;
CPU_INT(1, 0);
vif1Interrupt();
}

View File

@ -47,7 +47,7 @@ struct vifStruct {
};
extern vifStruct vif0, vif1;
extern bool Path3transfer;
extern int Path3progress;
void __fastcall UNPACK_S_32( u32 *dest, u32 *data, int size );

View File

@ -4409,7 +4409,7 @@ void recVUMI_XGKICK_(VURegs *VU)
CALLFunc((uptr)GSgifTransfer1);
#endif
}
psHu32(GIF_STAT) &= ~0x100;
s_ScheduleXGKICK = 0;
}
@ -4430,6 +4430,8 @@ void recVUMI_XGKICK(VURegs *VU, int info)
SHL32ItoR(isreg, 4);
AND32ItoR(isreg, 0x3fff);
s_XGKICKReg = isreg;
psHu32(GIF_STAT) |= 0x100;
if (!SUPERVU_XGKICKDELAY || pc == s_pCurBlock->endpc)
{