Couple of fixes, one for Kingdom Hearts 2 Issue 239, others might help textures in the GT games (maybe!)

Also prepared some code to add support for VU looping in MTGS mode, this will require a GS Spec update, so its commented out for now until i can sync an update with Gabest.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1289 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
refraction 2009-05-29 18:44:42 +00:00
parent e384d001da
commit aa64a21e93
8 changed files with 170 additions and 38 deletions

View File

@ -265,7 +265,7 @@ protected:
// Processes a GIFtag & packet, and throws out some gsIRQs as needed. // Processes a GIFtag & packet, and throws out some gsIRQs as needed.
// Used to keep interrupts in sync with the EE, while the GS itself // Used to keep interrupts in sync with the EE, while the GS itself
// runs potentially several frames behind. // runs potentially several frames behind.
u32 _gifTransferDummy( GIF_PATH pathidx, const u8 *pMem, u32 size ); int _gifTransferDummy( GIF_PATH pathidx, const u8 *pMem, u32 size );
// Used internally by SendSimplePacket type functions // Used internally by SendSimplePacket type functions
uint _PrepForSimplePacket(); uint _PrepForSimplePacket();

View File

@ -58,8 +58,6 @@ __forceinline void gsInterrupt() {
return; return;
} }
if(Path3progress == 2) vif1Regs->stat &= ~VIF1_STAT_VGW;
if (gif->qwc > 0 || gspath3done == 0) { if (gif->qwc > 0 || gspath3done == 0) {
if (!(psHu32(DMAC_CTRL) & 0x1)) { if (!(psHu32(DMAC_CTRL) & 0x1)) {
Console::Notice("gs dma masked, re-scheduling..."); Console::Notice("gs dma masked, re-scheduling...");
@ -72,12 +70,14 @@ __forceinline void gsInterrupt() {
return; return;
} }
vif1Regs->stat &= ~VIF1_STAT_VGW;
gspath3done = 0; gspath3done = 0;
gscycles = 0; gscycles = 0;
gif->chcr &= ~0x100; gif->chcr &= ~0x100;
GSCSRr &= ~0xC000; //Clear FIFO stuff GSCSRr &= ~0xC000; //Clear FIFO stuff
GSCSRr |= 0x4000; //FIFO empty GSCSRr |= 0x4000; //FIFO empty
psHu32(GIF_STAT)&= ~0xE00; // OPH=0 | APATH=0 psHu32(GIF_STAT) &= ~GIF_STAT_P3Q;
//psHu32(GIF_STAT)&= ~0xE00; // OPH=0 | APATH=0
psHu32(GIF_STAT)&= ~0x1F000000; // QFC=0 psHu32(GIF_STAT)&= ~0x1F000000; // QFC=0
hwDmacIrq(DMAC_GIF); hwDmacIrq(DMAC_GIF);
GIF_LOG("GIF DMA end"); GIF_LOG("GIF DMA end");
@ -86,7 +86,7 @@ __forceinline void gsInterrupt() {
static u32 WRITERING_DMA(u32 *pMem, u32 qwc) static u32 WRITERING_DMA(u32 *pMem, u32 qwc)
{ {
psHu32(GIF_STAT) |= 0xE00; psHu32(GIF_STAT) |= GIF_STAT_APATH3 | GIF_STAT_OPH;
if( mtgsThread != NULL ) if( mtgsThread != NULL )
@ -107,6 +107,7 @@ static u32 WRITERING_DMA(u32 *pMem, u32 qwc)
memcpy_aligned(pgsmem, pMem, sizetoread<<4); memcpy_aligned(pgsmem, pMem, sizetoread<<4);
mtgsThread->SendDataPacket(); mtgsThread->SendDataPacket();
if(Path3progress == 2) psHu32(GIF_STAT)&= ~(GIF_STAT_APATH3 | GIF_STAT_OPH); // OPH=0 | APATH=0
return sizetoread; return sizetoread;
} }
else else
@ -243,6 +244,7 @@ void GIFdma()
if(Path3progress == 2/* && gif->qwc != 0*/) if(Path3progress == 2/* && gif->qwc != 0*/)
{ {
vif1Regs->stat &= ~VIF1_STAT_VGW;
dmaGIFend(); dmaGIFend();
return; return;
} }
@ -347,8 +349,9 @@ void dmaGIF() {
return; return;
} }
gspath3done = 0; // For some reason this doesnt clear? So when the system starts the thread, we will clear it :)
gspath3done = 0; // For some reason this doesnt clear? So when the system starts the thread, we will clear it :)
psHu32(GIF_STAT) |= GIF_STAT_P3Q;
GSCSRr &= ~0xC000; //Clear FIFO stuff GSCSRr &= ~0xC000; //Clear FIFO stuff
GSCSRr |= 0x8000; //FIFO full GSCSRr |= 0x8000; //FIFO full
psHu32(GIF_STAT)|= 0x10000000; // FQC=31, hack ;) [used to be 0xE00; // OPH=1 | APATH=3] psHu32(GIF_STAT)|= 0x10000000; // FQC=31, hack ;) [used to be 0xE00; // OPH=1 | APATH=3]
@ -376,7 +379,7 @@ void dmaGIF() {
} }
//Halflife sets a QWC amount in chain mode, no tadr set. //Halflife sets a QWC amount in chain mode, no tadr set.
if((gif->qwc > 0) && ((gif->chcr & 0x4) == 0x4)) gspath3done = 1; if(gif->qwc > 0) gspath3done = 1;
GIFdma(); GIFdma();
} }
@ -391,7 +394,7 @@ static __forceinline int mfifoGIFrbTransfer() {
if ((gif->madr+mfifoqwc*16) > (psHu32(DMAC_RBOR) + psHu32(DMAC_RBSR)+16)) if ((gif->madr+mfifoqwc*16) > (psHu32(DMAC_RBOR) + psHu32(DMAC_RBSR)+16))
{ {
int s1 = ((psHu32(DMAC_RBOR) + psHu32(DMAC_RBSR)+16) - gif->madr) >> 4; int s1 = ((psHu32(DMAC_RBOR) + psHu32(DMAC_RBSR)+16) - gif->madr) >> 4;
int s2 = (mfifoqwc - s1);
// fixme - I don't think these should use WRITERING_DMA, since our source // fixme - I don't think these should use WRITERING_DMA, since our source
// isn't the DmaGetAddr(gif->madr) address that WRITERING_DMA expects. // isn't the DmaGetAddr(gif->madr) address that WRITERING_DMA expects.
@ -400,13 +403,14 @@ static __forceinline int mfifoGIFrbTransfer() {
if (src == NULL) return -1; if (src == NULL) return -1;
s1 = WRITERING_DMA(src, s1); s1 = WRITERING_DMA(src, s1);
if(s1 == (((psHu32(DMAC_RBOR) + psHu32(DMAC_RBSR)+16) - gif->madr) >> 4)) if(s1 == (mfifoqwc - s2))
{ {
/* and second copy 's2' bytes from 'maddr' to '&data[s1]' */ /* and second copy 's2' bytes from 'maddr' to '&data[s1]' */
src = (u32*)PSM(psHu32(DMAC_RBOR)); src = (u32*)PSM(psHu32(DMAC_RBOR));
if (src == NULL) return -1; if (src == NULL) return -1;
mfifoqwc = WRITERING_DMA(src, (mfifoqwc - s1)) + s1; s2 = WRITERING_DMA(src, s2);
} } else s2 = 0;
mfifoqwc = s1 + s2;
} }
else else
@ -579,10 +583,10 @@ void gifMFIFOInterrupt()
if (!gifmfifoirq) gifqwc = 0; if (!gifmfifoirq) gifqwc = 0;
gifstate = GIF_STATE_READY; gifstate = GIF_STATE_READY;
gif->chcr &= ~0x100; gif->chcr &= ~0x100;
vif1Regs->stat &= ~VIF1_STAT_VGW;
hwDmacIrq(DMAC_GIF); hwDmacIrq(DMAC_GIF);
GSCSRr &= ~0xC000; //Clear FIFO stuff GSCSRr &= ~0xC000; //Clear FIFO stuff
GSCSRr |= 0x4000; //FIFO empty GSCSRr |= 0x4000; //FIFO empty
psHu32(GIF_STAT)&= ~0xE00; // OPH=0 | APATH=0
psHu32(GIF_STAT)&= ~0x1F000000; // QFC=0 psHu32(GIF_STAT)&= ~0x1F000000; // QFC=0
} }

