gifTransferDummy() now handles path2 and path3 transfers.

Hopefully doesn't break anything :)

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1827 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
cottonvibes 2009-09-15 06:24:41 +00:00
parent 77639783ea
commit bd3601b2d6
5 changed files with 50 additions and 268 deletions

View File

@ -160,6 +160,9 @@ void __fastcall WriteFIFO_page_5(u32 mem, const mem128_t *value)
assert( ret == 0 ); // vif stall code not implemented assert( ret == 0 ); // vif stall code not implemented
} }
// Dummy GIF-TAG Packet to Guarantee Count = 1
PCSX2_ALIGNED16(u32 nloop0_packet[4]) = {0x8000, 0, 0, 0};
void __fastcall WriteFIFO_page_6(u32 mem, const mem128_t *value) void __fastcall WriteFIFO_page_6(u32 mem, const mem128_t *value)
{ {
jASSUME( (mem >= GIF_FIFO) && (mem < IPUout_FIFO) ); jASSUME( (mem >= GIF_FIFO) && (mem < IPUout_FIFO) );
@ -172,8 +175,7 @@ void __fastcall WriteFIFO_page_6(u32 mem, const mem128_t *value)
psHu64(0x6008) = value[1]; psHu64(0x6008) = value[1];
FreezeRegs(1); FreezeRegs(1);
const uint count = mtgsThread->PrepDataPacket( GIF_PATH_3, value, 1 ); const uint count = mtgsThread->PrepDataPacket(GIF_PATH_3, nloop0_packet, 1);
jASSUME( count == 1 );
u64* data = (u64*)mtgsThread->GetDataPacketPtr(); u64* data = (u64*)mtgsThread->GetDataPacketPtr();
data[0] = value[0]; data[0] = value[0];
data[1] = value[1]; data[1] = value[1];

View File

@ -89,28 +89,12 @@ struct GIFTAG
struct GIFPath struct GIFPath
{ {
GIFTAG tag; GIFTAG tag;
u32 curreg; u32 curreg; // Not Used Anymore
u32 _pad[3]; u32 _pad[3];
u8 regs[16]; u8 regs[16];
__forceinline void PrepRegs(); __forceinline void PrepRegs(bool doPrep);
void SetTag(const void* mem, bool doPrepRegs); __forceinline void SetTag(const void* mem);
u32 GetReg();
__forceinline bool StepReg()
{
if((++curreg & 0xf) == tag.nreg)
{
curreg = 0;
if(--tag.nloop == 0)
{
return false;
}
}
return true;
}
}; };
@ -230,9 +214,8 @@ public:
// Used primarily for plugin startup/shutdown. // Used primarily for plugin startup/shutdown.
void WaitGS(); void WaitGS();
int PrepDataPacket( GIF_PATH pathidx, const u8* srcdata, u32 size ); int PrepDataPacket( GIF_PATH pathidx, const u8* srcdata, u32 size );
int PrepDataPacket( GIF_PATH pathidx, const u32* srcdata, u32 size ); int PrepDataPacket( GIF_PATH pathidx, const u32* srcdata, u32 size );
int PrepDataPacket( GIF_PATH pathidx, const u64* srcdata, u32 size );
void SendDataPacket(); void SendDataPacket();
void SendSimplePacket( GS_RINGTYPE type, int data0, int data1, int data2 ); void SendSimplePacket( GS_RINGTYPE type, int data0, int data1, int data2 );
@ -257,8 +240,8 @@ 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.
int _gifTransferDummy ( GIF_PATH pathidx, const u8 *pMem, u32 size ); int gifTransferDummy(GIF_PATH pathidx, const u8 *pMem, u32 size);
int _gifTransferDummy2( 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

@ -98,8 +98,7 @@ static u32 WRITERING_DMA(u32 *pMem, u32 qwc)
{ {
psHu32(GIF_STAT) |= GIF_STAT_APATH3 | GIF_STAT_OPH; psHu32(GIF_STAT) |= GIF_STAT_APATH3 | GIF_STAT_OPH;
int sizetoread = qwc; int size = mtgsThread->PrepDataPacket(GIF_PATH_3, pMem, qwc);
sizetoread = mtgsThread->PrepDataPacket( GIF_PATH_3, pMem, qwc );
u8* pgsmem = mtgsThread->GetDataPacketPtr(); u8* pgsmem = mtgsThread->GetDataPacketPtr();
/* check if page of endmem is valid (dark cloud2) */ /* check if page of endmem is valid (dark cloud2) */
@ -111,10 +110,10 @@ static u32 WRITERING_DMA(u32 *pMem, u32 qwc)
// fixed? PrepDataPacket now returns the actual size of the packet. // fixed? PrepDataPacket now returns the actual size of the packet.
// VIF handles scratchpad wrapping also, so this code shouldn't be needed anymore. // VIF handles scratchpad wrapping also, so this code shouldn't be needed anymore.
memcpy_aligned(pgsmem, pMem, sizetoread<<4); memcpy_aligned(pgsmem, pMem, size<<4);
mtgsThread->SendDataPacket(); mtgsThread->SendDataPacket();
return sizetoread; return size;
} }
int _GIFchain() int _GIFchain()
@ -135,7 +134,7 @@ int _GIFchain()
return -1; return -1;
} }
return (WRITERING_DMA(pMem, qwc)); return WRITERING_DMA(pMem, qwc);
} }
static __forceinline void GIFchain() static __forceinline void GIFchain()
@ -384,7 +383,6 @@ static __forceinline int mfifoGIFrbTransfer()
/* it doesn't, so just transfer 'qwc*16' words from 'gif->madr' to GS */ /* it doesn't, so just transfer 'qwc*16' words from 'gif->madr' to GS */
src = (u32*)PSM(gif->madr); src = (u32*)PSM(gif->madr);
if (src == NULL) return -1; if (src == NULL) return -1;
mfifoqwc = WRITERING_DMA(src, mfifoqwc); mfifoqwc = WRITERING_DMA(src, mfifoqwc);
gif->madr = psHu32(DMAC_RBOR) + (gif->madr & psHu32(DMAC_RBSR)); gif->madr = psHu32(DMAC_RBOR) + (gif->madr & psHu32(DMAC_RBSR));
} }
@ -410,7 +408,6 @@ static __forceinline int mfifoGIFchain()
int mfifoqwc = gif->qwc; int mfifoqwc = gif->qwc;
u32 *pMem = (u32*)dmaGetAddr(gif->madr); u32 *pMem = (u32*)dmaGetAddr(gif->madr);
if (pMem == NULL) return -1; if (pMem == NULL) return -1;
mfifoqwc = WRITERING_DMA(pMem, mfifoqwc); mfifoqwc = WRITERING_DMA(pMem, mfifoqwc);
mfifocycles += (mfifoqwc) * 2; /* guessing */ mfifocycles += (mfifoqwc) * 2; /* guessing */
} }

