From 4524fd919e2cc91eb814914c3c51b15d891d027a Mon Sep 17 00:00:00 2001 From: "Jake.Stine" Date: Sun, 4 Jan 2009 06:38:22 +0000 Subject: [PATCH] *Experimental* Sync issues are very sensitive buggers. There could be some breakages in this revision, so keep an eye out, folks. Improved the responsiveness and efficiency of the EE's INTC handler by having it raise exceptions immediately in response to interrupt handlers (the old method delayed the exception until the next branch test, which meant that a lot of common interrupts like vsync, GS, GIF/VIF, etc resulted in two consecutive branch tests when they should have needed only one). Moved the gsIrq() in Counters.c from the vsyncStart() to the vsyncEnd(). The gsIrq() supposedly happens on the falling edge of the vsync, so this *should* be more correct. (but more correct doesn't always mean better) Added iopIntcTest() functions to the IOP's synchronization tools, so the IOP should now "correctly" raise exceptions when it re-enables pending IRQs. git-svn-id: http://pcsx2-playground.googlecode.com/svn/trunk@547 a6443dda-0b58-4228-96e9-037be469359c --- pcsx2/CDVD.cpp | 2 +- pcsx2/CdRom.cpp | 8 +- pcsx2/Counters.cpp | 28 +++++-- pcsx2/Hw.cpp | 75 ++++++----------- pcsx2/Memory.cpp | 37 ++++----- pcsx2/PsxCounters.cpp | 4 + pcsx2/PsxDma.cpp | 160 +++++++++++++++++------------------- pcsx2/PsxDma.h | 4 + pcsx2/PsxHw.cpp | 65 ++++++++++----- pcsx2/PsxSio2.cpp | 3 +- pcsx2/R3000A.cpp | 40 ++++++--- pcsx2/R3000A.h | 3 +- pcsx2/R5900.cpp | 145 +++++++++++++++++--------------- pcsx2/R5900.h | 1 + pcsx2/SPR.cpp | 2 +- pcsx2/Sio.cpp | 4 - pcsx2/x86/iHw.cpp | 40 ++++----- pcsx2/x86/iPsxHw.cpp | 36 ++++++-- pcsx2/x86/iR3000Atables.cpp | 5 ++ 19 files changed, 357 insertions(+), 305 deletions(-) diff --git a/pcsx2/CDVD.cpp b/pcsx2/CDVD.cpp index 1034734b61..6cf94718a2 100644 --- a/pcsx2/CDVD.cpp +++ b/pcsx2/CDVD.cpp @@ -206,7 +206,7 @@ static void CDVD_INT(int eCycle) static void cdvdSetIrq( uint id = (1< 0 ) { gsPostVsyncEnd( false ); diff --git a/pcsx2/Hw.cpp b/pcsx2/Hw.cpp index 90d513cbcc..7b424a3031 100644 --- a/pcsx2/Hw.cpp +++ b/pcsx2/Hw.cpp @@ -932,8 +932,7 @@ void hwWrite32(u32 mem, u32 value) { psHu16(0xe010)&= ~(value & 0xffff); // clear on 1 psHu16(0xe012) ^= (u16)(value >> 16); - if ((cpuRegs.CP0.n.Status.val & 0x10807) == 0x10801) - cpuTestDMACInts(); + cpuTestDMACInts(); break; //------------------------------------------------------------------ case 0x1000f000: // INTC_STAT @@ -945,7 +944,6 @@ void hwWrite32(u32 mem, u32 value) { case 0x1000f010: // INTC_MASK HW_LOG("INTC_MASK Write 32bit %x\n", value); psHu32(0xf010) ^= (u16)value; - cpuTestINTCInts(); break; //------------------------------------------------------------------ @@ -984,22 +982,18 @@ void hwWrite32(u32 mem, u32 value) { //------------------------------------------------------------------ case 0x1000f130: case 0x1000f410: -#ifdef PCSX2_DEVBUILD - HW_LOG("Unknown Hardware write 32 at %x with value %x (%x)\n", mem, value, cpuRegs.CP0.n.Status); -#endif + HW_LOG("Unknown Hardware write 32 at %x with value %x (%x)\n", mem, value, cpuRegs.CP0.n.Status.val); break; //------------------------------------------------------------------ default: #ifndef PCSX2_VIRTUAL_MEM - if (mem < 0x10010000) + if (mem < 0x10010000) #endif - { - psHu32(mem) = value; - } -#ifdef PCSX2_DEVBUILD - HW_LOG("Unknown Hardware write 32 at %x with value %x (%x)\n", mem, value, cpuRegs.CP0.n.Status); -#endif - break; + { + psHu32(mem) = value; + } + HW_LOG("Unknown Hardware write 32 at %x with value %x (%x)\n", mem, value, cpuRegs.CP0.n.Status.val); + break; } } @@ -1021,9 +1015,7 @@ void hwWrite64(u32 mem, u64 value) { switch (mem) { case GIF_CTRL: -#ifdef PCSX2_DEVBUILD - SysPrintf("GIF_CTRL write 64\n", value); -#endif + DevCon::Status("GIF_CTRL write 64", value); psHu32(mem) = value & 0x8; if(value & 0x1) { gsGIFReset(); @@ -1038,7 +1030,7 @@ void hwWrite64(u32 mem, u64 value) { case GIF_MODE: #ifdef GSPATH3FIX - SysPrintf("GIFMODE64 %x\n", value); + Console::Status("GIFMODE64 %x\n", value); #endif psHu64(GIF_MODE) = value; if (value & 0x1) psHu32(GIF_STAT)|= 0x1; @@ -1055,12 +1047,10 @@ void hwWrite64(u32 mem, u64 value) { DmaExec(dmaGIF, mem, value); break; -#ifdef HW_LOG case 0x1000e000: // DMAC_CTRL HW_LOG("DMAC_CTRL Write 64bit %x\n", value); psHu64(mem) = value; break; -#endif case 0x1000e010: // DMAC_STAT HW_LOG("DMAC_STAT Write 64bit %x\n", value); @@ -1073,8 +1063,7 @@ void hwWrite64(u32 mem, u64 value) { else psHu16(0xe012)|= 1<>16)&0x1f)].UL[0]); else if( IS_PSXCONSTREG(mmreg) ) AND16ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]); else AND16RtoM(mem, mmreg); break; - case 1: // and + case 1: // OR operation if( IS_EECONSTREG(mmreg) ) OR16ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); else if( IS_PSXCONSTREG(mmreg) ) OR16ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]); else OR16RtoM(mem, mmreg); break; - default: assert(0); + + jNO_DEFAULT } } @@ -2595,7 +2597,12 @@ static u8* m_psAllMem = NULL; int memInit() { #ifdef __LINUX__ - InstallLinuxExceptionHandler(); + struct sigaction sa; + + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_SIGINFO; + sa.sa_sigaction = &SysPageFaultExceptionFilter; + sigaction(SIGSEGV, &sa, NULL); #endif if (!vtlb_Init()) return -1; @@ -2923,29 +2930,14 @@ int SysPageFaultExceptionFilter(EXCEPTION_POINTERS* eps) } #else -#include "errno.h" - -__forceinline void __fastcall InstallLinuxExceptionHandler() -{ - struct sigaction sa; - - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_SIGINFO; - sa.sa_sigaction = &SysPageFaultExceptionFilter; - sigaction(SIGSEGV, &sa, NULL); -} // Linux implementation of SIGSEGV handler. Bind it using sigaction(). // This is my shot in the dark. Probably needs some work. Good luck! (air) __forceinline void __fastcall SysPageFaultExceptionFilter( int signal, siginfo_t *info, void * ) { - int err; - u32 pagesize = getpagesize(); - - //DevCon::Error("SysPageFaultExceptionFilter!"); + //Console::Error("SysPageFaultExceptionFilter!"); // get bad virtual address u32 offset = (u8*)info->si_addr - psM; - uptr pageoffset = ( offset / pagesize ) * pagesize; if (offset>=Ps2MemSize::Base) { @@ -2954,9 +2946,8 @@ __forceinline void __fastcall SysPageFaultExceptionFilter( int signal, siginfo_t assert( false ); } - err = mprotect( &psM[pageoffset], pagesize, PROT_READ | PROT_WRITE ); - if (err) DevCon::Error("SysPageFaultExceptionFilter: %s", strerror(errno)); - + mprotect(&psM[offset], 1, PROT_READ|PROT_WRITE); + offset>>=12; psMPWC[(offset/32)]|=(1<<(offset&31)); diff --git a/pcsx2/PsxCounters.cpp b/pcsx2/PsxCounters.cpp index fe734830a8..469b7a67cf 100644 --- a/pcsx2/PsxCounters.cpp +++ b/pcsx2/PsxCounters.cpp @@ -16,6 +16,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ +// Note on INTC usage: All counters code is always called from inside the context of an +// event test, so instead of using the iopTestIntc we just set the 0x1070 flags directly. +// The EventText function will pick it up. + #include "PrecompiledHeader.h" #include diff --git a/pcsx2/PsxDma.cpp b/pcsx2/PsxDma.cpp index 51d544dda0..49606afb8e 100644 --- a/pcsx2/PsxDma.cpp +++ b/pcsx2/PsxDma.cpp @@ -26,60 +26,72 @@ // Dma11/12 in PsxSio2.c int iopsifbusy[2] = { 0, 0 }; -void psxDma4(u32 madr, u32 bcr, u32 chcr) { // SPU - const int size = (bcr >> 16) * (bcr & 0xFFFF); // Number of blocks to transfer - /*if (chcr & 0x400) SysPrintf("SPU 2 DMA 4 linked list chain mode! chcr = %x madr = %x bcr = %x\n", chcr, madr, bcr); - if (chcr & 0x40000000) SysPrintf("SPU 2 DMA 4 Unusual bit set on 'to' direction chcr = %x madr = %x bcr = %x\n", chcr, madr, bcr); - if ((chcr & 0x1) == 0) SysPrintf("SPU 2 DMA 4 loading from spu2 memory chcr = %x madr = %x bcr = %x\n", chcr, madr, bcr);*/ +static void __fastcall psxDmaGeneric(u32 madr, u32 bcr, u32 chcr, u32 spuCore, _SPU2writeDMA4Mem spu2WriteFunc ) +{ + const char dmaNum = spuCore ? '7' : '4'; + /*if (chcr & 0x400) DevCon::Status("SPU 2 DMA %c linked list chain mode! chcr = %x madr = %x bcr = %x\n", dmaNum, chcr, madr, bcr); + if (chcr & 0x40000000) DevCon::Notice("SPU 2 DMA %c Unusual bit set on 'to' direction chcr = %x madr = %x bcr = %x\n", dmaNum, chcr, madr, bcr); + if ((chcr & 0x1) == 0) DevCon::Status("SPU 2 DMA %c loading from spu2 memory chcr = %x madr = %x bcr = %x\n", dmaNum, chcr, madr, bcr);*/ + + const int size = (bcr >> 16) * (bcr & 0xFFFF); + + // Update the spu2 to the current cycle before initiating the DMA if(SPU2async) - { - SPU2async(psxRegs.cycle - psxCounters[6].sCycleT); + { + SPU2async(psxRegs.cycle - psxCounters[6].sCycleT); + //Console::Status("cycles sent to SPU2 %x\n", psxRegs.cycle - psxCounters[6].sCycleT); - //SysPrintf("cycles sent to SPU2 %x\n", psxRegs.cycle - psxCounters[6].sCycleT); psxCounters[6].sCycleT = psxRegs.cycle; psxCounters[6].CycleT = size * 3; - + psxNextCounter -= (psxRegs.cycle-psxNextsCounter); psxNextsCounter = psxRegs.cycle; - if(psxCounters[6].CycleT < psxNextCounter) psxNextCounter = psxCounters[6].CycleT; + if(psxCounters[6].CycleT < psxNextCounter) + psxNextCounter = psxCounters[6].CycleT; } - switch (chcr) { - case 0x01000201: //cpu to spu transfer - PSXDMA_LOG("*** DMA 4 - SPU mem2spu *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); - //SysPrintf("DMA4 write blocks %x, size per block %x\n", (bcr >> 16), (bcr & 0xFFFF)); - - SPU2writeDMA4Mem((u16 *)PSXM(madr), size*2); - break; - case 0x01000200: //spu to cpu transfer - PSXDMA_LOG("*** DMA 4 - SPU spu2mem *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); - //SysPrintf("DMA4 read blocks %x, size per block %x\n", (bcr >> 16), (bcr & 0xFFFF)); - - SPU2readDMA4Mem((u16 *)PSXM(madr), size*2); - psxCpu->Clear(HW_DMA4_MADR, size); - break; + switch (chcr) + { + case 0x01000201: //cpu to spu2 transfer + PSXDMA_LOG("*** DMA %c - mem2spu *** %lx addr = %lx size = %lx\n", dmaNum, chcr, madr, bcr); + spu2WriteFunc((u16 *)PSXM(madr), size*2); + break; + + case 0x01000200: //spu2 to cpu transfer + PSXDMA_LOG("*** DMA %c - spu2mem *** %lx addr = %lx size = %lx\n", dmaNum, chcr, madr, bcr); + spu2WriteFunc((u16 *)PSXM(madr), size*2); + psxCpu->Clear(spuCore ? HW_DMA7_MADR : HW_DMA4_MADR, size); + break; default: - SysPrintf("*** DMA 4 - SPU unknown *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); - break; + Console::Error("*** DMA %c - SPU unknown *** %lx addr = %lx size = %lx\n", dmaNum, chcr, madr, bcr); + break; } } -int psxDma4Interrupt() { - HW_DMA4_CHCR &= ~0x01000000; - psxDmaInterrupt(4); - psxHu32(0x1070)|= 1<<9; - return 1; +void psxDma4(u32 madr, u32 bcr, u32 chcr) // SPU2's Core 0 +{ + psxDmaGeneric( madr, bcr, chcr, 0, SPU2writeDMA4Mem ); } -void psxDma2(u32 madr, u32 bcr, u32 chcr) { // GPU +int psxDma4Interrupt() +{ + HW_DMA4_CHCR &= ~0x01000000; + psxDmaInterrupt(4); + iopIntcIrq( 9 ); + return 1; +} + +void psxDma2(u32 madr, u32 bcr, u32 chcr) // GPU +{ HW_DMA2_CHCR &= ~0x01000000; psxDmaInterrupt(2); } -void psxDma6(u32 madr, u32 bcr, u32 chcr) { +void psxDma6(u32 madr, u32 bcr, u32 chcr) +{ u32 *mem = (u32 *)PSXM(madr); PSXDMA_LOG("*** DMA 6 - OT *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); @@ -98,50 +110,22 @@ void psxDma6(u32 madr, u32 bcr, u32 chcr) { psxDmaInterrupt(6); } -void psxDma7(u32 madr, u32 bcr, u32 chcr) { - int size = (bcr >> 16) * (bcr & 0xFFFF); - - if(SPU2async) - { - SPU2async(psxRegs.cycle - psxCounters[6].sCycleT); - - psxCounters[6].sCycleT = psxRegs.cycle; - psxCounters[6].CycleT = size * 3; - - psxNextCounter -= (psxRegs.cycle-psxNextsCounter); - psxNextsCounter = psxRegs.cycle; - if(psxCounters[6].CycleT < psxNextCounter) psxNextCounter = psxCounters[6].CycleT; - - } - - switch (chcr) { - case 0x01000201: //cpu to spu2 transfer - PSXDMA_LOG("*** DMA 7 - SPU2 mem2spu *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); - //SysPrintf("DMA7 write blocks %x, size per block %x\n", (bcr >> 16), (bcr & 0xFFFF)); - - SPU2writeDMA7Mem((u16 *)PSXM(madr), size*2); - break; - case 0x01000200: //spu2 to cpu transfer - PSXDMA_LOG("*** DMA 7 - SPU2 spu2mem *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); - //SysPrintf("DMA7 read blocks %x, size per block %x\n", (bcr >> 16), (bcr & 0xFFFF)); - - SPU2readDMA7Mem((u16 *)PSXM(madr), size*2); - psxCpu->Clear(HW_DMA7_MADR, size); - break; - default: - SysPrintf("*** DMA 7 - SPU unknown *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); - break; - } +void psxDma7(u32 madr, u32 bcr, u32 chcr) // SPU2's Core 1 +{ + psxDmaGeneric( madr, bcr, chcr, 1, SPU2writeDMA7Mem ); } -int psxDma7Interrupt() { - HW_DMA7_CHCR &= ~0x01000000; - psxDmaInterrupt2(0); - return 1; +int psxDma7Interrupt() +{ + HW_DMA7_CHCR &= ~0x01000000; + psxDmaInterrupt2(0); + //iopIntcIrq( 9 ); + return 1; } extern int eesifbusy[2]; -void psxDma9(u32 madr, u32 bcr, u32 chcr) { +void psxDma9(u32 madr, u32 bcr, u32 chcr) +{ SIF_LOG("IOP: dmaSIF0 chcr = %lx, madr = %lx, bcr = %lx, tadr = %lx\n", chcr, madr, bcr, HW_DMA9_TADR); iopsifbusy[0] = 1; @@ -171,25 +155,23 @@ void psxDma10(u32 madr, u32 bcr, u32 chcr) { } void psxDma8(u32 madr, u32 bcr, u32 chcr) { - int size; + + const int size = (bcr >> 16) * (bcr & 0xFFFF) * 8; switch (chcr & 0x01000201) { case 0x01000201: //cpu to dev9 transfer PSXDMA_LOG("*** DMA 8 - DEV9 mem2dev9 *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); + DEV9writeDMA8Mem((u32*)PSXM(madr), size); + break; - size = (bcr >> 16) * (bcr & 0xFFFF); // Number of blocks to transfer - DEV9writeDMA8Mem((u32*)PSXM(madr), size*8); - break; case 0x01000200: //dev9 to cpu transfer PSXDMA_LOG("*** DMA 8 - DEV9 dev9mem *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); + DEV9readDMA8Mem((u32*)PSXM(madr), size); + break; - size = (bcr >> 16) * (bcr & 0xFFFF); // Number of blocks to transfer - - DEV9readDMA8Mem((u32*)PSXM(madr), size*8); - break; default: PSXDMA_LOG("*** DMA 8 - DEV9 unknown *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); - break; + break; } HW_DMA8_CHCR &= ~0x01000000; psxDmaInterrupt2(1); @@ -198,8 +180,8 @@ void psxDma8(u32 madr, u32 bcr, u32 chcr) { void dev9Interrupt() { if( (dev9Handler != NULL) && (dev9Handler() != 1) ) return; - - psxHu32(0x1070)|= 1<<13; + + iopIntcIrq( 13 ); hwIntcIrq(INTC_SBUS); } @@ -211,7 +193,7 @@ void usbInterrupt() { if( usbHandler != NULL && (usbHandler() != 1) ) return; - psxHu32(0x1070)|= 1<<22; + iopIntcIrq( 22 ); hwIntcIrq(INTC_SBUS); } @@ -220,7 +202,7 @@ void usbIrq(int cycles) { } void fwIrq() { - psxHu32(0x1070)|= 1<<24; + iopIntcIrq( 24 ); hwIntcIrq(INTC_SBUS); } @@ -239,6 +221,12 @@ void spu2DMA7Irq() { } void spu2Irq() { - psxHu32(0x1070)|= 1<<9; + iopIntcIrq( 9 ); hwIntcIrq(INTC_SBUS); } + +void iopIntcIrq( uint irqType ) +{ + psxHu32(0x1070)|= 1<= 0x1f801600 && add < 0x1f801700) { USBwrite16(add, value); return; } -#ifdef PCSX2_DEVBUILD - if((add & 0xf) == 0x9) SysPrintf("16bit write (possible chcr set) %x value %x\n", add, value); -#endif + + if((add & 0xf) == 0x9) DevCon::WriteLn("16bit write (possible chcr set) %x value %x", add, value); + switch (add) { case 0x1f801040: sioWrite8((u8)value); @@ -741,13 +741,23 @@ void psxHwWrite16(u32 add, u16 value) { // if (Config.SpuIrq) psxHu16(0x1070) |= 0x200; psxHu16(0x1070) &= value; return; - case 0x1f801074: PSXHW_LOG("IMASK 16bit write %x\n", value); + + case 0x1f801074: + PSXHW_LOG("IMASK 16bit write %x\n", value); psxHu16(0x1074) = value; + iopTestIntc(); + return; + + case 0x1f801078: // see the 32-bit version for notes! + PSXHW_LOG("ICTRL 16bit write %x\n", value); + psxHu16(0x1078) = value; + iopTestIntc(); return; case 0x1f8010c4: PSXHW_LOG("DMA4 BCR_size 16bit write %lx\n", value); - psxHu16(0x10c4) = value; return; // DMA4 bcr_size + psxHu16(0x10c4) = value; + return; // DMA4 bcr_size case 0x1f8010c6: PSXHW_LOG("DMA4 BCR_count 16bit write %lx\n", value); @@ -868,6 +878,7 @@ void psxHwWrite32(u32 add, u32 value) { psxHu32(add) = value; return; // Ram size +//------------------------------------------------------------------ case 0x1f801070: PSXHW_LOG("IREG 32bit write %lx\n", value); // if (Config.Sio) psxHu32(0x1070) |= 0x80; @@ -878,13 +889,16 @@ void psxHwWrite32(u32 add, u32 value) { case 0x1f801074: PSXHW_LOG("IMASK 32bit write %lx\n", value); psxHu32(0x1074) = value; + iopTestIntc(); return; case 0x1f801078: PSXHW_LOG("ICTRL 32bit write %lx\n", value); - psxHu32(0x1078) = value;//1; //According to pSXAuthor this allways becomes 1 on write, but MHPB won't boot if value is not writen ;p + psxHu32(0x1078) = value; //1; //According to pSXAuthor this allways becomes 1 on write, but MHPB won't boot if value is not writen ;p + iopTestIntc(); return; +//------------------------------------------------------------------ //SSBus registers case 0x1f801000: psxHu32(0x1000) = value; @@ -958,6 +972,8 @@ void psxHwWrite32(u32 add, u32 value) { psxHu32(0x1420) = value; PSXHW_LOG("SSBUS 32bit write %lx\n", value); return; + +//------------------------------------------------------------------ case 0x1f801080: PSXHW_LOG("DMA0 MADR 32bit write %lx\n", value); HW_DMA0_MADR = value; return; // DMA0 madr @@ -970,6 +986,7 @@ void psxHwWrite32(u32 add, u32 value) { // DmaExec(0); return; +//------------------------------------------------------------------ case 0x1f801090: PSXHW_LOG("DMA1 MADR 32bit write %lx\n", value); HW_DMA1_MADR = value; return; // DMA1 madr @@ -982,6 +999,7 @@ void psxHwWrite32(u32 add, u32 value) { // DmaExec(1); return; +//------------------------------------------------------------------ case 0x1f8010a0: PSXHW_LOG("DMA2 MADR 32bit write %lx\n", value); HW_DMA2_MADR = value; return; // DMA2 madr @@ -994,6 +1012,7 @@ void psxHwWrite32(u32 add, u32 value) { DmaExec(2); return; +//------------------------------------------------------------------ case 0x1f8010b0: PSXHW_LOG("DMA3 MADR 32bit write %lx\n", value); HW_DMA3_MADR = value; return; // DMA3 madr @@ -1007,6 +1026,7 @@ void psxHwWrite32(u32 add, u32 value) { return; +//------------------------------------------------------------------ case 0x1f8010c0: PSXHW_LOG("DMA4 MADR 32bit write %lx\n", value); SPU2WriteMemAddr(0,value); @@ -1020,6 +1040,7 @@ void psxHwWrite32(u32 add, u32 value) { DmaExec(4); return; +//------------------------------------------------------------------ #if 0 case 0x1f8010d0: break; //DMA5write_madr(); case 0x1f8010d4: break; //DMA5write_bcr(); @@ -1038,6 +1059,7 @@ void psxHwWrite32(u32 add, u32 value) { DmaExec(6); return; +//------------------------------------------------------------------ case 0x1f801500: PSXHW_LOG("DMA7 MADR 32bit write %lx\n", value); SPU2WriteMemAddr(1,value); @@ -1051,6 +1073,7 @@ void psxHwWrite32(u32 add, u32 value) { DmaExec2(7); return; +//------------------------------------------------------------------ case 0x1f801510: PSXHW_LOG("DMA8 MADR 32bit write %lx\n", value); HW_DMA8_MADR = value; return; // DMA8 madr @@ -1063,6 +1086,7 @@ void psxHwWrite32(u32 add, u32 value) { DmaExec2(8); return; +//------------------------------------------------------------------ case 0x1f801520: PSXHW_LOG("DMA9 MADR 32bit write %lx\n", value); HW_DMA9_MADR = value; return; // DMA9 madr @@ -1078,6 +1102,7 @@ void psxHwWrite32(u32 add, u32 value) { PSXHW_LOG("DMA9 TADR 32bit write %lx\n", value); HW_DMA9_TADR = value; return; // DMA9 tadr +//------------------------------------------------------------------ case 0x1f801530: PSXHW_LOG("DMA10 MADR 32bit write %lx\n", value); HW_DMA10_MADR = value; return; // DMA10 madr @@ -1090,6 +1115,7 @@ void psxHwWrite32(u32 add, u32 value) { DmaExec2(10); return; +//------------------------------------------------------------------ case 0x1f801540: PSXHW_LOG("DMA11 SIO2in MADR 32bit write %lx\n", value); HW_DMA11_MADR = value; return; @@ -1103,6 +1129,7 @@ void psxHwWrite32(u32 add, u32 value) { DmaExec2(11); return; +//------------------------------------------------------------------ case 0x1f801550: PSXHW_LOG("DMA12 SIO2out MADR 32bit write %lx\n", value); HW_DMA12_MADR = value; return; @@ -1116,6 +1143,7 @@ void psxHwWrite32(u32 add, u32 value) { DmaExec2(12); return; +//------------------------------------------------------------------ case 0x1f801570: psxHu32(0x1570) = value; PSXHW_LOG("DMA PCR2 32bit write %lx\n", value); @@ -1130,17 +1158,18 @@ void psxHwWrite32(u32 add, u32 value) { { u32 tmp = (~value) & HW_DMA_ICR; HW_DMA_ICR = ((tmp ^ value) & 0xffffff) ^ tmp; - return; } + return; case 0x1f801574: PSXHW_LOG("DMA ICR2 32bit write %lx\n", value); { u32 tmp = (~value) & HW_DMA_ICR2; HW_DMA_ICR2 = ((tmp ^ value) & 0xffffff) ^ tmp; - return; } + return; +//------------------------------------------------------------------ /* case 0x1f801810: PSXHW_LOG("GPU DATA 32bit write %lx\n", value); GPU_writeData(value); return; @@ -1213,9 +1242,10 @@ void psxHwWrite32(u32 add, u32 value) { PSXCNT_LOG("COUNTER 5 TARGET 32bit write %lx\n", value); psxRcntWtarget32(5, value); return; +//------------------------------------------------------------------ case 0x1f8014c0: PSXHW_LOG("RTC_HOLDMODE 32bit write %lx\n", value); - SysPrintf("RTC_HOLDMODE 32bit write %lx\n", value); + Console::Notice("** RTC_HOLDMODE 32bit write %lx", value); break; case 0x1f801450: @@ -1230,6 +1260,7 @@ void psxHwWrite32(u32 add, u32 value) { psxHu32(0x1450) = /*(*/value/* & (~0x8)) | (psxHu32(0x1450) & 0x8)*/; return; +//------------------------------------------------------------------ case 0x1F808200: case 0x1F808204: case 0x1F808208: @@ -1279,6 +1310,7 @@ void psxHwWrite32(u32 add, u32 value) { PSXHW_LOG("SIO2 write INTR <- %lx\n", value); sio2_setIntr(value); return; +//------------------------------------------------------------------ default: psxHu32(add) = value; PSXHW_LOG("*Unknown 32bit write at address %lx value %lx\n", add, value); @@ -1350,20 +1382,13 @@ void psxHw4Write8(u32 add, u8 value) { case 0x1f40200A: cdvdWrite0A(value); return; case 0x1f40200F: cdvdWrite0F(value); return; case 0x1f402014: cdvdWrite14(value); return; - case 0x1f402016: - cdvdWrite16(value); - //fixme - are these supposed to be here? - FreezeMMXRegs(0); - FreezeXMMRegs(0); - return; + case 0x1f402016: cdvdWrite16(value); return; case 0x1f402017: cdvdWrite17(value); return; case 0x1f402018: cdvdWrite18(value); return; case 0x1f40203A: cdvdWrite3A(value); return; default: - // note: use SysPrintF to notify console since this is a potentially serious - // emulation problem: //PSXHW_LOG("*Unknown 8bit write at address %lx value %x\n", add, value); - SysPrintf("*Unknown 8bit write at address %lx value %x\n", add, value); + Console::Notice("*Unknown 8bit write at address %lx value %x", add, value); return; } PSXHW_LOG("*Known 8bit write at address %lx value %x\n", add, value); @@ -1373,7 +1398,7 @@ void psxDmaInterrupt(int n) { if (HW_DMA_ICR & (1 << (16 + n))) { HW_DMA_ICR|= (1 << (24 + n)); psxRegs.CP0.n.Cause |= 1 << (9 + n); - psxHu32(0x1070) |= 8; + iopIntcIrq( 3 ); } } @@ -1387,6 +1412,6 @@ void psxDmaInterrupt2(int n) { }*/ HW_DMA_ICR2|= (1 << (24 + n)); psxRegs.CP0.n.Cause |= 1 << (16 + n); - psxHu32(0x1070) |= 8; + iopIntcIrq( 3 ); } } diff --git a/pcsx2/PsxSio2.cpp b/pcsx2/PsxSio2.cpp index bf899b5d46..29f84f8fe1 100644 --- a/pcsx2/PsxSio2.cpp +++ b/pcsx2/PsxSio2.cpp @@ -117,8 +117,7 @@ void sio2_setCtrl(u32 value){ if (sio2.ctrl & 1){ //recv packet //handle data that had been sent - //trigger interupt for SIO2 - psxHu32(0x1070)|=0x20000; + iopIntcIrq( 17 ); //SBUS sio2.recvIndex=0; sio2.ctrl &= ~1; diff --git a/pcsx2/R3000A.cpp b/pcsx2/R3000A.cpp index 7c118a4a02..b91f4fbf5b 100644 --- a/pcsx2/R3000A.cpp +++ b/pcsx2/R3000A.cpp @@ -43,8 +43,9 @@ s32 psxCycleEE = -1; // Used to signal to the EE when important actions that need IOP-attention have // happened (hsyncs, vsyncs, IOP exceptions, etc). IOP runs code whenever this // is true, even if it's already running ahead a bit. -int iopBranchAction = 0; +bool iopBranchAction = false; +bool iopEventTestIsActive = false; PCSX2_ALIGNED16(psxRegisters psxRegs); @@ -245,25 +246,38 @@ void psxBranchTest() if( psxTestCycle( psxNextsCounter, psxNextCounter ) ) { psxRcntUpdate(); - iopBranchAction = 1; + iopBranchAction = true; } // start the next branch at the next counter event by default // the interrupt code below will assign nearer branches if needed. g_psxNextBranchCycle = psxNextsCounter+psxNextCounter; - if (psxRegs.interrupt) _psxTestInterrupts(); - - if (psxHu32(0x1078)) { - if(psxHu32(0x1070) & psxHu32(0x1074)){ - if ((psxRegs.CP0.n.Status & 0xFE01) >= 0x401) - { -// PSXCPU_LOG("Interrupt: %x %x\n", HWMu32(0x1070), HWMu32(0x1074)); - psxException(0, 0); - iopBranchAction = 1; - } - } + if (psxRegs.interrupt) + { + iopEventTestIsActive = true; + _psxTestInterrupts(); + iopEventTestIsActive = false; } + + if( psxHu32(0x1078) == 0 ) return; + if( (psxHu32(0x1070) & psxHu32(0x1074)) == 0 ) return; + + if ((psxRegs.CP0.n.Status & 0xFE01) >= 0x401) + { +// PSXCPU_LOG("Interrupt: %x %x\n", HWMu32(0x1070), HWMu32(0x1074)); + psxException(0, 0); + iopBranchAction = true; + } +} + +void iopTestIntc() +{ + if( iopEventTestIsActive ) return; + if( psxHu32(0x1078) == 0 ) return; + if( (psxHu32(0x1070) & psxHu32(0x1074)) == 0 ) return; + + psxSetNextBranchDelta( 4 ); } void psxExecuteBios() { diff --git a/pcsx2/R3000A.h b/pcsx2/R3000A.h index eb397c0f0a..edce3e05c3 100644 --- a/pcsx2/R3000A.h +++ b/pcsx2/R3000A.h @@ -214,6 +214,7 @@ void psxExecuteBios(); extern s32 psxNextCounter; extern u32 psxNextsCounter; -extern int iopBranchAction; +extern bool iopBranchAction; +extern bool iopEventTestIsActive; #endif /* __R3000A_H__ */ diff --git a/pcsx2/R5900.cpp b/pcsx2/R5900.cpp index f8700bc6e3..fdffee82d9 100644 --- a/pcsx2/R5900.cpp +++ b/pcsx2/R5900.cpp @@ -45,6 +45,8 @@ u32 bExecBIOS = 0; // set if the BIOS has already been executed static bool cpuIsInitialized = false; static uint eeWaitCycles = 1024; +bool eeEventTestIsActive = false; + #ifdef _DEBUG extern u32 s_vucount; #endif @@ -208,7 +210,7 @@ void cpuException(u32 code, u32 bd) { } } else { offset = 0x180; //Overrride the cause - SysPrintf("cpuException: Status.EXL = 1 cause %x\n", code); + Console::Notice("cpuException: Status.EXL = 1 cause %x", code); } if (cpuRegs.CP0.n.Status.b.BEV == 0) { cpuRegs.pc = 0x80000000 + offset; @@ -216,7 +218,7 @@ void cpuException(u32 code, u32 bd) { cpuRegs.pc = 0xBFC00200 + offset; } } else { //Error Level 2 - Console::Error("FIX ME: Level 2 cpuException"); + Console::Error("*PCSX2* FIX ME: Level 2 cpuException"); if((code & 0x38000) <= 0x8000 ) { //Reset / NMI cpuRegs.pc = 0xBFC00000; Console::Notice("Reset request"); @@ -430,10 +432,6 @@ static __forceinline void _cpuTestInterrupts() TESTINT(10, vifMFIFOInterrupt); TESTINT(11, gifMFIFOInterrupt); } - - if ((cpuRegs.CP0.n.Status.val & 0x10007) != 0x10001) return; - TESTINT(30, intcInterrupt); - TESTINT(31, dmacInterrupt); } u32 s_iLastCOP0Cycle = 0; @@ -450,8 +448,9 @@ static __forceinline void _cpuTestTIMR() // the Count or Compare registers are modified. if ( (cpuRegs.CP0.n.Status.val & 0x8000) && - cpuRegs.CP0.n.Count >= cpuRegs.CP0.n.Compare && cpuRegs.CP0.n.Count < cpuRegs.CP0.n.Compare+1000 ) { - SysPrintf("timr intr: %x, %x\n", cpuRegs.CP0.n.Count, cpuRegs.CP0.n.Compare); + cpuRegs.CP0.n.Count >= cpuRegs.CP0.n.Compare && cpuRegs.CP0.n.Count < cpuRegs.CP0.n.Compare+1000 ) + { + Console::Status("timr intr: %x, %x", cpuRegs.CP0.n.Count, cpuRegs.CP0.n.Compare); cpuException(0x808000, cpuRegs.branch); } } @@ -473,11 +472,6 @@ static __forceinline void _cpuTestPERF() } } -// Maximum wait between branches. Lower values provide a tighter synchronization between -// the EE and the IOP, but incur more execution overhead. -//#define EE_WAIT_CYCLE 3072 // 2048 is probably stable now, but starting low first - - // if cpuRegs.cycle is greater than this cycle, should check cpuBranchTest for updates u32 g_nextBranchCycle = 0; @@ -485,6 +479,7 @@ u32 g_nextBranchCycle = 0; // and the recompiler. (moved here to help alleviate redundant code) static __forceinline void _cpuBranchTest_Shared() { + eeEventTestIsActive = true; g_nextBranchCycle = cpuRegs.cycle + eeWaitCycles; EEsCycle += cpuRegs.cycle - EEoCycle; @@ -504,10 +499,6 @@ static __forceinline void _cpuBranchTest_Shared() _cpuTestTIMR(); - //#ifdef CPU_LOG - // cpuTestMissingHwInts(); - //#endif - // ---- Interrupts ------------- if( cpuRegs.interrupt ) @@ -537,41 +528,6 @@ static __forceinline void _cpuBranchTest_Shared() psxCpu->ExecuteBlock(); } - // The IOP cound be running ahead/behind of us, so adjust the iop's next branch by its - // relative position to the EE (via EEsCycle) - cpuSetNextBranchDelta( ((g_psxNextBranchCycle-psxRegs.cycle)*8) - EEsCycle ); - - // Apply the hsync counter's nextCycle - cpuSetNextBranch( counters[4].sCycle, counters[4].CycleT ); - - // Apply vsync and other counter nextCycles - cpuSetNextBranch( nextsCounter, nextCounter ); -} - -#ifdef PCSX2_DEVBUILD -extern u8 g_globalXMMSaved; -extern u8 g_globalMMXSaved; -#endif - -void cpuBranchTest() -{ - // cpuBranchTest should be called from the recompiler only. - assert( Cpu == &recCpu ); - -#ifdef PCSX2_DEVBUILD - // dont' remove this check unless doing an official release - if( g_globalXMMSaved || g_globalMMXSaved) - SysPrintf("frozen regs have not been restored!!!\n"); - assert( !g_globalXMMSaved && !g_globalMMXSaved); -#endif - - // Don't need to freeze any regs during a BranchTest. - // Everything has been flushed already. - g_EEFreezeRegs = false; - - // Perform counters, ints, and IOP updates: - _cpuBranchTest_Shared(); - // ---- VU0 ------------- if (VU0.VI[REG_VPU_STAT].UL & 0x1) @@ -590,6 +546,56 @@ void cpuBranchTest() // one shot always. That is, when a program is executed the VU1 doesn't even // bother to return until the program is completely finished. + // ---- Schedule Next Event Test -------------- + + // The IOP cound be running ahead/behind of us, so adjust the iop's next branch by its + // relative position to the EE (via EEsCycle) + cpuSetNextBranchDelta( ((g_psxNextBranchCycle-psxRegs.cycle)*8) - EEsCycle ); + + // Apply the hsync counter's nextCycle + cpuSetNextBranch( counters[4].sCycle, counters[4].CycleT ); + + // Apply vsync and other counter nextCycles + cpuSetNextBranch( nextsCounter, nextCounter ); + + eeEventTestIsActive = false; + + // ---- INTC / DMAC Exceptions ----------------- + // Raise the INTC and DMAC interrupts here, which usually throw exceptions. + // This should be done last since the IOP and the VU0 can raise several EE + // exceptions. + + if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001) + { + TESTINT(30, intcInterrupt); + TESTINT(31, dmacInterrupt); + } +} + +#ifdef PCSX2_DEVBUILD +extern u8 g_globalXMMSaved; +extern u8 g_globalMMXSaved; +#endif + +void cpuBranchTest() +{ + // cpuBranchTest should be called from the recompiler only. + assert( Cpu == &recCpu ); + +#ifdef PCSX2_DEVBUILD + // dont' remove this check unless doing an official release + if( g_globalXMMSaved || g_globalMMXSaved) + DevCon::Error("Pcsx2 Foopah! Frozen regs have not been restored!!!"); + assert( !g_globalXMMSaved && !g_globalMMXSaved); +#endif + + // Don't need to freeze any regs during a BranchTest. + // Everything has been flushed already. + g_EEFreezeRegs = false; + + // Perform counters, ints, and IOP updates: + _cpuBranchTest_Shared(); + #ifdef PCSX2_DEVBUILD assert( !g_globalXMMSaved && !g_globalMMXSaved); #endif @@ -616,28 +622,37 @@ __forceinline void CPU_INT( u32 n, s32 ecycle) cpuSetNextBranchDelta( cpuRegs.eCycle[n] ); } -__forceinline void cpuTestINTCInts() { +void cpuTestINTCInts() +{ + if( cpuRegs.interrupt & (1 << 30) ) return; if( (cpuRegs.CP0.n.Status.val & 0x10407) != 0x10401 ) return; if( (psHu32(INTC_STAT) & psHu32(INTC_MASK)) == 0 ) return; - if( cpuRegs.interrupt & (1 << 30) ) return; - // fixme: The counters code throws INT30's alot, and most of the time they're - // "late" already, so firing them immediately instead of after the next branch - // (in which case they'll be really late) would be a lot better in theory. - // However, setting this to zero for everything breaks games, so if it's done - // it needs to be done for counters only. + cpuRegs.interrupt|= 1 << 30; + cpuRegs.sCycle[30] = cpuRegs.cycle; + cpuRegs.eCycle[30] = 0; - CPU_INT(30,4); + // only set the next branch delta if the exception won't be handled for + // the current branch... + if( !eeEventTestIsActive ) + cpuSetNextBranchDelta( 4 ); } __forceinline void cpuTestDMACInts() { - if ((cpuRegs.CP0.n.Status.val & 0x10807) != 0x10801) return; if ( cpuRegs.interrupt & (1 << 31) ) return; + if ((cpuRegs.CP0.n.Status.val & 0x10807) != 0x10801) return; if ( ( (psHu16(0xe012) & psHu16(0xe010)) == 0) && ( (psHu16(0xe010) & 0x8000) == 0) ) return; - CPU_INT(31, 4); + cpuRegs.interrupt|= 1 << 31; + cpuRegs.sCycle[31] = cpuRegs.cycle; + cpuRegs.eCycle[31] = 0; + + // only set the next branch delta if the exception won't be handled for + // the current branch... + if( !eeEventTestIsActive ) + cpuSetNextBranchDelta( 4 ); } __forceinline void cpuTestTIMRInts() { @@ -711,11 +726,5 @@ void IntcpuBranchTest() } - // fixme: why is this in the interpreter but not in the recompiler? (Air) - - if (VU0.VI[REG_VPU_STAT].UL & 0x100) { - Cpu->ExecuteVU1Block(); - } - g_EEFreezeRegs = true; } diff --git a/pcsx2/R5900.h b/pcsx2/R5900.h index bf9ffa0870..2b1961e03a 100644 --- a/pcsx2/R5900.h +++ b/pcsx2/R5900.h @@ -127,6 +127,7 @@ struct cpuRegisters { extern s32 EEsCycle; extern u32 EEoCycle; +extern bool eeEventTestIsActive; extern PCSX2_ALIGNED16_DECL(cpuRegisters cpuRegs); // used for optimization diff --git a/pcsx2/SPR.cpp b/pcsx2/SPR.cpp index 3dd1c8b973..8e63fd26b2 100644 --- a/pcsx2/SPR.cpp +++ b/pcsx2/SPR.cpp @@ -128,7 +128,7 @@ void _SPR0interleave() { CPU_INT(8, cycles); } -void _dmaSPR0() { +static __forceinline void _dmaSPR0() { if ((psHu32(DMAC_CTRL) & 0x30) == 0x20) { // STS == fromSPR diff --git a/pcsx2/Sio.cpp b/pcsx2/Sio.cpp index 9fa3a7eaed..c2ca550f68 100644 --- a/pcsx2/Sio.cpp +++ b/pcsx2/Sio.cpp @@ -517,10 +517,6 @@ void SIO_FORCEINLINE sioInterrupt() { void SaveState::sioFreeze() { - // eh, not supported anymore.. :) - //if( Mode == 0 && dwCurSaveStateVer == 0x7a30000e ) - // savesize -= 4; - if( IsLoading() ) sio.count = 0; Freeze( sio ); diff --git a/pcsx2/x86/iHw.cpp b/pcsx2/x86/iHw.cpp index 435d538c4b..fc9216d40b 100644 --- a/pcsx2/x86/iHw.cpp +++ b/pcsx2/x86/iHw.cpp @@ -497,7 +497,8 @@ static void __fastcall PrintDebug(u8 value) } // fixme: this would be more optimal as a C++ template (with bit as the template parameter) -static __forceinline void ConstWrite_ExecTimer( uptr func, u8 index, u8 bit, int mmreg) +template< uint bit > +static void ConstWrite_ExecTimer( uptr func, u8 index, int mmreg) { if( bit != 32 ) { @@ -518,23 +519,23 @@ static __forceinline void ConstWrite_ExecTimer( uptr func, u8 index, u8 bit, int } #define CONSTWRITE_TIMERS(bit) \ - case 0x10000000: ConstWrite_ExecTimer((uptr)&rcntWcount, 0, bit, mmreg); break; \ - case 0x10000010: ConstWrite_ExecTimer((uptr)&rcntWmode, 0, bit, mmreg); break; \ - case 0x10000020: ConstWrite_ExecTimer((uptr)&rcntWtarget, 0, bit, mmreg); break; \ - case 0x10000030: ConstWrite_ExecTimer((uptr)&rcntWhold, 0, bit, mmreg); break; \ + case 0x10000000: ConstWrite_ExecTimer((uptr)&rcntWcount, 0, mmreg); break; \ + case 0x10000010: ConstWrite_ExecTimer((uptr)&rcntWmode, 0, mmreg); break; \ + case 0x10000020: ConstWrite_ExecTimer((uptr)&rcntWtarget, 0, mmreg); break; \ + case 0x10000030: ConstWrite_ExecTimer((uptr)&rcntWhold, 0, mmreg); break; \ \ - case 0x10000800: ConstWrite_ExecTimer((uptr)&rcntWcount, 1, bit, mmreg); break; \ - case 0x10000810: ConstWrite_ExecTimer((uptr)&rcntWmode, 1, bit, mmreg); break; \ - case 0x10000820: ConstWrite_ExecTimer((uptr)&rcntWtarget, 1, bit, mmreg); break; \ - case 0x10000830: ConstWrite_ExecTimer((uptr)&rcntWhold, 1, bit, mmreg); break; \ + case 0x10000800: ConstWrite_ExecTimer((uptr)&rcntWcount, 1, mmreg); break; \ + case 0x10000810: ConstWrite_ExecTimer((uptr)&rcntWmode, 1, mmreg); break; \ + case 0x10000820: ConstWrite_ExecTimer((uptr)&rcntWtarget, 1, mmreg); break; \ + case 0x10000830: ConstWrite_ExecTimer((uptr)&rcntWhold, 1, mmreg); break; \ \ - case 0x10001000: ConstWrite_ExecTimer((uptr)&rcntWcount, 2, bit, mmreg); break; \ - case 0x10001010: ConstWrite_ExecTimer((uptr)&rcntWmode, 2, bit, mmreg); break; \ - case 0x10001020: ConstWrite_ExecTimer((uptr)&rcntWtarget, 2, bit, mmreg); break; \ + case 0x10001000: ConstWrite_ExecTimer((uptr)&rcntWcount, 2, mmreg); break; \ + case 0x10001010: ConstWrite_ExecTimer((uptr)&rcntWmode, 2, mmreg); break; \ + case 0x10001020: ConstWrite_ExecTimer((uptr)&rcntWtarget, 2, mmreg); break; \ \ - case 0x10001800: ConstWrite_ExecTimer((uptr)&rcntWcount, 3, bit, mmreg); break; \ - case 0x10001810: ConstWrite_ExecTimer((uptr)&rcntWmode, 3, bit, mmreg); break; \ - case 0x10001820: ConstWrite_ExecTimer((uptr)&rcntWtarget, 3, bit, mmreg); break; \ + case 0x10001800: ConstWrite_ExecTimer((uptr)&rcntWcount, 3, mmreg); break; \ + case 0x10001810: ConstWrite_ExecTimer((uptr)&rcntWmode, 3, mmreg); break; \ + case 0x10001820: ConstWrite_ExecTimer((uptr)&rcntWtarget, 3, mmreg); break; \ void hwConstWrite8(u32 mem, int mmreg) { @@ -971,11 +972,10 @@ void hwConstWrite32(u32 mem, int mmreg) _eeMoveMMREGtoR(EAX, mmreg); iFlushCall(0); MOV32RtoR(ECX, EAX); - NOT32R(ECX); - AND16RtoM((uptr)&PS2MEM_HW[0xe010], ECX); - SHR32ItoR(EAX, 16); + NOT32R(ECX); XOR16RtoM((uptr)&PS2MEM_HW[0xe012], EAX); + AND16RtoM((uptr)&PS2MEM_HW[0xe010], ECX); CALLFunc((uptr)cpuTestDMACInts); break; @@ -1164,11 +1164,11 @@ void hwConstWrite64(u32 mem, int mmreg) iFlushCall(0); MOV32RtoR(ECX, EAX); + SHR32ItoR(EAX, 16); NOT32R(ECX); + XOR16RtoM((uptr)&PS2MEM_HW[0xe012], EAX); AND16RtoM((uptr)&PS2MEM_HW[0xe010], ECX); - SHR32ItoR(EAX, 16); - XOR16RtoM((uptr)&PS2MEM_HW[0xe012], EAX); CALLFunc((uptr)cpuTestDMACInts); break; diff --git a/pcsx2/x86/iPsxHw.cpp b/pcsx2/x86/iPsxHw.cpp index 68d1c7f0dd..550e7602eb 100644 --- a/pcsx2/x86/iPsxHw.cpp +++ b/pcsx2/x86/iPsxHw.cpp @@ -610,8 +610,21 @@ void psxHwConstWrite16(u32 add, int mmreg) { _eeWriteConstMem16((uptr)&sio.BaudReg, mmreg); return; - case 0x1f801070: - _eeWriteConstMem16OP((uptr)&psxH[(add) & 0xffff], mmreg, 0); + case 0x1f801070: + _eeWriteConstMem16OP((uptr)&psxHu32(0x1070), mmreg, 0); // AND operation + return; + + case 0x1f801074: + _eeWriteConstMem16((uptr)&psxHu32(0x1074), mmreg); + iFlushCall(0); + CALLFunc( (uptr)&iopTestIntc ); + return; + + case 0x1f801078: + //According to pSXAuthor this allways becomes 1 on write, but MHPB won't boot if value is not writen ;p + _eeWriteConstMem16((uptr)&psxHu32(0x1078), mmreg); + iFlushCall(0); + CALLFunc( (uptr)&iopTestIntc ); return; // counters[0] @@ -807,7 +820,20 @@ void psxHwConstWrite32(u32 add, int mmreg) return; case 0x1f801070: - _eeWriteConstMem32OP((uptr)&psxH[(add) & 0xffff], mmreg, 0); // and + _eeWriteConstMem32OP((uptr)&psxHu32(0x1070), mmreg, 0); // and + return; + + case 0x1f801074: + _eeWriteConstMem32((uptr)&psxHu32(0x1074), mmreg); + iFlushCall(0); + CALLFunc( (uptr)&iopTestIntc ); + return; + + case 0x1f801078: + //According to pSXAuthor this allways becomes 1 on write, but MHPB won't boot if value is not writen ;p + _eeWriteConstMem32((uptr)&psxHu32(0x1078), mmreg); + iFlushCall(0); + CALLFunc( (uptr)&iopTestIntc ); return; // case 0x1f801088: @@ -1123,7 +1149,7 @@ int psxHw4ConstRead8(u32 x86reg, u32 add, u32 sign) { case 0x1f402039: CONSTREAD8_CALL((uptr)cdvdRead39); return 1; case 0x1f40203A: CONSTREAD8_CALL((uptr)cdvdRead3A); return 1; default: - SysPrintf("*Unknown 8bit read at address %lx\n", add); + Console::Notice("*Unknown 8bit read at address %lx\n", add); XOR32RtoR(x86reg, x86reg); return 0; } @@ -1147,7 +1173,7 @@ void psxHw4ConstWrite8(u32 add, int mmreg) { case 0x1f402018: CONSTWRITE_CALL(cdvdWrite18); return; case 0x1f40203A: CONSTWRITE_CALL(cdvdWrite3A); return; default: - SysPrintf("*Unknown 8bit write at address %lx\n", add); + Console::Notice("*Unknown 8bit write at address %lx\n", add); return; } } diff --git a/pcsx2/x86/iR3000Atables.cpp b/pcsx2/x86/iR3000Atables.cpp index 8be0d93056..d733662aa5 100644 --- a/pcsx2/x86/iR3000Atables.cpp +++ b/pcsx2/x86/iR3000Atables.cpp @@ -1761,6 +1761,11 @@ void rpsxRFE() SHR32ItoR(ECX, 2); OR32RtoR (EAX, ECX); MOV32RtoM((uptr)&psxRegs.CP0.n.Status, EAX); + + // Test the IOP's INTC status, so that any pending ints get raised. + + _psxFlushCall(0); + CALLFunc( (uptr)&iopTestIntc ); } // R3000A tables