* Converted SPR.cpp and hwMFIFOWrite to use memcpy_qwc in the place of memcpy_fast.

* Fix a bug in my merge of the new MTGS code that caused crashes on some games (PATH1 queue bug).
* Added assertion checks to hwMFIFOWrite for qwc alignment and a SPR_LOG for null ringbuffer addresses (if a game specifies an invalid physical address).

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@3533 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2010-07-19 05:40:35 +00:00
parent 856ffe4c65
commit 575e1ceb46
7 changed files with 44 additions and 53 deletions

View File

@ -693,11 +693,12 @@ static __forceinline tDMA_TAG *dmaGetAddr(u32 addr, bool write)
} }
} }
void hwIntcIrq(int n); extern void hwIntcIrq(int n);
void hwDmacIrq(int n); extern void hwDmacIrq(int n);
bool hwDmacSrcChainWithStack(DMACh *dma, int id); extern bool hwMFIFOWrite(u32 addr, const u128* data, uint size_qwc);
bool hwDmacSrcChain(DMACh *dma, int id); extern bool hwDmacSrcChainWithStack(DMACh *dma, int id);
extern bool hwDmacSrcChain(DMACh *dma, int id);
extern void intcInterrupt(); extern void intcInterrupt();
extern void dmacInterrupt(); extern void dmacInterrupt();

View File

