Yay! Fixed a memory corruption bug in the SuperVU that caused several "VU-intense" games to crash randomly: Tekken 5, Persona 4, and God of War to name a few.

Changed the Hw FiFo to use what should be a more correct register addressing scheme.  The entire contents of each page of the FIFO is mirrored into the lowest register(s).  For example, any address between 0x10006010 and 0x10006ff0 should always be treated as address 0x10006000.

Code cleanups and minor optimizations to hw.cpp, FiFo.cpp, and gs.cpp.

Added some additional utility functions to the Path namespace, for splitting paths into files/folders parts.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@451 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2009-02-08 06:29:43 +00:00
parent 7e8aeba9c2
commit 63d5ce867b
12 changed files with 921 additions and 359 deletions

View File

@ -28,125 +28,194 @@
//////////////////////////////////////////////////////////////////////////
/////////////////////////// Quick & dirty FIFO :D ////////////////////////
//////////////////////////////////////////////////////////////////////////
// ** NOTE: cannot use XMM/MMX regs **
// Notes on FIFO implementation
//
// The FIFO consists of four separate pages of HW register memory, each mapped to a
// PS2 device. They are listed as follows:
//
// 0x4000 - 0x5000 : VIF0 (all registers map to 0x4000)
// 0x5000 - 0x6000 : VIF1 (all registers map to 0x5000)
// 0x6000 - 0x7000 : GS (all registers map to 0x6000)
// 0x7000 - 0x8000 : IPU (registers map to 0x7000 and 0x7010, respectively)
extern int FIFOto_write(u32* pMem, int size);
extern void FIFOfrom_readsingle(void *value);
extern int g_nIPU0Data;
extern u8* g_pIPU0Pointer;
extern int FOreadpos;
// NOTE: cannot use XMM/MMX regs
void ReadFIFO(u32 mem, u64 *out) {
if ((mem >= 0x10004000) && (mem < 0x10005000)) {
VIF_LOG("ReadFIFO VIF0 0x%08X\n", mem);
out[0] = psHu64(mem );
out[1] = psHu64(mem+8);
return;
} else
if ((mem >= 0x10005000) && (mem < 0x10006000)) {
#ifdef PCSX2_DEVBUILD
VIF_LOG("ReadFIFO VIF1 0x%08X\n", mem);
//////////////////////////////////////////////////////////////////////////
// ReadFIFO Pages
if( vif1Regs->stat & (VIF1_STAT_INT|VIF1_STAT_VSS|VIF1_STAT_VIS|VIF1_STAT_VFS) ) {
SysPrintf("reading from vif1 fifo when stalled\n");
}
#endif
void __fastcall ReadFIFO_page_4(u32 mem, u64 *out)
{
jASSUME( (mem >= 0x10004000) && (mem < 0x10005000) );
if (vif1Regs->stat & 0x800000) {
if (--psHu32(D1_QWC) == 0) {
vif1Regs->stat&= ~0x1f000000;
} else {
}
}
out[0] = psHu64(mem );
out[1] = psHu64(mem+8);
return;
} else if( (mem&0xfffff010) == 0x10007000) {
VIF_LOG("ReadFIFO/VIF0 0x%08X\n", mem);
//out[0] = psHu64(mem );
//out[1] = psHu64(mem+8);
if( g_nIPU0Data > 0 ) {
out[0] = psHu64(0x4000);
out[1] = psHu64(0x4008);
}
void __fastcall ReadFIFO_page_5(u32 mem, u64 *out)
{
jASSUME( (mem >= 0x10005000) && (mem < 0x10006000) );
VIF_LOG("ReadFIFO/VIF1, addr=0x%08X\n", mem);
if( vif1Regs->stat & (VIF1_STAT_INT|VIF1_STAT_VSS|VIF1_STAT_VIS|VIF1_STAT_VFS) )
DevCon::Notice( "Reading from vif1 fifo when stalled" );
if (vif1Regs->stat & 0x800000)
{
if (--psHu32(D1_QWC) == 0)
vif1Regs->stat&= ~0x1f000000;
}
//out[0] = psHu64(mem );
//out[1] = psHu64(mem+8);
out[0] = psHu64(0x5000);
out[1] = psHu64(0x5008);
}
void __fastcall ReadFIFO_page_6(u32 mem, u64 *out)
{
jASSUME( (mem >= 0x10006000) && (mem < 0x10007000) );
DevCon::Notice( "ReadFIFO/GIF, addr=0x%x", params mem );
//out[0] = psHu64(mem );
//out[1] = psHu64(mem+8);
out[0] = psHu64(0x6000);
out[1] = psHu64(0x6008);
}
void __fastcall ReadFIFO_page_7(u32 mem, u64 *out)
{
jASSUME( (mem >= 0x10007000) && (mem < 0x10008000) );
// All addresses in this page map to 0x7000 and 0x7010:
mem &= 0x10;
if( mem == 0 )
{
if( g_nIPU0Data > 0 )
{
out[0] = *(u64*)(g_pIPU0Pointer);
out[1] = *(u64*)(g_pIPU0Pointer+8);
FOreadpos = (FOreadpos + 4) & 31;
g_nIPU0Data--;
g_pIPU0Pointer += 16;
}
return;
}else if ( (mem&0xfffff010) == 0x10007010) {
}
else
FIFOfrom_readsingle((void*)out);
return;
}
SysPrintf("ReadFIFO Unknown %x\n", mem);
}
void ConstReadFIFO(u32 mem)
//////////////////////////////////////////////////////////////////////////
// WriteFIFO Pages
void __fastcall WriteFIFO_page_4(u32 mem, const mem128_t *value)
{
// not done
jASSUME( (mem >= 0x10004000) && (mem < 0x10005000) );
VIF_LOG("WriteFIFO/VIF0, addr=0x%08X\n", mem);
//psHu64(mem ) = value[0];
//psHu64(mem+8) = value[1];
psHu64(0x4000) = value[0];
psHu64(0x4008) = value[1];
vif0ch->qwc += 1;
int ret = VIF0transfer((u32*)value, 4, 0);
assert( ret == 0 ); // vif stall code not implemented
}
void WriteFIFO(u32 mem, const u64 *value) {
int ret;
void __fastcall WriteFIFO_page_5(u32 mem, const mem128_t *value)
{
jASSUME( (mem >= 0x10005000) && (mem < 0x10006000) );
if ((mem >= 0x10004000) && (mem < 0x10005000)) {
VIF_LOG("WriteFIFO VIF0 0x%08X\n", mem);
VIF_LOG("WriteFIFO/VIF1, addr=0x%08X\n", mem);
psHu64(mem ) = value[0];
psHu64(mem+8) = value[1];
vif0ch->qwc += 1;
ret = VIF0transfer((u32*)value, 4, 0);
assert(ret == 0 ); // vif stall code not implemented
//psHu64(mem ) = value[0];
//psHu64(mem+8) = value[1];
psHu64(0x5000) = value[0];
psHu64(0x5008) = value[1];
if(vif1Regs->stat & VIF1_STAT_FDR)
DevCon::Notice("writing to fifo when fdr is set!");
if( vif1Regs->stat & (VIF1_STAT_INT|VIF1_STAT_VSS|VIF1_STAT_VIS|VIF1_STAT_VFS) )
DevCon::Notice("writing to vif1 fifo when stalled");
vif1ch->qwc += 1;
int ret = VIF1transfer((u32*)value, 4, 0);
assert( ret == 0 ); // vif stall code not implemented
}
void __fastcall WriteFIFO_page_6(u32 mem, const mem128_t *value)
{
jASSUME( (mem >= 0x10006000) && (mem < 0x10007000) );
GIF_LOG("WriteFIFO/GIF, addr=0x%08X\n", mem);
//psHu64(mem ) = value[0];
//psHu64(mem+8) = value[1];
psHu64(0x6000) = value[0];
psHu64(0x6008) = value[1];
if( mtgsThread != NULL )
{
const uint count = mtgsThread->PrepDataPacket( GIF_PATH_3, value, 1 );
jASSUME( count == 1 );
u64* data = (u64*)mtgsThread->GetDataPacketPtr();
data[0] = value[0];
data[1] = value[1];
mtgsThread->SendDataPacket();
}
else if ((mem >= 0x10005000) && (mem < 0x10006000)) {
VIF_LOG("WriteFIFO VIF1 0x%08X\n", mem);
psHu64(mem ) = value[0];
psHu64(mem+8) = value[1];
#ifdef PCSX2_DEVBUILD
if(vif1Regs->stat & VIF1_STAT_FDR)
SysPrintf("writing to fifo when fdr is set!\n");
if( vif1Regs->stat & (VIF1_STAT_INT|VIF1_STAT_VSS|VIF1_STAT_VIS|VIF1_STAT_VFS) ) {
SysPrintf("writing to vif1 fifo when stalled\n");
}
#endif
vif1ch->qwc += 1;
ret = VIF1transfer((u32*)value, 4, 0);
assert(ret == 0 ); // vif stall code not implemented
else
{
FreezeXMMRegs(1);
FreezeMMXRegs(1);
GSGIFTRANSFER3((u32*)value, 1);
FreezeMMXRegs(0);
FreezeXMMRegs(0);
}
else if ((mem >= 0x10006000) && (mem < 0x10007000)) {
GIF_LOG("WriteFIFO GIF 0x%08X\n", mem);
}
psHu64(mem ) = value[0];
psHu64(mem+8) = value[1];
void __fastcall WriteFIFO_page_7(u32 mem, const mem128_t *value)
{
jASSUME( (mem >= 0x10007000) && (mem < 0x10008000) );
if( mtgsThread != NULL )
// All addresses in this page map to 0x7000 and 0x7010:
mem &= 0x10;
IPU_LOG( "WriteFIFO/IPU, addr=0x%x", params mem );
if( mem == 0 )
{
// Should this raise a PS2 exception or just ignore silently?
Console::Notice( "WriteFIFO/IPUout (ignored)" );
}
else
{
IPU_LOG("WriteFIFO IPU_in[%d] <- %8.8X_%8.8X_%8.8X_%8.8X\n",
mem/16, ((u32*)value)[3], ((u32*)value)[2], ((u32*)value)[1], ((u32*)value)[0]);
//committing every 16 bytes
while( FIFOto_write((u32*)value, 1) == 0 )
{
const uint count = mtgsThread->PrepDataPacket( GIF_PATH_3, value, 1 );
jASSUME( count == 1 );
u64* data = (u64*)mtgsThread->GetDataPacketPtr();
data[0] = value[0];
data[1] = value[1];
mtgsThread->SendDataPacket();
}
else
{
FreezeXMMRegs(1);
GSGIFTRANSFER3((u32*)value, 1);
FreezeXMMRegs(0);
}
} else
if ((mem&0xfffff010) == 0x10007010) {
IPU_LOG("WriteFIFO IPU_in[%d] <- %8.8X_%8.8X_%8.8X_%8.8X\n", (mem - 0x10007010)/8, ((u32*)value)[3], ((u32*)value)[2], ((u32*)value)[1], ((u32*)value)[0]);
//commiting every 16 bytes
while( FIFOto_write((u32*)value, 1) == 0 ) {
Console::WriteLn("IPU sleeping");
Threading::Timeslice();
}
} else {
Console::Notice("WriteFIFO Unknown %x", params mem);
}
}
void ConstWriteFIFO(u32 mem) {
}

View File

@ -169,6 +169,7 @@ void gsSetVideoRegionType( u32 isPal )
Config.PsxType &= ~1;
}
// If we made it this far it means the refresh rate changed, so update the vsync timers:
UpdateVSyncRate();
}
@ -339,14 +340,17 @@ void gsCSRwrite(u32 value)
}
}
static void IMRwrite(u32 value) {
static void IMRwrite(u32 value)
{
GSIMR = (value & 0x1f00)|0x6000;
// don't update mtgs mem
}
__forceinline void gsWrite8(u32 mem, u8 value) {
switch (mem) {
__forceinline void gsWrite8(u32 mem, u8 value)
{
switch (mem)
{
case 0x12001000: // GS_CSR
gsCSRwrite((CSRw & ~0x000000ff) | value); break;
case 0x12001001: // GS_CSR
@ -364,30 +368,45 @@ __forceinline void gsWrite8(u32 mem, u8 value) {
GIF_LOG("GS write 8 at %8.8lx with data %8.8lx\n", mem, value);
}
__forceinline void gsWrite16(u32 mem, u16 value) {
__forceinline void _gsSMODEwrite( u32 mem, u32 value )
{
switch (mem)
{
case GS_SMODE1:
gsSetVideoRegionType( !!(value & 0x6000) );
break;
case GS_SMODE2:
if(value & 0x1)
Config.PsxType |= 2; // Interlaced
else
Config.PsxType &= ~2; // Non-Interlaced
break;
}
}
//////////////////////////////////////////////////////////////////////////
// GS Write 16 bit
__forceinline void gsWrite16(u32 mem, u16 value)
{
GIF_LOG("GS write 16 at %8.8lx with data %8.8lx\n", mem, value);
switch (mem) {
case 0x12000010: // GS_SMODE1
gsSetVideoRegionType( (value & 0x6000) == 0x6000 );
break;
_gsSMODEwrite( mem, value );
case 0x12000020: // GS_SMODE2
if(value & 0x1) Config.PsxType |= 2; // Interlaced
else Config.PsxType &= ~2; // Non-Interlaced
break;
case 0x12001000: // GS_CSR
switch (mem)
{
case GS_CSR:
gsCSRwrite( (CSRw&0xffff0000) | value);
return; // do not write to MTGS memory
case 0x12001002: // GS_CSR
return; // do not write to MTGS memory
case GS_CSR+2:
gsCSRwrite( (CSRw&0xffff) | ((u32)value<<16));
return; // do not write to MTGS memory
case 0x12001010: // GS_IMR
//SysPrintf("writing to IMR 16\n");
return; // do not write to MTGS memory
case GS_IMR:
IMRwrite(value);
return; // do not write to MTGS memory
return; // do not write to MTGS memory
}
*(u16*)PS2GS_BASE(mem) = value;
@ -396,28 +415,25 @@ __forceinline void gsWrite16(u32 mem, u16 value) {
mtgsThread->SendSimplePacket(GS_RINGTYPE_MEMWRITE16, mem&0x13ff, value, 0);
}
//////////////////////////////////////////////////////////////////////////
// GS Write 32 bit
__forceinline void gsWrite32(u32 mem, u32 value)
{
assert( !(mem&3));
jASSUME( (mem & 3) == 0 );
GIF_LOG("GS write 32 at %8.8lx with data %8.8lx\n", mem, value);
switch (mem) {
case 0x12000010: // GS_SMODE1
gsSetVideoRegionType( (value & 0x6000) == 0x6000 );
break;
_gsSMODEwrite( mem, value );
case 0x12000020: // GS_SMODE2
if(value & 0x1) Config.PsxType |= 2; // Interlaced
else Config.PsxType &= ~2; // Non-Interlaced
break;
case 0x12001000: // GS_CSR
switch (mem)
{
case GS_CSR:
gsCSRwrite(value);
return;
return;
case 0x12001010: // GS_IMR
case GS_IMR:
IMRwrite(value);
return;
return;
}
*(u32*)PS2GS_BASE(mem) = value;
@ -426,14 +442,98 @@ __forceinline void gsWrite32(u32 mem, u32 value)
mtgsThread->SendSimplePacket(GS_RINGTYPE_MEMWRITE32, mem&0x13ff, value, 0);
}
__forceinline void gsWrite64(u32 mem, u64 value) {
//////////////////////////////////////////////////////////////////////////
// GS Write 64 bit
void __fastcall gsWrite64_page_00( u32 mem, const mem64_t* value )
{
gsWrite64_generic( mem, value );
_gsSMODEwrite( mem, (u32)value[0] );
}
void __fastcall gsWrite64_page_01( u32 mem, const mem64_t* value )
{
switch( mem )
{
case GS_CSR:
gsCSRwrite((u32)value[0]);
return;
case GS_IMR:
IMRwrite((u32)value[0]);
return;
}
gsWrite64_generic( mem, value );
}
void __fastcall gsWrite64_generic( u32 mem, const mem64_t* value )
{
const u32* const srcval32 = (u32*)value;
GIF_LOG("GS Write64 at %8.8lx with data %8.8x_%8.8x\n", mem, srcval32[1], srcval32[0]);
*(u64*)PS2GS_BASE(mem) = *value;
if( mtgsThread != NULL )
mtgsThread->SendSimplePacket(GS_RINGTYPE_MEMWRITE64, mem&0x13ff, srcval32[0], srcval32[1]);
}
//////////////////////////////////////////////////////////////////////////
// GS Write 128 bit
void __fastcall gsWrite128_page_00( u32 mem, const mem128_t* value )
{
gsWrite128_generic( mem, value );
_gsSMODEwrite( mem, (u32)value[0] );
}
void __fastcall gsWrite128_page_01( u32 mem, const mem128_t* value )
{
switch( mem )
{
case GS_CSR:
gsCSRwrite((u32)value[0]);
return;
case GS_IMR:
IMRwrite((u32)value[0]);
return;
}
gsWrite128_generic( mem, value );
}
void __fastcall gsWrite128_generic( u32 mem, const mem128_t* value )
{
const u32* const srcval32 = (u32*)value;
GIF_LOG("GS Write64 at %8.8lx with data %8.8x_%8.8x_%8.8x_%8.8x \n", mem,
srcval32[3], srcval32[2], srcval32[1], srcval32[0]);
const uint masked_mem = mem & 0x13ff;
u64* writeTo = (u64*)(&g_RealGSMem[masked_mem]);
writeTo[0] = value[0];
writeTo[1] = value[1];
if( mtgsThread != NULL )
{
mtgsThread->SendSimplePacket(GS_RINGTYPE_MEMWRITE64, masked_mem, srcval32[0], srcval32[1]);
mtgsThread->SendSimplePacket(GS_RINGTYPE_MEMWRITE64, masked_mem+8, srcval32[2], srcval32[3]);
}
}
#if 0
// This function is left in for now for debugging/reference purposes.
__forceinline void gsWrite64(u32 mem, u64 value)
{
GIF_LOG("GS write 64 at %8.8lx with data %8.8lx_%8.8lx\n", mem, ((u32*)&value)[1], (u32)value);
switch (mem) {
switch (mem)
{
case 0x12000010: // GS_SMODE1
gsSetVideoRegionType( (value & 0x6000) == 0x6000 );
break;
break;
case 0x12000020: // GS_SMODE2
if(value & 0x1) Config.PsxType |= 2; // Interlaced
@ -454,6 +554,7 @@ __forceinline void gsWrite64(u32 mem, u64 value) {
if( mtgsThread != NULL )
mtgsThread->SendSimplePacket(GS_RINGTYPE_MEMWRITE64, mem&0x13ff, (u32)value, (u32)(value>>32));
}
#endif
__forceinline u8 gsRead8(u32 mem)
{

View File

@ -279,13 +279,24 @@ void gsCSRwrite(u32 value);
extern void gsWrite8(u32 mem, u8 value);
extern void gsWrite16(u32 mem, u16 value);
extern void gsWrite32(u32 mem, u32 value);
extern void gsWrite64(u32 mem, u64 value);
extern void __fastcall gsWrite64_page_00( u32 mem, const mem64_t* value );
extern void __fastcall gsWrite64_page_01( u32 mem, const mem64_t* value );
extern void __fastcall gsWrite64_generic( u32 mem, const mem64_t* value );
extern void __fastcall gsWrite128_page_00( u32 mem, const mem128_t* value );
extern void __fastcall gsWrite128_page_01( u32 mem, const mem128_t* value );
extern void __fastcall gsWrite128_generic( u32 mem, const mem128_t* value );
extern u8 gsRead8(u32 mem);
extern u16 gsRead16(u32 mem);
extern u32 gsRead32(u32 mem);
extern u64 gsRead64(u32 mem);
//extern void gsWrite64(u32 mem, u64 value);
void gsConstWrite8(u32 mem, int mmreg);
void gsConstWrite16(u32 mem, int mmreg);
void gsConstWrite32(u32 mem, int mmreg);

View File

@ -71,7 +71,10 @@ void hwReset()
ipuReset();
}
__forceinline u8 hwRead8(u32 mem)
/////////////////////////////////////////////////////////////////////////
// Hardware READ 8 bit
__forceinline u8 hwRead8(u32 mem)
{
u8 ret;
@ -134,6 +137,9 @@ __forceinline u8 hwRead8(u32 mem)
return ret;
}
/////////////////////////////////////////////////////////////////////////
// Hardware READ 16 bit
__forceinline u16 hwRead16(u32 mem)
{
u16 ret;
@ -177,6 +183,9 @@ __forceinline u16 hwRead16(u32 mem)
return ret;
}
/////////////////////////////////////////////////////////////////////////
// Hardware READ 32 bit
// Reads hardware registers for page 0 (counters 0 and 1)
mem32_t __fastcall hwRead32_page_00(u32 mem)
{
@ -221,20 +230,8 @@ mem32_t __fastcall hwRead32_page_0F(u32 mem)
// *Performance Warning* This function is called -A-LOT. Be weary when making changes. It
// could impact FPS significantly.
// Optimization Note:
// Shortcut for the INTC_STAT register, which is checked *very* frequently as part of the EE's
// vsynch timers. INTC_STAT has the disadvantage of being in the 0x1000f000 case, which has
// a lot of additional registers in it, and combined with it's call frequency is a bad thing.
mem &= 0xffff;
/*if(mem == (INTC_STAT & 0xffff) )
{
// This one is checked alot, so leave it commented out unless you love 600 meg logfiles.
//HW_LOG("DMAC_STAT Read 32bit %x\n", psHu32(0xe010));
return psHu32(INTC_STAT);
}*/
switch( mem )
{
case 0xf000:
@ -293,7 +290,7 @@ mem32_t __fastcall hwRead32_page_02(u32 mem)
}
// Used for all pages not explicitly specified above.
mem32_t __fastcall hwRead32_page_other(u32 mem)
mem32_t __fastcall hwRead32_generic(u32 mem)
{
const u16 masked_mem = mem & 0xffff;
@ -347,39 +344,62 @@ mem32_t __fastcall hwRead32_page_other(u32 mem)
return *((u32*)&PS2MEM_HW[masked_mem]);
}
__forceinline u64 hwRead64(u32 mem) {
u64 ret;
/////////////////////////////////////////////////////////////////////////
// Hardware READ 64 bit
if ((mem>=0x10002000) && (mem<0x10003000)) {
return ipuRead64(mem);
}
// switch (mem) {
// default:
if (mem < 0x10010000) {
ret = psHu64(mem);
}
else ret = 0;
HW_LOG("Unknown Hardware Read 64 at %x\n",mem);
// break;
// }
return ret;
void __fastcall hwRead64_page_00(u32 mem, mem64_t* result )
{
*result = hwRead32_page_00( mem );
}
__forceinline void hwRead128(u32 mem, u64 *out) {
if (mem >= 0x10004000 && mem < 0x10008000) {
ReadFIFO(mem, out); return;
}
void __fastcall hwRead64_page_01(u32 mem, mem64_t* result )
{
*result = hwRead32_page_01( mem );
}
if (mem < 0x10010000) {
out[0] = psHu64(mem);
out[1] = psHu64(mem+8);
}
void __fastcall hwRead64_page_02(u32 mem, mem64_t* result )
{
*result = ipuRead64(mem);
}
void __fastcall hwRead64_generic(u32 mem, mem64_t* result )
{
*result = psHu64(mem);
HW_LOG("Unknown Hardware Read 64 at %x\n",mem);
}
/////////////////////////////////////////////////////////////////////////
// Hardware READ 128 bit
void __fastcall hwRead128_page_00(u32 mem, mem128_t* result )
{
result[0] = hwRead32_page_00( mem );
result[1] = 0;
}
void __fastcall hwRead128_page_01(u32 mem, mem128_t* result )
{
result[0] = hwRead32_page_01( mem );
result[1] = 0;
}
void __fastcall hwRead128_page_02(u32 mem, mem128_t* result )
{
// IPU is currently unhandled in 128 bit mode.
HW_LOG("Unknown Hardware Read 128 at %x (IPU)\n",mem);
}
void __fastcall hwRead128_generic(u32 mem, mem128_t* out)
{
out[0] = psHu64(mem);
out[1] = psHu64(mem+8);
HW_LOG("Unknown Hardware Read 128 at %x\n",mem);
}
/////////////////////////////////////////////////////////////////////////
// DMA Execution Interfaces
// dark cloud2 uses 8 bit DMAs register writes
static __forceinline void DmaExec8( void (*func)(), u32 mem, u8 value )
{
@ -407,12 +427,15 @@ static void DmaExec( void (*func)(), u32 mem, u32 value )
if( (value & 0xc) == 0x4 && (value & 0xffff0000) == 0)
psHu32(mem) = (psHu32(mem) & 0xFFFF0000) | (u16)value;
else /* Else (including Normal mode etc) write whatever the hardware sends*/
psHu32(mem) = (u32)value;
psHu32(mem) = (u32)value;
if ((psHu32(mem) & 0x100) && (psHu32(DMAC_CTRL) & 0x1))
func();
}
/////////////////////////////////////////////////////////////////////////
// Hardware WRITE 8 bit
char sio_buffer[1024];
int sio_count;
@ -456,7 +479,6 @@ void hwWrite8(u32 mem, u8 value) {
sio_buffer[sio_count++] = value;
}
}
// SysPrintf("%c", value);
break;
case 0x10003c02: //Tony Hawks Project 8 uses this
@ -545,10 +567,8 @@ void hwWrite8(u32 mem, u8 value) {
__forceinline void hwWrite16(u32 mem, u16 value)
{
#ifdef PCSX2_DEVBUILD
if( mem >= 0x10002000 && mem < 0x10008000 )
SysPrintf("hwWrite16 to %x\n", mem);
#endif
Console::Notice( "hwWrite16 to %x", params mem );
switch(mem)
{
@ -767,7 +787,7 @@ __forceinline void hwWrite16(u32 mem, u16 value)
}
}
// Page 0 of HW mwmory houses registers for Counters 0 and 1
// Page 0 of HW memory houses registers for Counters 0 and 1
void __fastcall hwWrite32_page_00( u32 mem, u32 value )
{
mem &= 0xffff;
@ -787,7 +807,7 @@ void __fastcall hwWrite32_page_00( u32 mem, u32 value )
*((u32*)&PS2MEM_HW[mem]) = value;
}
// Page 1 of HW mwmory houses registers for Counters 2 and 3
// Page 1 of HW memory houses registers for Counters 2 and 3
void __fastcall hwWrite32_page_01( u32 mem, u32 value )
{
mem &= 0xffff;
@ -826,24 +846,29 @@ void __fastcall hwWrite32_page_03( u32 mem, u32 value )
switch (mem)
{
case GIF_CTRL:
//SysPrintf("GIF_CTRL write %x\n", value);
psHu32(mem) = value & 0x8;
if (value & 0x1) gsGIFReset();
else if( value & 8 ) psHu32(GIF_STAT) |= 8;
else psHu32(GIF_STAT) &= ~8;
if (value & 0x1)
gsGIFReset();
else if( value & 8 )
psHu32(GIF_STAT) |= 8;
else
psHu32(GIF_STAT) &= ~8;
break;
case GIF_MODE:
{
// need to set GIF_MODE (hamster ball)
psHu32(GIF_MODE) = value;
if (value & 0x1) psHu32(GIF_STAT)|= 0x1;
else psHu32(GIF_STAT)&= ~0x1;
if (value & 0x4) psHu32(GIF_STAT)|= 0x4;
else psHu32(GIF_STAT)&= ~0x4;
// set/clear bits 0 and 2 as per the GIF_MODE value.
const u32 bitmask = 0x1 | 0x4;
psHu32(GIF_STAT) &= ~bitmask;
psHu32(GIF_STAT) |= (u32)value & bitmask;
}
break;
case GIF_STAT: // stat is readonly
DevCon::Notice("*PCSX2* Gifstat write value = 0x%x\n", params value);
DevCon::Notice("*PCSX2* GIFSTAT write value = 0x%x (readonly, ignored)", params value);
break;
default:
@ -894,7 +919,11 @@ void __fastcall hwWrite32_page_0E( u32 mem, u32 value )
else if( mem == DMAC_STAT )
{
HW_LOG("DMAC_STAT Write 32bit %x\n", value);
psHu16(0xe010)&= ~(value & 0xffff); // clear on 1
// lower 16 bits: clear on 1
// upper 16 bits: reverse on 1
psHu16(0xe010) &= ~(value & 0xffff);
psHu16(0xe012) ^= (u16)(value >> 16);
cpuTestDMACInts();
@ -932,16 +961,6 @@ void __fastcall hwWrite32_page_0F( u32 mem, u32 value )
psHu32(mem) = value & ~0x80000000; //kill the busy bit
break;
case HELPSWITCH(0x1000f440)://MCH_DRD:
psHu32(mem) = value;
break;
//------------------------------------------------------------------
case HELPSWITCH(0x1000f590): // DMAC_ENABLEW
HW_LOG("DMAC_ENABLEW Write 32bit %lx\n", value);
psHu32(0xf590) = value;
psHu32(0xf520) = value;
break;
//------------------------------------------------------------------
case HELPSWITCH(0x1000f200):
psHu32(mem) = value;
break;
@ -960,18 +979,29 @@ void __fastcall hwWrite32_page_0F( u32 mem, u32 value )
case HELPSWITCH(0x1000f260):
psHu32(mem) = 0;
break;
case HELPSWITCH(0x1000f440)://MCH_DRD:
psHu32(mem) = value;
break;
case HELPSWITCH(0x1000f590): // DMAC_ENABLEW
HW_LOG("DMAC_ENABLEW Write 32bit %lx\n", value);
psHu32(0xf590) = value;
psHu32(0xf520) = value;
break;
//------------------------------------------------------------------
case HELPSWITCH(0x1000f130):
case HELPSWITCH(0x1000f410):
HW_LOG("Unknown Hardware write 32 at %x with value %x (%x)\n", mem, value, cpuRegs.CP0.n.Status.val);
break;
break;
default:
psHu32(mem) = value;
}
}
void __fastcall hwWrite32_page_other( u32 mem, u32 value )
void __fastcall hwWrite32_generic( u32 mem, u32 value )
{
// Used for developer logging -- optimized away in Public Release.
const char* regName = "Unknown";
@ -1044,141 +1074,175 @@ void __fastcall hwWrite32_page_other( u32 mem, u32 value )
psHu32(mem) = value;
}
__forceinline void hwWrite64(u32 mem, u64 value) {
u32 val32;
int i;
/////////////////////////////////////////////////////////////////////////
// HW Write 64 bit
if ((mem>=0x10002000) && (mem<=0x10002030)) {
ipuWrite64(mem, value);
void __fastcall hwWrite64_page_02( u32 mem, const mem64_t* srcval )
{
//hwWrite64( mem, *srcval ); return;
ipuWrite64( mem, *srcval );
}
void __fastcall hwWrite64_page_03( u32 mem, const mem64_t* srcval )
{
//hwWrite64( mem, *srcval ); return;
const u64 value = *srcval;
if(mem>=0x10003800)
{
if(mem<0x10003c00)
vif0Write32(mem, value);
else
vif1Write32(mem, value);
return;
}
if ((mem>=0x10003800) && (mem<0x10003c00)) {
vif0Write32(mem, value); return;
}
if ((mem>=0x10003c00) && (mem<0x10004000)) {
vif1Write32(mem, value); return;
}
switch (mem) {
switch (mem)
{
case GIF_CTRL:
DevCon::Status("GIF_CTRL write 64", params value);
psHu32(mem) = value & 0x8;
if(value & 0x1) {
if(value & 0x1)
gsGIFReset();
//gsReset();
}
else {
if( value & 8 ) psHu32(GIF_STAT) |= 8;
else psHu32(GIF_STAT) &= ~8;
else
{
if( value & 8 )
psHu32(GIF_STAT) |= 8;
else
psHu32(GIF_STAT) &= ~8;
}
return;
case GIF_MODE:
{
#ifdef GSPATH3FIX
Console::Status("GIFMODE64 %x\n", params value);
#endif
psHu64(GIF_MODE) = value;
if (value & 0x1) psHu32(GIF_STAT)|= 0x1;
else psHu32(GIF_STAT)&= ~0x1;
if (value & 0x4) psHu32(GIF_STAT)|= 0x4;
else psHu32(GIF_STAT)&= ~0x4;
break;
// set/clear bits 0 and 2 as per the GIF_MODE value.
const u32 bitmask = 0x1 | 0x4;
psHu32(GIF_STAT) &= ~bitmask;
psHu32(GIF_STAT) |= (u32)value & bitmask;
}
case GIF_STAT: // stat is readonly
return;
}
}
void __fastcall hwWrite64_page_0E( u32 mem, const mem64_t* srcval )
{
//hwWrite64( mem, *srcval ); return;
const u64 value = *srcval;
if( mem == DMAC_CTRL )
{
HW_LOG("DMAC_CTRL Write 64bit %x\n", value);
}
else if( mem == DMAC_STAT )
{
HW_LOG("DMAC_STAT Write 64bit %x\n", value);
// lower 16 bits: clear on 1
// upper 16 bits: reverse on 1
psHu16(0xe010) &= ~(value & 0xffff);
psHu16(0xe012) ^= (u16)(value >> 16);
cpuTestDMACInts();
return;
}
psHu64(mem) = value;
}
void __fastcall hwWrite64_generic( u32 mem, const mem64_t* srcval )
{
//hwWrite64( mem, *srcval ); return;
const u64 value = *srcval;
switch (mem)
{
case 0x1000a000: // dma2 - gif
DMA_LOG("0x%8.8x hwWrite64: GSdma %lx\n", cpuRegs.cycle, value);
DMA_LOG("0x%8.8x hwWrite64: GSdma %x\n", cpuRegs.cycle, value);
DmaExec(dmaGIF, mem, value);
break;
break;
case 0x1000e000: // DMAC_CTRL
HW_LOG("DMAC_CTRL Write 64bit %x\n", value);
psHu64(mem) = value;
break;
case INTC_STAT:
HW_LOG("INTC_STAT Write 64bit %x\n", (u32)value);
psHu32(INTC_STAT) &= ~value;
//cpuTestINTCInts();
break;
case 0x1000e010: // DMAC_STAT
HW_LOG("DMAC_STAT Write 64bit %x\n", value);
val32 = (u32)value;
psHu16(0xe010)&= ~(val32 & 0xffff); // clear on 1
val32 = val32 >> 16;
for (i=0; i<16; i++) { // reverse on 1
if (val32 & (1<<i)) {
if (psHu16(0xe012) & (1<<i))
psHu16(0xe012)&= ~(1<<i);
else
psHu16(0xe012)|= 1<<i;
}
}
cpuTestDMACInts();
case INTC_MASK:
HW_LOG("INTC_MASK Write 64bit %x\n", (u32)value);
psHu32(INTC_MASK) ^= (u16)value;
cpuTestINTCInts();
break;
case 0x1000f130:
case 0x1000f410:
case 0x1000f430:
break;
case 0x1000f590: // DMAC_ENABLEW
psHu32(0xf590) = value;
psHu32(0xf520) = value;
break;
case 0x1000f000: // INTC_STAT
HW_LOG("INTC_STAT Write 64bit %x\n", value);
psHu32(INTC_STAT)&=~value;
cpuTestINTCInts();
break;
case 0x1000f010: // INTC_MASK
HW_LOG("INTC_MASK Write 32bit %x\n", value);
for (i=0; i<16; i++) { // reverse on 1
const int s = (1<<i);
if (value & s) {
if (psHu32(INTC_MASK) & s)
psHu32(INTC_MASK)&= ~s;
else
psHu32(INTC_MASK)|= s;
}
}
cpuTestINTCInts();
break;
case 0x1000f130:
case 0x1000f410:
case 0x1000f430:
break;
break;
default:
psHu64(mem) = value;
HW_LOG("Unknown Hardware write 64 at %x with value %x (status=%x)\n",mem,value, cpuRegs.CP0.n.Status.val);
break;
break;
}
}
__forceinline void hwWrite128(u32 mem, const u64 *value) {
if (mem >= 0x10004000 && mem < 0x10008000) {
WriteFIFO(mem, value); return;
}
/////////////////////////////////////////////////////////////////////////
// HW Write 128 bit
void __fastcall hwWrite128_generic(u32 mem, const mem128_t *srcval)
{
//hwWrite128( mem, srcval ); return;
switch (mem)
{
case INTC_STAT:
HW_LOG("INTC_STAT Write 64bit %x\n", (u32)srcval[0]);
psHu32(INTC_STAT) &= ~srcval[0];
//cpuTestINTCInts();
break;
case INTC_MASK:
HW_LOG("INTC_MASK Write 64bit %x\n", (u32)srcval[0]);
psHu32(INTC_MASK) ^= (u16)srcval[0];
cpuTestINTCInts();
break;
switch (mem) {
case 0x1000f590: // DMAC_ENABLEW
psHu32(0xf590) = *(u32*)value;
psHu32(0xf520) = *(u32*)value;
break;
psHu32(0xf590) = srcval[0];
psHu32(0xf520) = srcval[0];
break;
case 0x1000f130:
case 0x1000f410:
case 0x1000f430:
break;
default:
psHu64(mem ) = srcval[0];
psHu64(mem+8) = srcval[1];
psHu64(mem ) = value[0];
psHu64(mem+8) = value[1];
HW_LOG("Unknown Hardware write 128 at %x with value %x_%x (status=%x)\n", mem, value[1], value[0], cpuRegs.CP0.n.Status.val);
break;
HW_LOG("Unknown Hardware write 128 at %x with value %x_%x (status=%x)\n", mem, srcval[1], srcval[0], cpuRegs.CP0.n.Status.val);
break;
}
}
__forceinline void intcInterrupt() {
__forceinline void intcInterrupt()
{
if ((cpuRegs.CP0.n.Status.val & 0x400) != 0x400) return;
if ((psHu32(INTC_STAT)) == 0) {
@ -1814,5 +1878,143 @@ __forceinline void __fastcall hwWrite32(u32 mem, u32 value)
break;
}
}
#endif
#if 0
__forceinline void hwWrite64(u32 mem, u64 value)
{
u32 val32;
int i;
if ((mem>=0x10002000) && (mem<=0x10002030)) {
ipuWrite64(mem, value);
return;
}
if ((mem>=0x10003800) && (mem<0x10003c00)) {
vif0Write32(mem, value); return;
}
if ((mem>=0x10003c00) && (mem<0x10004000)) {
vif1Write32(mem, value); return;
}
switch (mem) {
case GIF_CTRL:
DevCon::Status("GIF_CTRL write 64", params value);
psHu32(mem) = value & 0x8;
if(value & 0x1) {
gsGIFReset();
//gsReset();
}
else {
if( value & 8 ) psHu32(GIF_STAT) |= 8;
else psHu32(GIF_STAT) &= ~8;
}
return;
case GIF_MODE:
#ifdef GSPATH3FIX
Console::Status("GIFMODE64 %x\n", params value);
#endif
psHu64(GIF_MODE) = value;
if (value & 0x1) psHu32(GIF_STAT)|= 0x1;
else psHu32(GIF_STAT)&= ~0x1;
if (value & 0x4) psHu32(GIF_STAT)|= 0x4;
else psHu32(GIF_STAT)&= ~0x4;
break;
case GIF_STAT: // stat is readonly
return;
case 0x1000a000: // dma2 - gif
DMA_LOG("0x%8.8x hwWrite64: GSdma %lx\n", cpuRegs.cycle, value);
DmaExec(dmaGIF, mem, value);
break;
case 0x1000e000: // DMAC_CTRL
HW_LOG("DMAC_CTRL Write 64bit %x\n", value);
psHu64(mem) = value;
break;
case 0x1000e010: // DMAC_STAT
HW_LOG("DMAC_STAT Write 64bit %x\n", value);
val32 = (u32)value;
psHu16(0xe010)&= ~(val32 & 0xffff); // clear on 1
val32 = val32 >> 16;
for (i=0; i<16; i++) { // reverse on 1
if (val32 & (1<<i)) {
if (psHu16(0xe012) & (1<<i))
psHu16(0xe012)&= ~(1<<i);
else
psHu16(0xe012)|= 1<<i;
}
}
cpuTestDMACInts();
break;
case 0x1000f590: // DMAC_ENABLEW
psHu32(0xf590) = value;
psHu32(0xf520) = value;
break;
case 0x1000f000: // INTC_STAT
HW_LOG("INTC_STAT Write 64bit %x\n", value);
psHu32(INTC_STAT)&=~value;
cpuTestINTCInts();
break;
case 0x1000f010: // INTC_MASK
HW_LOG("INTC_MASK Write 32bit %x\n", value);
for (i=0; i<16; i++) { // reverse on 1
const int s = (1<<i);
if (value & s) {
if (psHu32(INTC_MASK) & s)
psHu32(INTC_MASK)&= ~s;
else
psHu32(INTC_MASK)|= s;
}
}
cpuTestINTCInts();
break;
case 0x1000f130:
case 0x1000f410:
case 0x1000f430:
break;
default:
psHu64(mem) = value;
HW_LOG("Unknown Hardware write 64 at %x with value %x (status=%x)\n",mem,value, cpuRegs.CP0.n.Status.val);
break;
}
}
__forceinline void hwWrite128(u32 mem, const u64 *value)
{
if (mem >= 0x10004000 && mem < 0x10008000) {
WriteFIFO(mem, value); return;
}
switch (mem) {
case 0x1000f590: // DMAC_ENABLEW
psHu32(0xf590) = *(u32*)value;
psHu32(0xf520) = *(u32*)value;
break;
case 0x1000f130:
case 0x1000f410:
case 0x1000f430:
break;
default:
psHu64(mem ) = value[0];
psHu64(mem+8) = value[1];
HW_LOG("Unknown Hardware write 128 at %x with value %x_%x (status=%x)\n", mem, value[1], value[0], cpuRegs.CP0.n.Status.val);
break;
}
}
#endif

View File

@ -32,17 +32,24 @@ extern u8 *psH; // hw mem
extern void CPU_INT( u32 n, s32 ecycle );
//////////////////////////////////////////////////////////////////////////
// Hardware FIFOs (128 bit access only!)
//
// VIF0 -- 0x10004000 -- psH[0x4000]
// VIF1 -- 0x10005000 -- psH[0x5000]
// GIF -- 0x10006000 -- psH[0x6000]
// IPUout -- 0x10007000 -- psH[0x7000]
// IPUin -- 0x10007010 -- psH[0x7010]
void ReadFIFO(u32 mem, u64 *out);
void ConstReadFIFO(u32 mem);
void __fastcall ReadFIFO_page_4(u32 mem, mem128_t *out);
void __fastcall ReadFIFO_page_5(u32 mem, mem128_t *out);
void __fastcall ReadFIFO_page_6(u32 mem, mem128_t *out);
void __fastcall ReadFIFO_page_7(u32 mem, mem128_t *out);
void WriteFIFO(u32 mem, const u64 *value);
void ConstWriteFIFO(u32 mem);
void __fastcall WriteFIFO_page_4(u32 mem, const mem128_t *value);
void __fastcall WriteFIFO_page_5(u32 mem, const mem128_t *value);
void __fastcall WriteFIFO_page_6(u32 mem, const mem128_t *value);
void __fastcall WriteFIFO_page_7(u32 mem, const mem128_t *value);
//
@ -364,22 +371,26 @@ void hwShutdown();
// hw read functions
extern u8 hwRead8 (u32 mem);
extern u16 hwRead16(u32 mem);
extern u64 hwRead64(u32 mem);
extern void hwRead128(u32 mem, u64 *out);
extern mem32_t __fastcall hwRead32_page_00(u32 mem);
extern mem32_t __fastcall hwRead32_page_01(u32 mem);
extern mem32_t __fastcall hwRead32_page_02(u32 mem);
extern mem32_t __fastcall hwRead32_page_0F(u32 mem);
extern mem32_t __fastcall hwRead32_page_other(u32 mem);
extern mem32_t __fastcall hwRead32_generic(u32 mem);
extern mem32_t __fastcall hwRead32(u32 mem);
extern void __fastcall hwRead64_page_00(u32 mem, mem64_t* result );
extern void __fastcall hwRead64_page_01(u32 mem, mem64_t* result );
extern void __fastcall hwRead64_page_02(u32 mem, mem64_t* result );
extern void __fastcall hwRead64_generic(u32 mem, mem64_t* result );
extern void __fastcall hwRead128_page_00(u32 mem, mem128_t* result );
extern void __fastcall hwRead128_page_01(u32 mem, mem128_t* result );
extern void __fastcall hwRead128_page_02(u32 mem, mem128_t* result );
extern void __fastcall hwRead128_generic(u32 mem, mem128_t *out);
// hw write functions
extern void hwWrite8 (u32 mem, u8 value);
extern void hwWrite16(u32 mem, u16 value);
extern void hwWrite64(u32 mem, u64 value);
extern void hwWrite128(u32 mem, const u64 *value);
extern void __fastcall hwWrite32_page_00( u32 mem, u32 value );
extern void __fastcall hwWrite32_page_01( u32 mem, u32 value );
@ -388,9 +399,21 @@ extern void __fastcall hwWrite32_page_03( u32 mem, u32 value );
extern void __fastcall hwWrite32_page_0B( u32 mem, u32 value );
extern void __fastcall hwWrite32_page_0E( u32 mem, u32 value );
extern void __fastcall hwWrite32_page_0F( u32 mem, u32 value );
extern void __fastcall hwWrite32_page_other( u32 mem, u32 value );
extern void __fastcall hwWrite32_generic( u32 mem, u32 value );
extern void __fastcall hwWrite32(u32 mem, u32 value);
extern void __fastcall hwWrite64_page_02( u32 mem, const mem64_t* srcval );
extern void __fastcall hwWrite64_page_03( u32 mem, const mem64_t* srcval );
extern void __fastcall hwWrite64_page_0E( u32 mem, const mem64_t* srcval );
extern void __fastcall hwWrite64_generic( u32 mem, const mem64_t* srcval );
extern void __fastcall hwWrite128_generic(u32 mem, const mem128_t *srcval);
// legacy - used for debugging sometimes
//extern mem32_t __fastcall hwRead32(u32 mem);
//extern void __fastcall hwWrite32(u32 mem, u32 value);
//extern void hwWrite64(u32 mem, u64 value);
//extern void hwWrite128(u32 mem, const u64 *value);
void hwIntcIrq(int n);
void hwDmacIrq(int n);

View File

@ -165,6 +165,9 @@ vtlbHandler vu0_micro_mem[2]; // 0 - dynarec, 1 - interpreter
vtlbHandler vu1_micro_mem[2]; // 0 - dynarec, 1 - interpreter
vtlbHandler hw_by_page[0x10];
vtlbHandler gs_page_0;
vtlbHandler gs_page_1;
// Used to remap the VUmicro memory according to the VU0/VU1 dynarec setting.
// (the VU memory operations are different for recs vs. interpreters)
@ -196,23 +199,36 @@ void memMapPhy()
//These fallback to mem* stuff ...
vtlb_MapHandler(tlb_fallback_1,0x10000000,0x10000);
vtlb_MapHandler(tlb_fallback_6,0x12000000,0x10000);
vtlb_MapHandler(tlb_fallback_7,0x14000000,0x10000);
vtlb_MapHandler(tlb_fallback_4,0x18000000,0x10000);
vtlb_MapHandler(tlb_fallback_5,0x1a000000,0x10000);
vtlb_MapHandler(tlb_fallback_6,0x12000000,0x10000);
vtlb_MapHandler(tlb_fallback_8,0x1f000000,0x10000);
vtlb_MapHandler(tlb_fallback_3,0x1f400000,0x10000);
vtlb_MapHandler(tlb_fallback_2,0x1f800000,0x10000);
vtlb_MapHandler(tlb_fallback_8,0x1f900000,0x10000);
#ifdef PCSX2_DEVBUILD
// Bind fallback handlers used for logging purposes only.
// In release mode the Vtlb will map these addresses directly instead of using
// the read/write handlers (which just issue logs and do normal memOps)
#endif
// map specific optimized page handlers for HW accesses
vtlb_MapHandler(hw_by_page[0x0], 0x10000000, 0x01000);
vtlb_MapHandler(hw_by_page[0x1], 0x10001000, 0x01000);
vtlb_MapHandler(hw_by_page[0x2], 0x10002000, 0x01000);
vtlb_MapHandler(hw_by_page[0x3], 0x10003000, 0x01000);
vtlb_MapHandler(hw_by_page[0x4], 0x10004000, 0x01000);
vtlb_MapHandler(hw_by_page[0x5], 0x10005000, 0x01000);
vtlb_MapHandler(hw_by_page[0x6], 0x10006000, 0x01000);
vtlb_MapHandler(hw_by_page[0x7], 0x10007000, 0x01000);
vtlb_MapHandler(hw_by_page[0xb], 0x1000b000, 0x01000);
vtlb_MapHandler(hw_by_page[0xe], 0x1000e000, 0x01000);
vtlb_MapHandler(hw_by_page[0xf], 0x1000f000, 0x01000);
vtlb_MapHandler(gs_page_0, 0x12000000, 0x01000);
vtlb_MapHandler(gs_page_1, 0x12001000, 0x01000);
}
//Why is this required ?
@ -298,8 +314,6 @@ mem32_t __fastcall _ext_memRead32(u32 mem)
{
switch (p)
{
case 1: // hwm
return hwRead32_page_other(mem);
case 2: // psh
return psxHwRead32(mem);
case 6: // gsm
@ -322,8 +336,6 @@ void __fastcall _ext_memRead64(u32 mem, mem64_t *out)
{
switch (p)
{
case 1: // hwm
*out = hwRead64(mem); return;
case 6: // gsm
*out = gsRead64(mem); return;
}
@ -337,8 +349,8 @@ void __fastcall _ext_memRead128(u32 mem, mem128_t *out)
{
switch (p)
{
case 1: // hwm
hwRead128(mem & ~0xa0000000, out); return;
//case 1: // hwm
// hwRead128(mem & ~0xa0000000, out); return;
case 6: // gsm
out[0] = gsRead64(mem );
out[1] = gsRead64(mem+8); return;
@ -398,8 +410,6 @@ template<int p>
void __fastcall _ext_memWrite32(u32 mem, u32 value)
{
switch (p) {
case 1: // hwm
hwWrite32_page_other(mem, value); return;
case 2: // psh
psxHwWrite32(mem, value); return;
case 6: // gsm
@ -416,13 +426,13 @@ template<int p>
void __fastcall _ext_memWrite64(u32 mem, const u64* value)
{
switch (p) {
case 1: // hwm
hwWrite64(mem & ~0xa0000000, *value);
return;
case 6: // gsm
gsWrite64(mem & ~0xa0000000, *value); return;
}
/*switch (p) {
//case 1: // hwm
// hwWrite64(mem & ~0xa0000000, *value);
// return;
//case 6: // gsm
// gsWrite64(mem & ~0xa0000000, *value); return;
}*/
MEM_LOG("Unknown Memory write64 to address %x with data %8.8x_%8.8x\n", mem, (u32)(*value>>32), (u32)*value);
cpuTlbMissW(mem, cpuRegs.branch);
@ -430,15 +440,15 @@ void __fastcall _ext_memWrite64(u32 mem, const u64* value)
template<int p>
void __fastcall _ext_memWrite128(u32 mem, const u64 *value)
{
switch (p) {
case 1: // hwm
hwWrite128(mem & ~0xa0000000, value);
return;
case 6: // gsm
mem &= ~0xa0000000;
gsWrite64(mem, value[0]);
gsWrite64(mem+8, value[1]); return;
}
/*switch (p) {
//case 1: // hwm
// hwWrite128(mem & ~0xa0000000, value);
// return;
//case 6: // gsm
// mem &= ~0xa0000000;
// gsWrite64(mem, value[0]);
// gsWrite64(mem+8, value[1]); return;
}*/
MEM_LOG("Unknown Memory write128 to address %x with data %8.8x_%8.8x_%8.8x_%8.8x\n", mem, ((u32*)value)[3], ((u32*)value)[2], ((u32*)value)[1], ((u32*)value)[0]);
cpuTlbMissW(mem, cpuRegs.branch);
@ -671,7 +681,7 @@ void memReset()
tlb_fallback_3=vtlb_RegisterHandlerTempl1(_ext_mem,3);
tlb_fallback_4=vtlb_RegisterHandlerTempl1(_ext_mem,4);
tlb_fallback_5=vtlb_RegisterHandlerTempl1(_ext_mem,5);
tlb_fallback_6=vtlb_RegisterHandlerTempl1(_ext_mem,6);
//tlb_fallback_6=vtlb_RegisterHandlerTempl1(_ext_mem,6);
tlb_fallback_7=vtlb_RegisterHandlerTempl1(_ext_mem,7);
tlb_fallback_8=vtlb_RegisterHandlerTempl1(_ext_mem,8);
@ -683,50 +693,88 @@ void memReset()
vu0_micro_mem[1] = vtlb_RegisterHandlerTempl2(vuMicro,0,false);
vu1_micro_mem[1] = vtlb_RegisterHandlerTempl2(vuMicro,1,false);
//////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// psHw Optimized Mappings
// The HW Registers have been split into pages to improve optimization.
// Anything not explicitly mapped into one of the hw_by_page handlers will be handled
// by the default/generic tlb_fallback_1 handler.
tlb_fallback_1 = vtlb_RegisterHandler(
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_page_other, _ext_memRead64<1>, _ext_memRead128<1>,
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_other, _ext_memWrite64<1>, _ext_memWrite128<1>
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, hwRead128_generic,
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_generic, hwWrite64_generic, hwWrite128_generic
);
hw_by_page[0x0] = vtlb_RegisterHandler(
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_page_00, _ext_memRead64<1>, _ext_memRead128<1>,
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_00, _ext_memWrite64<1>, _ext_memWrite128<1>
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_page_00, hwRead64_page_00, hwRead128_page_00,
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_00, hwWrite64_generic, hwWrite128_generic
);
hw_by_page[0x1] = vtlb_RegisterHandler(
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_page_01, _ext_memRead64<1>, _ext_memRead128<1>,
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_01, _ext_memWrite64<1>, _ext_memWrite128<1>
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_page_01, hwRead64_page_01, hwRead128_page_01,
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_01, hwWrite64_generic, hwWrite128_generic
);
hw_by_page[0x2] = vtlb_RegisterHandler(
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_page_02, _ext_memRead64<1>, _ext_memRead128<1>,
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_02, _ext_memWrite64<1>, _ext_memWrite128<1>
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_page_02, hwRead64_page_02, hwRead128_page_02,
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_02, hwWrite64_page_02, hwWrite128_generic
);
hw_by_page[0x3] = vtlb_RegisterHandler(
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_page_other, _ext_memRead64<1>, _ext_memRead128<1>,
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_03, _ext_memWrite64<1>, _ext_memWrite128<1>
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, hwRead128_generic,
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_03, hwWrite64_page_03, hwWrite128_generic
);
hw_by_page[0x4] = vtlb_RegisterHandler(
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, ReadFIFO_page_4,
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_generic, hwWrite64_generic, WriteFIFO_page_4
);
hw_by_page[0x5] = vtlb_RegisterHandler(
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, ReadFIFO_page_5,
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_generic, hwWrite64_generic, WriteFIFO_page_5
);
hw_by_page[0x6] = vtlb_RegisterHandler(
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, ReadFIFO_page_6,
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_generic, hwWrite64_generic, WriteFIFO_page_6
);
hw_by_page[0x7] = vtlb_RegisterHandler(
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, ReadFIFO_page_7,
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_generic, hwWrite64_generic, WriteFIFO_page_7
);
hw_by_page[0xb] = vtlb_RegisterHandler(
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_page_other, _ext_memRead64<1>, _ext_memRead128<1>,
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_0B, _ext_memWrite64<1>, _ext_memWrite128<1>
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, hwRead128_generic,
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_0B, hwWrite64_generic, hwWrite128_generic
);
hw_by_page[0xe] = vtlb_RegisterHandler(
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_page_other, _ext_memRead64<1>, _ext_memRead128<1>,
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_0E, _ext_memWrite64<1>, _ext_memWrite128<1>
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, hwRead128_generic,
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_0E, hwWrite64_page_0E, hwWrite128_generic
);
hw_by_page[0xf] = vtlb_RegisterHandler(
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_page_0F, _ext_memRead64<1>, _ext_memRead128<1>,
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_0F, _ext_memWrite64<1>, _ext_memWrite128<1>
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_page_0F, hwRead64_generic, hwRead128_generic,
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_0F, hwWrite64_generic, hwWrite128_generic
);
//////////////////////////////////////////////////////////////////////
// GS Optimized Mappings
tlb_fallback_6 = vtlb_RegisterHandler(
_ext_memRead8<6>, _ext_memRead16<6>, _ext_memRead32<6>, _ext_memRead64<6>, _ext_memRead128<6>,
_ext_memWrite8<6>, _ext_memWrite16<6>, _ext_memWrite32<6>, gsWrite64_generic, gsWrite128_generic
);
gs_page_0 = vtlb_RegisterHandler(
_ext_memRead8<6>, _ext_memRead16<6>, _ext_memRead32<6>, _ext_memRead64<6>, _ext_memRead128<6>,
_ext_memWrite8<6>, _ext_memWrite16<6>, _ext_memWrite32<6>, gsWrite64_page_00, gsWrite128_page_00
);
gs_page_1 = vtlb_RegisterHandler(
_ext_memRead8<6>, _ext_memRead16<6>, _ext_memRead32<6>, _ext_memRead64<6>, _ext_memRead128<6>,
_ext_memWrite8<6>, _ext_memWrite16<6>, _ext_memWrite32<6>, gsWrite64_page_01, gsWrite128_page_01
);
//vtlb_Reset();

View File

@ -33,9 +33,13 @@ namespace Path
{
#ifdef WIN32
static const char Separator = '\\';
// Path Separator used when creating new paths.
static const char Separator( '\\' );
// Path separators used when breaking existing paths into parts and pieces.
static const string Delimiters( "\\/" );
#else
static const char Separator = '/';
static const char Delimiters( '/' );
#endif
bool Exists( const string& path )
@ -130,7 +134,7 @@ void Combine( string& dest, const string& srcPath, const string& srcFile )
void ReplaceExtension( string& dest, const string& src, const string& ext )
{
int pos = src.find_last_of( '.' );
if( pos == 0 )
if( pos == string::npos || pos == 0 )
dest = src;
else
dest.assign( src.begin(), src.begin()+pos );
@ -142,4 +146,89 @@ void ReplaceExtension( string& dest, const string& src, const string& ext )
}
}
// finds the starting character position of a filename for the given source path.
static int _findFilenamePosition( const string& src)
{
// note: the source path could have multiple trailing slashes. We want to ignore those.
int startpos = src.find_last_not_of( Delimiters );
if(startpos == string::npos )
return 0;
int pos;
if( startpos < src.length() )
{
string trimmed( src.begin(), src.begin()+startpos );
pos = trimmed.find_last_of( Delimiters );
}
else
{
pos = src.find_last_of( Delimiters );
}
if( pos == string::npos )
return 0;
return pos;
}
void ReplaceFilename( string& dest, const string& src, const string& newfilename )
{
int pos = _findFilenamePosition( src );
if( pos == 0 )
dest = src;
else
dest.assign( src.begin(), src.begin()+pos );
if( !newfilename.empty() )
{
dest += '.';
dest += newfilename;
}
}
void GetFilename( const string& src, string& dest )
{
int pos = _findFilenamePosition( src );
dest.assign( src.begin()+pos, src.end() );
}
void GetDirectory( const string& src, string& dest )
{
int pos = _findFilenamePosition( src );
if( pos == 0 )
dest.clear();
else
dest.assign( src.begin(), src.begin()+pos );
}
void Split( const string& src, string& destpath, string& destfile )
{
int pos = _findFilenamePosition( src );
if( pos == 0 )
{
destpath.clear();
destfile = src;
}
else
{
destpath.assign( src.begin(), src.begin()+pos );
destfile.assign( src.begin()+pos, src.end() );
}
}
// Assigns the base/root directory of the given path into dest.
// Example /this/that/something.txt -> dest == "/"
void GetRootDirectory( const string& src, string& dest )
{
int pos = src.find_first_of( Delimiters );
if( pos == string::npos )
dest.clear();
else
dest.assign( src.begin(), src.begin()+pos );
}
}

View File

@ -20,14 +20,20 @@
namespace Path
{
void Combine( string& dest, const string& srcPath, const string& srcFile );
bool isRooted( const string& path );
bool isDirectory( const string& path );
bool isFile( const string& path );
bool Exists( const string& path );
int getFileSize( const string& path );
void Combine( std::string& dest, const std::string& srcPath, const std::string& srcFile );
bool isRooted( const std::string& path );
bool isDirectory( const std::string& path );
bool isFile( const std::string& path );
bool Exists( const std::string& path );
int getFileSize( const std::string& path );
void ReplaceExtension( std::string& dest, const std::string& src, const std::string& ext );
void ReplaceFilename( std::string& dest, const std::string& src, const std::string& newfilename );
void GetFilename( const std::string& src, std::string& dest );
void GetDirectory( const std::string& src, std::string& dest );
void GetRootDirectory( const std::string& src, std::string& dest );
void Split( const std::string& src, std::string& destpath, std::string& destfile );
void ReplaceExtension( string& dest, const string& src, const string& ext );
}
#endif

View File

@ -374,7 +374,9 @@ void hwConstRead64(u32 mem, int mmreg) {
PCSX2_ALIGNED16(u32 s_TempFIFO[4]);
void hwConstRead128(u32 mem, int xmmreg) {
if (mem >= 0x10004000 && mem < 0x10008000) {
// fixme : This needs to be updated to use the new paged FIFO accessors.
/*if (mem >= 0x10004000 && mem < 0x10008000) {
iFlushCall(0);
PUSH32I((uptr)&s_TempFIFO[0]);
PUSH32I(mem);
@ -382,7 +384,7 @@ void hwConstRead128(u32 mem, int xmmreg) {
ADD32ItoR(ESP, 8);
_eeReadConstMem128( xmmreg, (uptr)&s_TempFIFO[0]);
return;
}
}*/
_eeReadConstMem128( xmmreg, (uptr)PSM(mem));
}
@ -1125,7 +1127,9 @@ void hwConstWrite64(u32 mem, int mmreg)
void hwConstWrite128(u32 mem, int mmreg)
{
if (mem >= 0x10004000 && mem < 0x10008000) {
// fixme : This needs to be updated to use the new paged FIFO accessors.
/*if (mem >= 0x10004000 && mem < 0x10008000) {
_eeWriteConstMem128((uptr)&s_TempFIFO[0], mmreg);
iFlushCall(0);
PUSH32I((uptr)&s_TempFIFO[0]);
@ -1133,7 +1137,7 @@ void hwConstWrite128(u32 mem, int mmreg)
CALLFunc((uptr)WriteFIFO);
ADD32ItoR(ESP, 8);
return;
}
}*/
switch (mem) {
case 0x1000f590: // DMAC_ENABLEW

View File

@ -40,7 +40,7 @@ void recDoBranchImm( u32* jmpSkip, bool isLikely )
pc -= 4; // instruction rewinder for delay slot, if non-likely.
recompileNextInstruction(1);
}
SetBranchImm(pc);
SetBranchImm(pc); // start a new recompiled block.
}
void recDoBranchImm_Likely( u32* jmpSkip )

View File

@ -680,6 +680,11 @@ int recVUTransformAddr(int x86reg, VURegs* VU, int vireg, int imm)
SHL32ItoR(EAX, 4);
}
else {
// VU0 has a somewhat interesting memory mapping:
// if addr >= 0x4000, reads VU1's VF regs and VI regs
// if addr < 0x4000, wrap around at 0x1000
CMP32ItoR(EAX, 0x400);
pjmp[0] = JL8(0); // if addr >= 0x4000, reads VU1's VF regs and VI regs
AND32ItoR(EAX, 0x43f);

View File

@ -283,9 +283,9 @@ VuBaseBlock::VuBaseBlock()
#define SUPERVU_STACKSIZE 0x1000
static list<VuFunctionHeader*> s_listVUHeaders[2];
static list<VuFunctionHeader*>* s_plistCachedHeaders[2];
static VuFunctionHeader** recVUHeaders[2] = {NULL};
static VuBlockHeader* recVUBlocks[2] = {NULL};
static list<VuFunctionHeader*>* s_plistCachedHeaders[2] = {NULL, NULL};
static VuFunctionHeader** recVUHeaders[2] = {NULL,NULL};
static VuBlockHeader* recVUBlocks[2] = {NULL,NULL};
static u8* recVUStack = NULL, *recVUStackPtr = NULL;
static vector<_x86regs> s_vecRegArray(128);
@ -403,7 +403,11 @@ void SuperVUReset(int vuindex)
if( vuindex < 0 )
{
DbgCon::Status( "SuperVU reset > Resetting recompiler memory and structures." );
memset_8<0xcd, VU_EXESIZE>(s_recVUMem);
// Does this cause problems on VU recompiler resets? It could, if the VU works like
// the EE used to, and actually tries to re-enter the recBlock after issuing a clear. (air)
//memset_8<0xcd, VU_EXESIZE>(s_recVUMem);
memzero_ptr<SUPERVU_STACKSIZE>(recVUStack);
s_recVUPtr = s_recVUMem;
@ -795,9 +799,9 @@ static VuFunctionHeader* SuperVURecompileProgram(u32 startpc, int vuindex)
// if recPtr reached the mem limit reset whole mem
if ( ( (uptr)s_recVUPtr - (uptr)s_recVUMem ) >= VU_EXESIZE-0x40000 ) {
//SysPrintf("SuperVU reset mem\n");
SuperVUReset(-1);
SuperVUReset(0);
SuperVUReset(1);
SuperVUReset(-1);
if( s_TotalVUCycles > 0 ) {
// already executing, so return NULL
return NULL;