View File

@ -59,8 +59,9 @@ using namespace std;
// registers are stored as a sequence of 4 bit values in the // registers are stored as a sequence of 4 bit values in the
// upper 64 bits of the GIFTAG. That sucks for us, so we unpack // upper 64 bits of the GIFTAG. That sucks for us, so we unpack
// them into an 8 bit array. // them into an 8 bit array.
__forceinline void GIFPath::PrepRegs() __forceinline void GIFPath::PrepRegs(bool doPrep = 1)
{ {
if (!doPrep) return;
int loopEnd = ((tag.nreg-1)&0xf) + 1; int loopEnd = ((tag.nreg-1)&0xf) + 1;
u32 tempreg = tag.regs[0]; u32 tempreg = tag.regs[0];
@ -71,17 +72,10 @@ __forceinline void GIFPath::PrepRegs()
} }
} }
void GIFPath::SetTag(const void* mem, bool doPrepRegs = 1) __forceinline void GIFPath::SetTag(const void* mem)
{ {
tag = *((GIFTAG*)mem); tag = *((GIFTAG*)mem);
curreg = 0; curreg = 0;
if (doPrepRegs) PrepRegs();
}
u32 GIFPath::GetReg()
{
return regs[curreg];
} }
static void _mtgsFreezeGIF( SaveState& state, GIFPath (&paths)[3] ) static void _mtgsFreezeGIF( SaveState& state, GIFPath (&paths)[3] )
@ -235,26 +229,28 @@ void mtgsThreadObject::Reset()
memzero_obj( m_path ); memzero_obj( m_path );
} }
#define incPmem(x) { \ #define incPmem(x) { \
if ((pMem + x) >= ptrEnd) pMem = (pMem + x) - 0x4000; \ pMem += x; \
else pMem += x; \ size += x; \
size += x; \ if ((pathidx==GIF_PATH_1)&&(pMem>=vuMemEnd)) pMem -= 0x4000; \
} }
__forceinline int mtgsThreadObject::_gifTransferDummy2(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];
u8* ptrEnd = (u8*)pMem + (size<<4); // End of VU Mem u8* vuMemEnd = (u8*)pMem + (size<<4); // End of VU Mem
u32 finish = (pathidx == GIF_PATH_1) ? 0x4000 : (size<<4);
bool EOP = 0; bool EOP = 0;
bool hasRegAD = 0; bool hasRegAD = 0;
size = 0; size = 0;
while(!EOP && size < 0x4000) { while(!EOP && size < finish) {
path.SetTag(pMem, !path.tag.flg); path.SetTag(pMem);
EOP = path.tag.eop; path.PrepRegs(!path.tag.flg);
int numRegs = ((path.tag.nreg-1)&0xf)+1; EOP = (pathidx == GIF_PATH_2) ? 0 : path.tag.eop;
incPmem(16); incPmem(16);
if (!path.tag.nloop) continue; if (!path.tag.nloop) continue;
int numRegs = ((path.tag.nreg-1)&0xf)+1;
switch(path.tag.flg) { switch(path.tag.flg) {
case GIF_FLG_PACKED: case GIF_FLG_PACKED:
for (u32 i = 0; i < path.tag.nloop; i++) { for (u32 i = 0; i < path.tag.nloop; i++) {
@ -262,12 +258,13 @@ __forceinline int mtgsThreadObject::_gifTransferDummy2(GIF_PATH pathidx, const u
if (path.regs[j] == 0x0e) { if (path.regs[j] == 0x0e) {
const int handler = pMem[8]; const int handler = pMem[8];
if (handler >= 0x60 && handler < 0x63) { if (handler >= 0x60 && handler < 0x63) {
//DevCon::Status("GIF Tag Signal"); //DevCon::Status("GIF Tag Interrupt");
s_GSHandlers[handler&0x3]((const u32*)pMem); s_GSHandlers[handler&0x3]((const u32*)pMem);
} }
hasRegAD = 1; hasRegAD = 1;
} }
incPmem(16); incPmem(16);
if (size >= finish) goto endLoop;
} }
if (!hasRegAD) { // Optimization: No Need to Loop if (!hasRegAD) { // Optimization: No Need to Loop
incPmem((16 * numRegs * (path.tag.nloop-1))); incPmem((16 * numRegs * (path.tag.nloop-1)));
@ -285,23 +282,25 @@ __forceinline int mtgsThreadObject::_gifTransferDummy2(GIF_PATH pathidx, const u
break; break;
} }
} }
endLoop:
if (size > finish) size = finish;
if (pathidx == GIF_PATH_3) {
gif->madr += size;
gif->qwc -= (size/16);
Path3progress = STOPPED_MODE;
}
return (size / 16); return (size / 16);
} }
// 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.
// size - size of the packet in simd128's __forceinline int 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];
/* 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;
if( profStartPtr == 0 ) if (profStartPtr == 0) {
{
__asm __asm
{ {
__beginfunc: __beginfunc:
@ -312,189 +311,8 @@ __forceinline int mtgsThreadObject::_gifTransferDummy( GIF_PATH pathidx, const u
} }
#endif #endif
while(size > 0) int retSize = _gifTransferDummy(pathidx, pMem, size);
{
if (path.tag.nloop == 0)
{
path.SetTag( pMem );
pMem += sizeof(GIFTAG);
--size;
if (pathidx == 2)
{
if (path.tag.flg != GIF_FLG_IMAGE)
Path3progress = TRANSFER_MODE; //Other mode (but not stopped, I guess?)
else
Path3progress = IMAGE_MODE; //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)
{
// int transize = 0;
// 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.
/*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;
if((path.tag.nloop * numregs) > (size * ((path.tag.flg == 1) ? 2 : 1)))
{
path.tag.nloop = 0;
return ++size;
}
}
}
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:
do
{
if( path.GetReg() == 0xe )
{
const int handler = pMem[8];
if(handler >= 0x60 && handler < 0x63)
s_GSHandlers[handler&0x3]((const u32*)pMem);
}
size--;
pMem += 16; // 128 bits! //sizeof(GIFPackedReg);
}
while(path.StepReg() && size > 0);
break;
case GIF_FLG_REGLIST:
size *= 2;
do
{
const int handler = path.GetReg();
if(handler >= 0x60 && handler < 0x63)
s_GSHandlers[handler&0x3]((const u32*)pMem);
size--;
pMem += 8; //sizeof(GIFReg); -- 64 bits!
}
while(path.StepReg() && size > 0);
if(size & 1) pMem += 8; //sizeof(GIFReg);
size /= 2;
break;
case GIF_FLG_IMAGE2: // hmmm
assert(0);
path.tag.nloop = 0;
break;
case GIF_FLG_IMAGE:
{
int len = (int)min(size, path.tag.nloop);
pMem += len * 16;
path.tag.nloop -= len;
size -= len;
}
break;
jNO_DEFAULT;
}
}
if(path.tag.nloop == 0)
{
if(path.tag.eop)
{
if(pathidx != 1)
{
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", path.tag.nloop, path.tag.eop, path.tag.flg);
size = 0x400;
pMem -= 0x4000;
path1loop = true;
}*/
}
/*else if(size == 0 && pathidx == 0)
{
if(path1loop == true) return size - 0x400;
//DevCon::Notice("Looping Nloop %x, Eop %x, FLG %x", path.tag.nloop, path.tag.eop, path.tag.flg);
size = 0x400;
pMem -= 0x4000;
path1loop = true;
}*/
}
/*else if(size == 0 && pathidx == 0)
{
if(path1loop == true) return size - 0x400;
//DevCon::Notice("Looping Nloop %x, Eop %x, FLG %x", path.tag.nloop, path.tag.eop, path.tag.flg);
size = 0x400;
pMem -= 0x4000;
path1loop = true;
}*/
}
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)
{
path.tag.nloop = 0;
DevCon::Write( "path1 hack! " );
// This means that the giftag data got screwly somewhere
// 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 = STOPPED_MODE;
//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 #ifdef PCSX2_GSRING_SAMPLING_STATS
__asm __asm
{ {
@ -502,7 +320,7 @@ __forceinline int mtgsThreadObject::_gifTransferDummy( GIF_PATH pathidx, const u
nop; nop;
} }
#endif #endif
return size; return retSize;
} }
void mtgsThreadObject::PostVsyncEnd( bool updategs ) void mtgsThreadObject::PostVsyncEnd( bool updategs )
@ -848,11 +666,6 @@ void mtgsThreadObject::SendDataPacket()
//m_PacketLocker.Unlock(); //m_PacketLocker.Unlock();
} }
int mtgsThreadObject::PrepDataPacket( GIF_PATH pathidx, const u64* srcdata, u32 size )
{
return PrepDataPacket( pathidx, (u8*)srcdata, size );
}
int mtgsThreadObject::PrepDataPacket( GIF_PATH pathidx, const u32* srcdata, u32 size ) int mtgsThreadObject::PrepDataPacket( GIF_PATH pathidx, const u32* srcdata, u32 size )
{ {
return PrepDataPacket( pathidx, (u8*)srcdata, size ); return PrepDataPacket( pathidx, (u8*)srcdata, size );
@ -947,23 +760,8 @@ int mtgsThreadObject::PrepDataPacket( GIF_PATH pathidx, const u8* srcdata, u32 s
size = (size+15)&(~15); size = (size+15)&(~15);
}*/ }*/
if (pathidx != GIF_PATH_1) { m_packet_size = gifTransferDummy(pathidx, srcdata, size);
// retval has the amount of data *not* processed, so we only need to reserve size = m_packet_size + 1; // takes into account our command qword.
// enough room for size - retval:
int retval = _gifTransferDummy( pathidx, srcdata, size );
if(pathidx == GIF_PATH_3)
{
gif->madr += (size - retval) * 16;
gif->qwc -= size - retval;
}
//if(retval < 0) DevCon::Notice("Increasing size from %x to %x path %x", size, size-retval, pathidx+1);
size = size - retval;
}
else size = _gifTransferDummy2(pathidx, srcdata, size);
m_packet_size = size;
size++; // takes into account our command qword.
if( writepos + size < m_RingBufferSize ) if( writepos + size < m_RingBufferSize )
{ {

View File

@ -1854,6 +1854,9 @@ static int __fastcall Vif1TransMPG(u32 *data)
} }
} }
// Dummy GIF-TAG Packet to Guarantee Count = 1
PCSX2_ALIGNED16_EXTERN(u32 nloop0_packet[4]);
static int __fastcall Vif1TransDirectHL(u32 *data) static int __fastcall Vif1TransDirectHL(u32 *data)
{ {
int ret = 0; int ret = 0;
@ -1884,8 +1887,7 @@ static int __fastcall Vif1TransDirectHL(u32 *data)
FreezeRegs(1); FreezeRegs(1);
// copy 16 bytes the fast way: // copy 16 bytes the fast way:
const u64* src = (u64*)splittransfer[0]; const u64* src = (u64*)splittransfer[0];
const uint count = mtgsThread->PrepDataPacket(GIF_PATH_2, src, 1); const uint count = mtgsThread->PrepDataPacket(GIF_PATH_2, nloop0_packet, 1);
jASSUME(count == 1);
u64* dst = (u64*)mtgsThread->GetDataPacketPtr(); u64* dst = (u64*)mtgsThread->GetDataPacketPtr();
dst[0] = src[0]; dst[0] = src[0];
dst[1] = src[1]; dst[1] = src[1];