@ -127,39 +127,35 @@ void hwDmacIrq(int n)
} }
// Write 'size' bytes to memory address 'addr' from 'data'. // Write 'size' bytes to memory address 'addr' from 'data'.
bool hwMFIFOWrite(u32 addr, u8 *data, u32 size) __releaseinline bool hwMFIFOWrite(u32 addr, const u128* data, uint qwc)
{ {
u32 msize = dmacRegs->rbor.ADDR + dmacRegs->rbsr.RMSK + 16; // all FIFO addresses should always be QWC-aligned.
u8 *dst; pxAssume((dmacRegs->rbor.ADDR & 15) == 0);
pxAssume((addr & 15) == 0);
addr = dmacRegs->rbor.ADDR + (addr & dmacRegs->rbsr.RMSK); // DMAC Address resolution: FIFO can be placed anywhere in the *physical* memory map
// for the PS2. Its probably a serious error for a PS2 app to have the buffer cross
// valid/invalid page areas of ram, so realistically we only need to test the base address
// of the FIFO for address validity.
// Check if the transfer should wrap around the ring buffer if (u128* dst = (u128*)PSM(dmacRegs->rbor.ADDR))
if ((addr+size) >= msize) { {
int s1 = msize - addr; const u32 ringsize = (dmacRegs->rbsr.RMSK / 16) + 1;
int s2 = size - s1; pxAssertMsg( PSM(dmacRegs->rbor.ADDR+ringsize-1) != NULL, "Scratchpad/MFIFO ringbuffer spans into invalid (unmapped) physical memory!" );
uint startpos = (addr & dmacRegs->rbsr.RMSK)/16;
// it does, so first copy 's1' bytes from 'data' to 'addr' MemCopy_WrappedDest( data, dst, startpos, ringsize, qwc );
dst = (u8*)PSM(addr);
if (dst == NULL) return false;
memcpy_fast(dst, data, s1);
// and second copy 's2' bytes from '&data[s1]' to 'maddr'
dst = (u8*)PSM(dmacRegs->rbor.ADDR);
if (dst == NULL) return false;
memcpy_fast(dst, &data[s1], s2);
} }
else { else
// it doesn't, so just copy 'size' bytes from 'data' to 'addr' {
dst = (u8*)PSM(addr); SPR_LOG( "Scratchpad/MFIFO: invalid base physical address: 0x%08x", dmacRegs->rbor.ADDR );
if (dst == NULL) return false; pxFailDev( wxsFormat( L"Scratchpad/MFIFO: Invalid base physical address: 0x%08x", dmacRegs->rbor.ADDR) );
memcpy_fast(dst, data, size); return false;
} }
return true; return true;
} }
bool hwDmacSrcChainWithStack(DMACh *dma, int id) { __releaseinline bool hwDmacSrcChainWithStack(DMACh *dma, int id) {
switch (id) { switch (id) {
case TAG_REFE: // Refe - Transfer Packet According to ADDR field case TAG_REFE: // Refe - Transfer Packet According to ADDR field
//End Transfer //End Transfer

View File

@ -312,8 +312,6 @@ extern void __fastcall hwWrite64_generic( u32 mem, const mem64_t* srcval );
extern void __fastcall hwWrite128_generic(u32 mem, const mem128_t *srcval); extern void __fastcall hwWrite128_generic(u32 mem, const mem128_t *srcval);
bool hwMFIFOWrite(u32 addr, u8 *data, u32 size);
extern const int rdram_devices; extern const int rdram_devices;
extern int rdram_sdevid; extern int rdram_sdevid;

View File

@ -114,14 +114,12 @@ extern u8 *psMHW;
#define psERu32(mem) (*(u32*)&PS2MEM_EROM[(mem) & 0x3ffff]) #define psERu32(mem) (*(u32*)&PS2MEM_EROM[(mem) & 0x3ffff])
#define psERu64(mem) (*(u64*)&PS2MEM_EROM[(mem) & 0x3ffff]) #define psERu64(mem) (*(u64*)&PS2MEM_EROM[(mem) & 0x3ffff])
#define psSs8(mem) (*(s8 *)&PS2MEM_SCRATCH[(mem) & 0x3fff]) #define psSs32(mem) (*(s32 *)&PS2MEM_SCRATCH[(mem) & 0x3fff])
#define psSs16(mem) (*(s16*)&PS2MEM_SCRATCH[(mem) & 0x3fff]) #define psSs64(mem) (*(s64 *)&PS2MEM_SCRATCH[(mem) & 0x3fff])
#define psSs32(mem) (*(s32*)&PS2MEM_SCRATCH[(mem) & 0x3fff]) #define psSs128(mem) (*(s128*)&PS2MEM_SCRATCH[(mem) & 0x3fff])
#define psSs64(mem) (*(s64*)&PS2MEM_SCRATCH[(mem) & 0x3fff]) #define psSu32(mem) (*(u32 *)&PS2MEM_SCRATCH[(mem) & 0x3fff])
#define psSu8(mem) (*(u8 *)&PS2MEM_SCRATCH[(mem) & 0x3fff]) #define psSu64(mem) (*(u64 *)&PS2MEM_SCRATCH[(mem) & 0x3fff])
#define psSu16(mem) (*(u16*)&PS2MEM_SCRATCH[(mem) & 0x3fff]) #define psSu128(mem) (*(u128*)&PS2MEM_SCRATCH[(mem) & 0x3fff])
#define psSu32(mem) (*(u32*)&PS2MEM_SCRATCH[(mem) & 0x3fff])
#define psSu64(mem) (*(u64*)&PS2MEM_SCRATCH[(mem) & 0x3fff])
#define psH_DMACh(mem) (*(DMACh*)&PS2MEM_HW[(mem) & 0xffff]) #define psH_DMACh(mem) (*(DMACh*)&PS2MEM_HW[(mem) & 0xffff])
extern void memAlloc(); extern void memAlloc();

View File

@ -64,14 +64,14 @@ int _SPR0chain()
else else
mfifotransferred += spr0->qwc; mfifotransferred += spr0->qwc;
hwMFIFOWrite(spr0->madr, &psSu8(spr0->sadr), spr0->qwc << 4); hwMFIFOWrite(spr0->madr, &psSu128(spr0->sadr), spr0->qwc);
spr0->madr += spr0->qwc << 4; spr0->madr += spr0->qwc << 4;
spr0->madr = dmacRegs->rbor.ADDR + (spr0->madr & dmacRegs->rbsr.RMSK); spr0->madr = dmacRegs->rbor.ADDR + (spr0->madr & dmacRegs->rbsr.RMSK);
break; break;
case NO_MFD: case NO_MFD:
case MFD_RESERVED: case MFD_RESERVED:
memcpy_fast((u8*)pMem, &psSu8(spr0->sadr), spr0->qwc << 4); memcpy_qwc(pMem, &psSu128(spr0->sadr), spr0->qwc);
// clear VU mem also! // clear VU mem also!
TestClearVUs(spr0->madr, spr0->qwc << 2); // Wtf is going on here? AFAIK, only VIF should affect VU micromem (cottonvibes) TestClearVUs(spr0->madr, spr0->qwc << 2); // Wtf is going on here? AFAIK, only VIF should affect VU micromem (cottonvibes)
@ -114,7 +114,7 @@ void _SPR0interleave()
{ {
case MFD_VIF1: case MFD_VIF1:
case MFD_GIF: case MFD_GIF:
hwMFIFOWrite(spr0->madr, &psSu8(spr0->sadr), spr0->qwc << 4); hwMFIFOWrite(spr0->madr, &psSu128(spr0->sadr), spr0->qwc);
mfifotransferred += spr0->qwc; mfifotransferred += spr0->qwc;
break; break;
@ -122,7 +122,7 @@ void _SPR0interleave()
case MFD_RESERVED: case MFD_RESERVED:
// clear VU mem also! // clear VU mem also!
TestClearVUs(spr0->madr, spr0->qwc << 2); TestClearVUs(spr0->madr, spr0->qwc << 2);
memcpy_fast((u8*)pMem, &psSu8(spr0->sadr), spr0->qwc << 4); memcpy_qwc(pMem, &psSu128(spr0->sadr), spr0->qwc);
break; break;
} }
spr0->sadr += spr0->qwc * 16; spr0->sadr += spr0->qwc * 16;
@ -273,11 +273,10 @@ void dmaSPR0() // fromSPR
SPRFROMinterrupt(); SPRFROMinterrupt();
} }
__forceinline static void SPR1transfer(u32 *data, int size) __forceinline static void SPR1transfer(const void* data, int qwc)
{ {
memcpy_fast(&psSu8(spr1->sadr), (u8*)data, size << 2); memcpy_qwc(&psSu128(spr1->sadr), data, qwc);
spr1->sadr += qwc * 16;
spr1->sadr += size << 2;
} }
int _SPR1chain() int _SPR1chain()
@ -289,8 +288,8 @@ int _SPR1chain()
pMem = SPRdmaGetAddr(spr1->madr, false); pMem = SPRdmaGetAddr(spr1->madr, false);
if (pMem == NULL) return -1; if (pMem == NULL) return -1;
SPR1transfer((u32*)pMem, spr1->qwc << 2); SPR1transfer(pMem, spr1->qwc);
spr1->madr += spr1->qwc << 4; spr1->madr += spr1->qwc * 16;
return (spr1->qwc); return (spr1->qwc);
} }
@ -317,7 +316,7 @@ void _SPR1interleave()
spr1->qwc = std::min(tqwc, qwc); spr1->qwc = std::min(tqwc, qwc);
qwc -= spr1->qwc; qwc -= spr1->qwc;
pMem = SPRdmaGetAddr(spr1->madr, false); pMem = SPRdmaGetAddr(spr1->madr, false);
memcpy_fast(&psSu8(spr1->sadr), (u8*)pMem, spr1->qwc << 4); memcpy_qwc(&psSu128(spr1->sadr), pMem, spr1->qwc);
spr1->sadr += spr1->qwc * 16; spr1->sadr += spr1->qwc * 16;
spr1->madr += (sqwc + spr1->qwc) * 16; spr1->madr += (sqwc + spr1->qwc) * 16;
} }
@ -365,7 +364,7 @@ void _dmaSPR1() // toSPR work function
if (spr1->chcr.TTE) if (spr1->chcr.TTE)
{ {
SPR_LOG("SPR TTE: %x_%x\n", ptag[3]._u32, ptag[2]._u32); SPR_LOG("SPR TTE: %x_%x\n", ptag[3]._u32, ptag[2]._u32);
SPR1transfer((u32*)ptag, 4); //Transfer Tag SPR1transfer(ptag, 1); //Transfer Tag
} }
SPR_LOG("spr1 dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx taddr=%lx saddr=%lx", SPR_LOG("spr1 dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx taddr=%lx saddr=%lx",

View File

@ -529,7 +529,7 @@ __forceinline int GIFPath::ParseTagQuick(GIF_PATH pathidx, const u8* pMem, u32 s
return size; return size;
} }
__forceinline void MemCopy_WrappedDest( const u128* src, u128* destBase, uint& destStart, uint destSize, uint len ) __releaseinline void MemCopy_WrappedDest( const u128* src, u128* destBase, uint& destStart, uint destSize, uint len )
{ {
uint endpos = destStart + len; uint endpos = destStart + len;
if( endpos < destSize ) if( endpos < destSize )
@ -547,7 +547,7 @@ __forceinline void MemCopy_WrappedDest( const u128* src, u128* destBase, uint& d
} }
} }
__forceinline void MemCopy_WrappedSrc( const u128* srcBase, uint& srcStart, uint srcSize, u128* dest, uint len ) __releaseinline void MemCopy_WrappedSrc( const u128* srcBase, uint& srcStart, uint srcSize, u128* dest, uint len )
{ {
uint endpos = srcStart + len; uint endpos = srcStart + len;
if( endpos < srcSize ) if( endpos < srcSize )

View File

@ -1134,7 +1134,6 @@ void __fastcall mVU_XGKICK_(u32 addr) {
} }
else { else {
memcpy_qwc(pDest, microVU1.regs->Mem + (addr*16), size); memcpy_qwc(pDest, microVU1.regs->Mem + (addr*16), size);
Path1WritePos += size;
} }
//if(!gifRegs->stat.P1Q) CPU_INT(28, 128); //if(!gifRegs->stat.P1Q) CPU_INT(28, 128);
gifRegs->stat.P1Q = true; gifRegs->stat.P1Q = true;