diff --git a/pcsx2/FiFo.cpp b/pcsx2/FiFo.cpp index a2a4baf255..100b45f5da 100644 --- a/pcsx2/FiFo.cpp +++ b/pcsx2/FiFo.cpp @@ -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) ); + + VIF_LOG("ReadFIFO/VIF0 0x%08X\n", mem); + //out[0] = psHu64(mem ); + //out[1] = psHu64(mem+8); - 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) { - - 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 __fastcall WriteFIFO_page_5(u32 mem, const mem128_t *value) +{ + jASSUME( (mem >= 0x10005000) && (mem < 0x10006000) ); + + VIF_LOG("WriteFIFO/VIF1, addr=0x%08X\n", mem); + + //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 WriteFIFO(u32 mem, const u64 *value) { - int ret; +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); - if ((mem >= 0x10004000) && (mem < 0x10005000)) { - VIF_LOG("WriteFIFO VIF0 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(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); +} + +void __fastcall WriteFIFO_page_7(u32 mem, const mem128_t *value) +{ + jASSUME( (mem >= 0x10007000) && (mem < 0x10008000) ); - psHu64(mem ) = value[0]; - psHu64(mem+8) = value[1]; + // All addresses in this page map to 0x7000 and 0x7010: + mem &= 0x10; - if( mtgsThread != NULL ) + 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) { -} diff --git a/pcsx2/GS.cpp b/pcsx2/GS.cpp index 0c7d6a2360..7c0bb58e63 100644 --- a/pcsx2/GS.cpp +++ b/pcsx2/GS.cpp @@ -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; - - case 0x12000020: // GS_SMODE2 - if(value & 0x1) Config.PsxType |= 2; // Interlaced - else Config.PsxType &= ~2; // Non-Interlaced - break; - - case 0x12001000: // GS_CSR + _gsSMODEwrite( mem, value ); + + 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) { diff --git a/pcsx2/GS.h b/pcsx2/GS.h index 4570ad44e4..157749788e 100644 --- a/pcsx2/GS.h +++ b/pcsx2/GS.h @@ -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); diff --git a/pcsx2/Hw.cpp b/pcsx2/Hw.cpp index 0cea5ff0ee..257386a4a3 100644 --- a/pcsx2/Hw.cpp +++ b/pcsx2/Hw.cpp @@ -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<= 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<= 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 \ No newline at end of file diff --git a/pcsx2/Hw.h b/pcsx2/Hw.h index ee15b2288e..e0dee83883 100644 --- a/pcsx2/Hw.h +++ b/pcsx2/Hw.h @@ -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); diff --git a/pcsx2/Memory.cpp b/pcsx2/Memory.cpp index 89f9a65b43..7212f54f50 100644 --- a/pcsx2/Memory.cpp +++ b/pcsx2/Memory.cpp @@ -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 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 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 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(); diff --git a/pcsx2/PathUtils.cpp b/pcsx2/PathUtils.cpp index 0a20cc21db..65684816a8 100644 --- a/pcsx2/PathUtils.cpp +++ b/pcsx2/PathUtils.cpp @@ -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 ) } } -} \ No newline at end of file +// 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 ); +} +} diff --git a/pcsx2/Paths.h b/pcsx2/Paths.h index 1756733e24..b78616da6c 100644 --- a/pcsx2/Paths.h +++ b/pcsx2/Paths.h @@ -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 diff --git a/pcsx2/x86/iHw.cpp b/pcsx2/x86/iHw.cpp index c43d0d5063..fe5fe243cb 100644 --- a/pcsx2/x86/iHw.cpp +++ b/pcsx2/x86/iHw.cpp @@ -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 diff --git a/pcsx2/x86/iR5900Misc.cpp b/pcsx2/x86/iR5900Misc.cpp index 8972efbdaa..cd5eda0607 100644 --- a/pcsx2/x86/iR5900Misc.cpp +++ b/pcsx2/x86/iR5900Misc.cpp @@ -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 ) diff --git a/pcsx2/x86/iVUmicroLower.cpp b/pcsx2/x86/iVUmicroLower.cpp index 5def6d51e3..673163da0e 100644 --- a/pcsx2/x86/iVUmicroLower.cpp +++ b/pcsx2/x86/iVUmicroLower.cpp @@ -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); diff --git a/pcsx2/x86/iVUzerorec.cpp b/pcsx2/x86/iVUzerorec.cpp index cf7f3b10f2..89c76b0f52 100644 --- a/pcsx2/x86/iVUzerorec.cpp +++ b/pcsx2/x86/iVUzerorec.cpp @@ -283,9 +283,9 @@ VuBaseBlock::VuBaseBlock() #define SUPERVU_STACKSIZE 0x1000 static list s_listVUHeaders[2]; -static list* s_plistCachedHeaders[2]; -static VuFunctionHeader** recVUHeaders[2] = {NULL}; -static VuBlockHeader* recVUBlocks[2] = {NULL}; +static list* 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(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;