View File

@ -288,6 +288,23 @@ enum DMACIrqs
#define VIF_STAT_ER1 (1<<13) #define VIF_STAT_ER1 (1<<13)
#define VIF_STAT_FDR (1<<23) #define VIF_STAT_FDR (1<<23)
//GIF_STAT
#define GIF_STAT_M3R (1) //GIF_MODE Mask
#define GIF_STAT_M3P (1<<1) //VIF PATH3 Mask
#define GIF_STAT_IMT (1<<2) //Intermittent Transfer Mode
#define GIF_STAT_PSE (1<<3) //Temporary Transfer Stop
#define GIF_STAT_IP3 (1<<5) //Interrupted PATH3
#define GIF_STAT_P3Q (1<<6) //PATH3 request Queued
#define GIF_STAT_P2Q (1<<7) //PATH2 request Queued
#define GIF_STAT_P1Q (1<<8) //PATH1 request Queued
#define GIF_STAT_OPH (1<<9) //Output Path (Outputting Data)
#define GIF_STAT_APATH1 (1<<10) //Data Transfer Path 1 (In progress)
#define GIF_STAT_APATH2 (2<<10) //Data Transfer Path 2 (In progress)
#define GIF_STAT_APATH3 (3<<10) //Data Transfer Path 3 (In progress) (Mask too)
#define GIF_STAT_DIR (1<<12) //Transfer Direction
#define GIF_STAT_FQC (31<<24) //QWC in GIF-FIFO
//DMA interrupts & masks //DMA interrupts & masks
enum DMAInter enum DMAInter
{ {

View File

@ -259,10 +259,11 @@ void mtgsThreadObject::Reset()
// Used to keep interrupts in sync with the EE, while the GS itself // Used to keep interrupts in sync with the EE, while the GS itself
// runs potentially several frames behind. // runs potentially several frames behind.
// size - size of the packet in simd128's // size - size of the packet in simd128's
__forceinline u32 mtgsThreadObject::_gifTransferDummy( GIF_PATH pathidx, const u8* pMem, u32 size ) __forceinline int mtgsThreadObject::_gifTransferDummy( GIF_PATH pathidx, const u8* pMem, u32 size )
{ {
GIFPath& path = m_path[pathidx]; GIFPath& path = m_path[pathidx];
/* bool path1loop = false;
int startval = size;*/
#ifdef PCSX2_GSRING_SAMPLING_STATS #ifdef PCSX2_GSRING_SAMPLING_STATS
static uptr profStartPtr = 0; static uptr profStartPtr = 0;
static uptr profEndPtr = 0; static uptr profEndPtr = 0;
@ -296,9 +297,24 @@ __forceinline u32 mtgsThreadObject::_gifTransferDummy( GIF_PATH pathidx, const u
if( pathidx == 0 ) if( pathidx == 0 )
{ {
// int transize = 0;
// hack: if too much data for VU1, just ignore. // hack: if too much data for VU1, just ignore.
// The GIF is evil : if nreg is 0, it's really 16. Otherwise it's the value in nreg. // The GIF is evil : if nreg is 0, it's really 16. Otherwise it's the value in nreg.
/*const int numregs = path.tag.nreg ? path.tag.nreg : 16;
if(path.tag.flg < 2)
{
transize = (path.tag.nloop * numregs);
}
else transize = path.tag.nloop;
if(transize > (path.tag.flg == 1 ? 0x800 : 0x400))
{
//DevCon::Notice("Too much data");
path.tag.nloop = 0;
if(path1loop == true)return ++size - 0x400;
else return ++size;
}*/
const int numregs = ((path.tag.nreg-1)&15)+1; const int numregs = ((path.tag.nreg-1)&15)+1;
if((path.tag.nloop * numregs) > (size * ((path.tag.flg == 1) ? 2 : 1))) if((path.tag.nloop * numregs) > (size * ((path.tag.flg == 1) ? 2 : 1)))
@ -374,7 +390,22 @@ __forceinline u32 mtgsThreadObject::_gifTransferDummy( GIF_PATH pathidx, const u
} }
} }
if(pathidx == 0 || pathidx == 2) if(pathidx == 0)
{
if(path.tag.eop && path.tag.nloop == 0)
{
break;
}
/*if((path.tag.nloop > 0 || (!path.tag.eop && path.tag.nloop == 0)) && size == 0)
{
if(path1loop == true) return size - 0x400;
//DevCon::Notice("Looping Nloop %x, Eop %x, FLG %x", params path.tag.nloop, path.tag.eop, path.tag.flg);
size = 0x400;
pMem -= 0x4000;
path1loop = true;
}*/
}
if(pathidx == 2)
{ {
if(path.tag.eop && path.tag.nloop == 0) if(path.tag.eop && path.tag.nloop == 0)
{ {
@ -386,6 +417,11 @@ __forceinline u32 mtgsThreadObject::_gifTransferDummy( GIF_PATH pathidx, const u
if(pathidx == 0) if(pathidx == 0)
{ {
//If the XGKick has spun around the VU memory end address, we need to INCREASE the size sent.
/*if(path1loop == true)
{
return (size - 0x400); //This will cause a negative making eg. size(20) - retval(-30) = 50;
}*/
if(size == 0 && path.tag.nloop > 0) if(size == 0 && path.tag.nloop > 0)
{ {
path.tag.nloop = 0; path.tag.nloop = 0;
@ -533,8 +569,8 @@ int mtgsThreadObject::Callback()
const u128* data = m_RingBuffer.GetPtr( m_RingPos+1 ); const u128* data = m_RingBuffer.GetPtr( m_RingPos+1 );
// make sure that tag>>16 is the MAX size readable // make sure that tag>>16 is the MAX size readable
//GSgifTransfer1(((u32*)data) - 0x1000 + 4*qsize, 0x4000-qsize*16);
GSgifTransfer1((u32*)(data - 0x400 + qsize), 0x4000-qsize*16); GSgifTransfer1((u32*)(data - 0x400 + qsize), 0x4000-qsize*16);
//GSgifTransfer1((u32*)data, qsize);
ringposinc += qsize; ringposinc += qsize;
} }
break; break;
@ -863,6 +899,7 @@ int mtgsThreadObject::PrepDataPacket( GIF_PATH pathidx, const u8* srcdata, u32 s
gif->madr += (size - retval) * 16; gif->madr += (size - retval) * 16;
gif->qwc -= size - retval; gif->qwc -= size - retval;
} }
//if(retval < 0) DevCon::Notice("Increasing size from %x to %x path %x", params size, size-retval, pathidx+1);
size = size - retval; size = size - retval;
m_packet_size = size; m_packet_size = size;
size++; // takes into account our command qword. size++; // takes into account our command qword.

View File

@ -2061,7 +2061,33 @@ void _vuXGKICK(VURegs * VU)
ptr = (u32*)GET_VU_MEM(VU, 0); ptr = (u32*)GET_VU_MEM(VU, 0);
memcpy(&tempmem[temp], ptr, ((VU->VI[_Is_].US[0]*16) & 0x3fff)); memcpy(&tempmem[temp], ptr, ((VU->VI[_Is_].US[0]*16) & 0x3fff));
GSGIFTRANSFER1((u32*)&tempmem[0], 0); GSGIFTRANSFER1((u32*)&tempmem[0], 0);
} else*/ GSGIFTRANSFER1((u32*)VU->Mem, (VU->VI[_Is_].US[0]*16) & 0x3fff); } else*/
//DevCon::Notice("Addr %x", params VU->VI[_Is_].US[0] & 0x3fff);
if( mtgsThread != NULL )
{
u32* data = (u32*)((u8*)VU->Mem + ((VU->VI[_Is_].US[0]*16) & 0x3fff));
u32 size;
size = mtgsThread->PrepDataPacket( GIF_PATH_1, data, (0x4000-((VU->VI[_Is_].US[0]*16) & 0x3fff)) >> 4);
{
u8* pmem = mtgsThread->GetDataPacketPtr();
if((size << 4) > (u32)(0x4000-((VU->VI[_Is_].US[0]*16) & 0x3fff)))
{
//DevCon::Notice("addr + Size = 0x%x, transferring %x then doing %x", params ((VU->VI[_Is_].US[0]*16) & 0x3fff) + (size << 4), (0x4000-((VU->VI[_Is_].US[0]*16) & 0x3fff)) >> 4, size - (0x4000-((VU->VI[_Is_].US[0]*16) & 0x3fff) >> 4));
memcpy_aligned(pmem, (u8*)VU->Mem+((VU->VI[_Is_].US[0]*16) & 0x3fff), 0x4000-((VU->VI[_Is_].US[0]*16) & 0x3fff));
size -= (0x4000-((VU->VI[_Is_].US[0]*16) & 0x3fff)) >> 4;
//DevCon::Notice("Size left %x", params size);
pmem += 0x4000-((VU->VI[_Is_].US[0]*16) & 0x3fff);
memcpy_aligned(pmem, (u8*)VU->Mem, size<<4);
}
else
{
memcpy_aligned(pmem, (u8*)VU->Mem+((VU->VI[_Is_].US[0]*16) & 0x3fff), size<<4);
}
mtgsThread->SendDataPacket();
}
}else GSGIFTRANSFER1((u32*)VU->Mem, (VU->VI[_Is_].US[0]*16) & 0x3fff);
} }
void _vuXTOP(VURegs * VU) { void _vuXTOP(VURegs * VU) {

View File

@ -623,8 +623,8 @@ static void VIFunpack(u32 *data, vifCode *v, unsigned int size, const unsigned i
if(tempsize > (u32)(VIFdmanum ? 0x4000 : 0x1000)) if(tempsize > (u32)(VIFdmanum ? 0x4000 : 0x1000))
{ {
//DevCon::Notice("VIF%x Unpack ending %x > %x", params VIFdmanum, tempsize, VIFdmanum ? 0x4000 : 0x1000);
if(vifRegs->cycle.cl == 1 && ((u32)(VIFdmanum ? 0x4000 : 0x1000) + ((vifRegs->cycle.cl - vifRegs->cycle.wl) * 16)) == tempsize if(((vifRegs->cycle.cl != vifRegs->cycle.wl) && ((u32)(VIFdmanum ? 0x4000 : 0x1000) + ((vifRegs->cycle.cl - vifRegs->cycle.wl) * 16)) == tempsize)
|| tempsize == (u32)(VIFdmanum ? 0x4000 : 0x1000)) || tempsize == (u32)(VIFdmanum ? 0x4000 : 0x1000))
{ {
//Its a red herring! so ignore it! SSE unpacks will be much quicker //Its a red herring! so ignore it! SSE unpacks will be much quicker
@ -632,6 +632,7 @@ static void VIFunpack(u32 *data, vifCode *v, unsigned int size, const unsigned i
} }
else else
{ {
//DevCon::Notice("VIF%x Unpack ending %x > %x", params VIFdmanum, tempsize, VIFdmanum ? 0x4000 : 0x1000);
tempsize = size; tempsize = size;
size = 0; size = 0;
} }
@ -1678,7 +1679,7 @@ static __forceinline void vif1UNPACK(u32 *data)
return; return;
} }
} }
vif1FLUSH(); //vif1FLUSH();
vl = (vif1.cmd) & 0x3; vl = (vif1.cmd) & 0x3;
vn = (vif1.cmd >> 2) & 0x3; vn = (vif1.cmd >> 2) & 0x3;
@ -1890,7 +1891,7 @@ static int __fastcall Vif1TransDirectHL(u32 *data)
} }
else else
{ {
psHu32(GIF_STAT) &= ~0x80; psHu32(GIF_STAT) &= ~GIF_STAT_APATH2;
ret = vif1.tag.size; ret = vif1.tag.size;
vif1.tag.size = 0; vif1.tag.size = 0;
vif1.cmd = 0; vif1.cmd = 0;
@ -2057,7 +2058,7 @@ static void Vif1CMDFlush() // FLUSH/E/A
if((vif1.cmd & 0x7f) == 0x13) if((vif1.cmd & 0x7f) == 0x13)
{ {
if(Path3progress != 2 && gif->chcr & 0x100) // Gif is already transferring so wait for it. if((Path3progress != 2 || !vif1Regs->mskpath3) && gif->chcr & 0x100) // Gif is already transferring so wait for it.
{ {
vif1Regs->stat |= VIF1_STAT_VGW; vif1Regs->stat |= VIF1_STAT_VGW;
} }
@ -2089,7 +2090,7 @@ static void Vif1CMDSTRowCol() // STROW / STCOL
static void Vif1CMDMPGTransfer() // MPG static void Vif1CMDMPGTransfer() // MPG
{ {
int vifNum; int vifNum;
vif1FLUSH(); //vif1FLUSH();
vifNum = (u8)(vif1Regs->code >> 16); vifNum = (u8)(vif1Regs->code >> 16);
if (vifNum == 0) vifNum = 256; if (vifNum == 0) vifNum = 256;
@ -2113,15 +2114,15 @@ static void Vif1CMDDirectHL() // DIRECT/HL
//FIXME: This should have timing in both cases, see note below. //FIXME: This should have timing in both cases, see note below.
if((vif1.cmd & 0x7f) == 0x51) if((vif1.cmd & 0x7f) == 0x51)
{ {
if(gif->chcr & 0x100 /*&& Path3progress == 0*/) //PATH3 is in image mode, so wait for end of transfer if(gif->chcr & 0x100 && (!vif1Regs->mskpath3 || Path3progress != 2)) //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); //DevCon::Notice("DirectHL gif chcr %x gif qwc %x mskpth3 %x", params gif->chcr, gif->qwc, vif1Regs->mskpath3);
if(vif1Regs->mskpath3)vif1Regs->stat |= VIF1_STAT_VGW; /*if(vif1Regs->mskpath3)*/vif1Regs->stat |= VIF1_STAT_VGW;
else while(gif->chcr & 0x100) gsInterrupt(); //Hacky as hell (no timing) but Soul Calibur 3 doesnt want timing :( //else while(gif->chcr & 0x100) gsInterrupt(); //Hacky as hell (no timing) but Soul Calibur 3 doesnt want timing :(
} }
} }
psHu32(GIF_STAT) |= 0x80; psHu32(GIF_STAT) |= GIF_STAT_APATH2;
} }
static void Vif1CMDNull() // invalid opcode static void Vif1CMDNull() // invalid opcode
@ -2193,6 +2194,17 @@ int VIF1transfer(u32 *data, int size, int istag)
while (vif1.vifpacketsize > 0) while (vif1.vifpacketsize > 0)
{ {
if((vif1.cmd & 0x7f) == 0x51)
{
if(gif->chcr & 0x100 && (!vif1Regs->mskpath3 || Path3progress != 2)) //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);
/*if(vif1Regs->mskpath3)*/vif1Regs->stat |= VIF1_STAT_VGW;
//else while(gif->chcr & 0x100) gsInterrupt(); //Hacky as hell (no timing) but Soul Calibur 3 doesnt want timing :(
}
}
if(vif1Regs->stat & VIF1_STAT_VGW) break;
if (vif1.cmd) if (vif1.cmd)
{ {
vif1Regs->stat |= VIF1_STAT_VPS_T; //Decompression has started vif1Regs->stat |= VIF1_STAT_VPS_T; //Decompression has started
@ -2350,7 +2362,7 @@ void vif1TransferFromMemory()
} }
FreezeXMMRegs(0); FreezeXMMRegs(0);
if (vif1Regs->mskpath3 == 0)vif1Regs->stat &= ~0x1f000000;
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
vif1ch->qwc = 0; vif1ch->qwc = 0;
@ -2401,6 +2413,7 @@ __forceinline void vif1SetupTransfer()
case 1: //Normal (From memory) case 1: //Normal (From memory)
vif1.inprogress = 1; vif1.inprogress = 1;
vif1.done = true; vif1.done = true;
g_vifCycles = 2;
break; break;
case 2: //Chain case 2: //Chain
@ -2513,7 +2526,12 @@ __forceinline void vif1Interrupt()
} }
} }
if (vif1.inprogress) _VIF1chain(); if (vif1.inprogress)
{
_VIF1chain();
CPU_INT(1, g_vifCycles);
return;
}
if ((!vif1.done) || (vif1.inprogress & 0x1)) if ((!vif1.done) || (vif1.inprogress & 0x1))
{ {
@ -2543,7 +2561,7 @@ __forceinline void vif1Interrupt()
vif1ch->chcr &= ~0x100; vif1ch->chcr &= ~0x100;
g_vifCycles = 0; g_vifCycles = 0;
hwDmacIrq(DMAC_VIF1); hwDmacIrq(DMAC_VIF1);
vif1Regs->stat &= ~0x1F000000; // FQC=0 if(vif1ch->chcr & 0x1)vif1Regs->stat &= ~0x1F000000; // FQC=0
} }
void dmaVIF1() void dmaVIF1()
@ -2557,7 +2575,6 @@ void dmaVIF1()
g_vifCycles = 0; g_vifCycles = 0;
vif1.inprogress = 0; vif1.inprogress = 0;
vif1Regs->stat |= 0x10000000; // FQC=16
if (((psHu32(DMAC_CTRL) & 0xC) == 0x8)) // VIF MFIFO if (((psHu32(DMAC_CTRL) & 0xC) == 0x8)) // VIF MFIFO
{ {
@ -2591,6 +2608,9 @@ void dmaVIF1()
vif1.dmamode = 2; vif1.dmamode = 2;
} }
if(vif1.dmamode != 1)vif1Regs->stat |= 0x10000000; // FQC=16
else vif1Regs->stat |= min((u16)16, vif1ch->qwc) << 24; // FQC=16
// Chain Mode // Chain Mode
vif1.done = false; vif1.done = false;
vif1Interrupt(); vif1Interrupt();
@ -2705,7 +2725,7 @@ void vif1Write32(u32 mem, u32 value)
vif1Regs->stat = (vif1Regs->stat & ~VIF1_STAT_FDR) | (value & VIF1_STAT_FDR); vif1Regs->stat = (vif1Regs->stat & ~VIF1_STAT_FDR) | (value & VIF1_STAT_FDR);
if (vif1Regs->stat & VIF1_STAT_FDR) if (vif1Regs->stat & VIF1_STAT_FDR)
{ {
vif1Regs->stat |= 0x01000000; vif1Regs->stat |= 0x01000000; // FQC=1 - hack but it checks this is true before tranfer? (fatal frame)
} }
else else
{ {

View File

@ -1989,7 +1989,20 @@ void VU1XGKICK_MTGSTransfer(u32 *pMem, u32 addr)
//if( size > 0 ) //if( size > 0 )
{ {
u8* pmem = mtgsThread->GetDataPacketPtr(); u8* pmem = mtgsThread->GetDataPacketPtr();
/* if((size << 4) > (0x4000-(addr&0x3fff)))
{
//DevCon::Notice("addr + Size = 0x%x, transferring %x then doing %x", params (addr&0x3fff) + (size << 4), (0x4000-(addr&0x3fff)) >> 4, size - ((0x4000-(addr&0x3fff)) >> 4));
memcpy_aligned(pmem, (u8*)pMem+addr, 0x4000-(addr&0x3fff));
size -= (0x4000-(addr&0x3fff)) >> 4;
//DevCon::Notice("Size left %x", params size);
pmem += 0x4000-(addr&0x3fff);
memcpy_aligned(pmem, (u8*)pMem, size<<4);
}
else
{*/
memcpy_aligned(pmem, (u8*)pMem+addr, size<<4); memcpy_aligned(pmem, (u8*)pMem+addr, size<<4);
// }
mtgsThread->SendDataPacket(); mtgsThread->SendDataPacket();
} }
} }

View File

@ -1103,7 +1103,22 @@ void __fastcall mVU_XGKICK_(u32 addr) {
u32 *data = (u32*)(microVU1.regs->Mem + addr); u32 *data = (u32*)(microVU1.regs->Mem + addr);
u32 size = mtgsThread->PrepDataPacket(GIF_PATH_1, data, (0x4000-addr) >> 4); u32 size = mtgsThread->PrepDataPacket(GIF_PATH_1, data, (0x4000-addr) >> 4);
u8 *pDest = mtgsThread->GetDataPacketPtr(); u8 *pDest = mtgsThread->GetDataPacketPtr();
/*
if((size << 4) > (0x4000-(addr&0x3fff)))
{
//DevCon::Notice("addr + Size = 0x%x, transferring %x then doing %x", params (addr&0x3fff) + (size << 4), (0x4000-(addr&0x3fff)) >> 4, size - ((0x4000-(addr&0x3fff)) >> 4));
memcpy_aligned(pDest, microVU1.regs->Mem + addr, 0x4000-(addr&0x3fff));
size -= (0x4000-(addr&0x3fff)) >> 4;
//DevCon::Notice("Size left %x", params size);
pDest += 0x4000-(addr&0x3fff);
memcpy_aligned(pDest, microVU1.regs->Mem, size<<4);
}
else
{
*/
memcpy_aligned(pDest, microVU1.regs->Mem + addr, size<<4); memcpy_aligned(pDest, microVU1.regs->Mem + addr, size<<4);
// }
mtgsThread->SendDataPacket(); mtgsThread->SendDataPacket();
} }