After hours of frustration getting my gifDummyTranfser() function to work the way pcsx2 wants path2/path3 transfers to occur, I decided to just rewrite it again using the old gifDummyTransfer() as a base.

Fixes GT4 corrupt textures.
Again tell me if this version breaks anything...

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1868 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
cottonvibes 2009-09-19 04:04:06 +00:00
parent 8376e0a886
commit 32e8a8a260
2 changed files with 86 additions and 73 deletions

View File

@ -97,6 +97,20 @@ struct GIFPath
__forceinline void PrepRegs(bool doPrep);
__forceinline void SetTag(const void* mem);
__forceinline bool StepReg()
{
u32 numRegs = ((tag.nreg-1)&0xf)+1;
if ((++curreg & 0xf) == numRegs) {
curreg = 0;
if (--tag.nloop == 0) {
return false;
}
}
return true;
}
__forceinline u8 GetReg() {
return regs[curreg&0xf];
}
};

View File

@ -90,6 +90,7 @@ __forceinline void GIFPath::SetTag(const void* mem)
{
tag = *((GIFTAG*)mem);
curreg = 0;
PrepRegs();
}
static void _mtgsFreezeGIF( SaveStateBase& state, GIFPath (&paths)[3] )
@ -242,101 +243,99 @@ void mtgsThreadObject::Reset()
memzero_obj( s_path );
}
#define incPmem(x) { \
pMem += (x) * 16; \
size += (x) * 16; \
#define incTag(x, y) { \
pMem += (x); \
size -= (y); \
if ((pathidx==GIF_PATH_1)&&(pMem>=vuMemEnd)) pMem -= 0x4000; \
}
#define subVal(x) ((x) ? (x-1) : 0)
#define aMin(x, y) ((x < y) ? (x) : (y))
#define subVal(x, y) ((x > y) ? (x-y) : 0 )
__forceinline void gsHandler(const u8* pMem) {
const int handler = pMem[8];
if (handler >= 0x60 && handler < 0x63) {
//DevCon::Status("GIF Tag Interrupt");
s_GSHandlers[handler&0x3]((const u32*)pMem);
}
}
__forceinline int mtgsThreadObject::_gifTransferDummy(GIF_PATH pathidx, const u8* pMem, u32 size)
{
GIFPath& path = s_path[pathidx];
u32 finish = (pathidx == GIF_PATH_1) ? 0x4000 : (size<<4);
u32 oldSize = 0;
u32 numRegs = 0;
const u8* vuMemEnd = pMem + (size<<4); // End of VU Mem
bool pathContinue = !!path.tag.nloop; // Continue From Last Transfer
bool EOP = 0;
bool hasRegAD = 0;
size = 0;
GIFPath& path = s_path[pathidx]; // Current Path
const u8* vuMemEnd = pMem + (size<<4); // End of VU1 Mem
if (pathidx==GIF_PATH_1) size = 0x4000; // VU1 mem size
u32 startSize = size; // Start Size
while(!EOP && size < finish) {
while (size > 0) {
if (!path.tag.nloop) {
if(!pathContinue) {
path.SetTag(pMem);
path.PrepRegs(!path.tag.flg);
incPmem(1);
incTag(16, 1);
if (pathidx == GIF_PATH_3) {
if (path.tag.flg&2) Path3progress = IMAGE_MODE;
else Path3progress = TRANSFER_MODE;
}
}
pathContinue = 0;
oldSize = size;
numRegs = ((path.tag.nreg-1)&0xf)+1;
EOP = ((pathidx == GIF_PATH_2) ? 0 : path.tag.eop);
if (!path.tag.nloop || size >= finish) continue;
switch(path.tag.flg) {
case GIF_FLG_PACKED:
for (u32 i = 0; i < path.tag.nloop; i++) {
for (u32 j = path.curreg; j < numRegs; j++) {
if (path.regs[j] == 0x0e) {
const int handler = pMem[8];
if (handler >= 0x60 && handler < 0x63) {
//DevCon::Status("GIF Tag Interrupt");
s_GSHandlers[handler&0x3]((const u32*)pMem);
}
hasRegAD = 1;
else {
switch(path.tag.flg) {
case GIF_FLG_PACKED:
do {
if (path.GetReg() == 0xe) {
gsHandler(pMem);
}
incPmem(1);
path.curreg = 0;
if (size >= finish) goto endLoop;
incTag(16, 1);
} while(path.StepReg() && size > 0);
break;
case GIF_FLG_REGLIST:
{
u32 numRegs = (((path.tag.nreg-1)&0xf)+2)/2;
if((numRegs * path.tag.nloop) <= size) {
u32 temp1 = (numRegs - path.curreg);
u32 temp2 = (numRegs * subVal(path.tag.nloop, 1));
incTag((temp1*16), temp1);
incTag((temp2*16), temp2);
path.tag.nloop = 0;
}
if (!hasRegAD) { // Optimization: No Need to Loop
incPmem(numRegs * subVal(path.tag.nloop));
break;
else {
size *= 2;
do { incTag(8, 1); }
while(path.StepReg() && size > 0);
if (size & 1) { incTag(8, 1); }
size /= 2;
}
}
break;
case GIF_FLG_REGLIST:
numRegs = (numRegs + 1) / 2;
incPmem((numRegs - path.curreg) * path.tag.nloop);
incPmem((numRegs * subVal(path.tag.nloop)));
case GIF_FLG_IMAGE:
case GIF_FLG_IMAGE2:
{
int len = aMin(size, path.tag.nloop);
incTag((len * 16), len);
path.tag.nloop -= len;
}
break;
case GIF_FLG_IMAGE:
case GIF_FLG_IMAGE2:
incPmem(path.tag.nloop);
}
}
if (path.tag.eop && !path.tag.nloop) {
if (pathidx != GIF_PATH_2) {
break;
}
}
}
}
endLoop:
// This handles cases where we skipped too far ahead because of bulky IMAGE/REGLIST tags
// or PACKED tags w/o RegA+D (they don't compare 'size < finish' every qwc).
if (size > finish) size = finish;
// Sets information to resume partial transfers
if (!EOP && path.tag.nloop && pathidx) {
int diff = (size - oldSize) / 16;
if (!(path.tag.flg&2)) { // PACKED/REGLIST
path.curreg = (diff % path.tag.nloop);
path.tag.nloop -= (diff / numRegs);
}
else path.tag.nloop -= diff;
}
else {
path.curreg = 0;
path.tag.nloop = 0;
}
size = (startSize - size);
if (pathidx == GIF_PATH_3) {
gif->madr += size;
gif->qwc -= (size/16);
if (EOP) Path3progress = STOPPED_MODE;
else if (path.tag.flg&2) Path3progress = IMAGE_MODE;
else Path3progress = TRANSFER_MODE;
if (path.tag.eop && !path.tag.nloop) {
Path3progress = STOPPED_MODE;
}
gif->madr += size * 16;
gif->qwc -= size;
}
return (size / 16);
return size;
}
// Processes a GIFtag & packet, and throws out some gsIRQs as needed.