*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
This commit is contained in:
Jake.Stine 2009-01-04 06:38:22 +00:00 committed by Gregory Hainaut
parent bbfb6ac41a
commit 4524fd919e
19 changed files with 357 additions and 305 deletions

View File

@ -206,7 +206,7 @@ static void CDVD_INT(int eCycle)
static void cdvdSetIrq( uint id = (1<<Irq_CommandComplete) ) static void cdvdSetIrq( uint id = (1<<Irq_CommandComplete) )
{ {
cdvd.PwOff |= id; cdvd.PwOff |= id;
psxHu32(0x1070)|= 0x4; iopIntcIrq( 2 );
hwIntcIrq(INTC_SBUS); hwIntcIrq(INTC_SBUS);
psxSetNextBranchDelta( 20 ); psxSetNextBranchDelta( 20 );
} }

View File

@ -489,7 +489,8 @@ void cdrInterrupt() {
break; break;
} }
if (cdr.Stat != NoIntr && cdr.Reg2 != 0x18) psxHu32(0x1070)|=0x4; if (cdr.Stat != NoIntr && cdr.Reg2 != 0x18)
psxHu32(0x1070)|= 0x4;
CDR_LOG("Cdr Interrupt %x\n", Irq); CDR_LOG("Cdr Interrupt %x\n", Irq);
} }
@ -554,7 +555,7 @@ void cdrReadInterrupt() {
CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime); CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime);
} }
psxHu32(0x1070)|=0x4; psxHu32(0x1070)|= 0x4;
return; return;
} }
@ -827,7 +828,8 @@ void cdrWrite1(u8 rt) {
CDR_LOG("Unknown Cmd: %x\n", cdr.Cmd); CDR_LOG("Unknown Cmd: %x\n", cdr.Cmd);
return; return;
} }
if (cdr.Stat != NoIntr) psxHu32(0x1070)|=0x4; if (cdr.Stat != NoIntr)
iopIntcIrq( 2 );
} }
u8 cdrRead2(void) { u8 cdrRead2(void) {

View File

@ -391,24 +391,38 @@ static __forceinline void frameLimit()
} }
} }
static __forceinline void VSyncStart(u32 sCycle)
static __forceinline void VSyncStart(u32 sCycle) // VSync Start
{ {
vSyncDebugStuff(); // EE Profiling and Debug code vSyncDebugStuff(); // EE Profiling and Debug code
if ((CSRw & 0x8)) GSCSRr|= 0x8;
if (!(GSIMR&0x800)) gsIrq(); //GS Irq
hwIntcIrq(2); // HW Irq // HACK : For some inexplicable reason, having the IntcIrq(2) handled during the
psxVBlankStart(); // psxCounters vBlank Start // current Event Test breaks some games (Grandia 2 at bootup). I can't fathom why.
// To fix I fool the Intc handler into thinking that we're not in an event test, so
// that it schedules the handler into the future by 4 cycles. (air)
eeEventTestIsActive = false;
hwIntcIrq(2);
eeEventTestIsActive = true;
psxVBlankStart();
if (gates) rcntStartGate(0x8, sCycle); // Counters Start Gate code if (gates) rcntStartGate(0x8, sCycle); // Counters Start Gate code
if (Config.Patch) applypatch(1); // Apply patches (ToDo: clean up patch code) if (Config.Patch) applypatch(1); // Apply patches (ToDo: clean up patch code)
cpuRegs.eCycle[30] = 8;
} }
static __forceinline void VSyncEnd(u32 sCycle) // VSync End static __forceinline void VSyncEnd(u32 sCycle)
{ {
iFrame++; iFrame++;
// I moved the gsIrq trigger to the falling edge, where I've been told it is
// more correct. (air)
if ((CSRw & 0x8)) GSCSRr|= 0x8;
if (!(GSIMR&0x800)) gsIrq();
if( g_vu1SkipCount > 0 ) if( g_vu1SkipCount > 0 )
{ {
gsPostVsyncEnd( false ); gsPostVsyncEnd( false );

View File

@ -932,8 +932,7 @@ void hwWrite32(u32 mem, u32 value) {
psHu16(0xe010)&= ~(value & 0xffff); // clear on 1 psHu16(0xe010)&= ~(value & 0xffff); // clear on 1
psHu16(0xe012) ^= (u16)(value >> 16); psHu16(0xe012) ^= (u16)(value >> 16);
if ((cpuRegs.CP0.n.Status.val & 0x10807) == 0x10801) cpuTestDMACInts();
cpuTestDMACInts();
break; break;
//------------------------------------------------------------------ //------------------------------------------------------------------
case 0x1000f000: // INTC_STAT case 0x1000f000: // INTC_STAT
@ -945,7 +944,6 @@ void hwWrite32(u32 mem, u32 value) {
case 0x1000f010: // INTC_MASK case 0x1000f010: // INTC_MASK
HW_LOG("INTC_MASK Write 32bit %x\n", value); HW_LOG("INTC_MASK Write 32bit %x\n", value);
psHu32(0xf010) ^= (u16)value; psHu32(0xf010) ^= (u16)value;
cpuTestINTCInts(); cpuTestINTCInts();
break; break;
//------------------------------------------------------------------ //------------------------------------------------------------------
@ -984,22 +982,18 @@ void hwWrite32(u32 mem, u32 value) {
//------------------------------------------------------------------ //------------------------------------------------------------------
case 0x1000f130: case 0x1000f130:
case 0x1000f410: case 0x1000f410:
#ifdef PCSX2_DEVBUILD HW_LOG("Unknown Hardware write 32 at %x with value %x (%x)\n", mem, value, cpuRegs.CP0.n.Status.val);
HW_LOG("Unknown Hardware write 32 at %x with value %x (%x)\n", mem, value, cpuRegs.CP0.n.Status);
#endif
break; break;
//------------------------------------------------------------------ //------------------------------------------------------------------
default: default:
#ifndef PCSX2_VIRTUAL_MEM #ifndef PCSX2_VIRTUAL_MEM
if (mem < 0x10010000) if (mem < 0x10010000)
#endif #endif
{ {
psHu32(mem) = value; 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.val);
HW_LOG("Unknown Hardware write 32 at %x with value %x (%x)\n", mem, value, cpuRegs.CP0.n.Status); break;
#endif
break;
} }
} }
@ -1021,9 +1015,7 @@ void hwWrite64(u32 mem, u64 value) {
switch (mem) { switch (mem) {
case GIF_CTRL: case GIF_CTRL:
#ifdef PCSX2_DEVBUILD DevCon::Status("GIF_CTRL write 64", value);
SysPrintf("GIF_CTRL write 64\n", value);
#endif
psHu32(mem) = value & 0x8; psHu32(mem) = value & 0x8;
if(value & 0x1) { if(value & 0x1) {
gsGIFReset(); gsGIFReset();
@ -1038,7 +1030,7 @@ void hwWrite64(u32 mem, u64 value) {
case GIF_MODE: case GIF_MODE:
#ifdef GSPATH3FIX #ifdef GSPATH3FIX
SysPrintf("GIFMODE64 %x\n", value); Console::Status("GIFMODE64 %x\n", value);
#endif #endif
psHu64(GIF_MODE) = value; psHu64(GIF_MODE) = value;
if (value & 0x1) psHu32(GIF_STAT)|= 0x1; if (value & 0x1) psHu32(GIF_STAT)|= 0x1;
@ -1055,12 +1047,10 @@ void hwWrite64(u32 mem, u64 value) {
DmaExec(dmaGIF, mem, value); DmaExec(dmaGIF, mem, value);
break; break;
#ifdef HW_LOG
case 0x1000e000: // DMAC_CTRL case 0x1000e000: // DMAC_CTRL
HW_LOG("DMAC_CTRL Write 64bit %x\n", value); HW_LOG("DMAC_CTRL Write 64bit %x\n", value);
psHu64(mem) = value; psHu64(mem) = value;
break; break;
#endif
case 0x1000e010: // DMAC_STAT case 0x1000e010: // DMAC_STAT
HW_LOG("DMAC_STAT Write 64bit %x\n", value); HW_LOG("DMAC_STAT Write 64bit %x\n", value);
@ -1073,8 +1063,7 @@ void hwWrite64(u32 mem, u64 value) {
else psHu16(0xe012)|= 1<<i; else psHu16(0xe012)|= 1<<i;
} }
} }
if ((cpuRegs.CP0.n.Status.val & 0x10807) == 0x10801) cpuTestDMACInts();
cpuTestDMACInts();
break; break;
case 0x1000f590: // DMAC_ENABLEW case 0x1000f590: // DMAC_ENABLEW
@ -1084,17 +1073,17 @@ void hwWrite64(u32 mem, u64 value) {
case 0x1000f000: // INTC_STAT case 0x1000f000: // INTC_STAT
HW_LOG("INTC_STAT Write 64bit %x\n", value); HW_LOG("INTC_STAT Write 64bit %x\n", value);
psHu32(0xf000)&=~value; psHu32(INTC_STAT)&=~value;
cpuTestINTCInts(); cpuTestINTCInts();
break; break;
case 0x1000f010: // INTC_MASK case 0x1000f010: // INTC_MASK
HW_LOG("INTC_MASK Write 32bit %x\n", value); HW_LOG("INTC_MASK Write 32bit %x\n", value);
for (i=0; i<16; i++) { // reverse on 1 for (i=0; i<16; i++) { // reverse on 1
int s = (1<<i); const int s = (1<<i);
if (value & s) { if (value & s) {
if (psHu32(0xf010) & (1<<i)) psHu32(0xf010)&= ~(1<<i); if (psHu32(INTC_MASK) & s) psHu32(INTC_MASK)&= ~s;
else psHu32(0xf010)|= 1<<i; else psHu32(INTC_MASK)|= s;
} }
} }
cpuTestINTCInts(); cpuTestINTCInts();
@ -1104,12 +1093,11 @@ void hwWrite64(u32 mem, u64 value) {
case 0x1000f410: case 0x1000f410:
case 0x1000f430: case 0x1000f430:
break; break;
default: default:
psHu64(mem) = value; psHu64(mem) = value;
#ifdef PCSX2_DEVBUILD HW_LOG("Unknown Hardware write 64 at %x with value %x (status=%x)\n",mem,value, cpuRegs.CP0.n.Status.val);
HW_LOG("Unknown Hardware write 64 at %x with value %x (status=%x)\n",mem,value, cpuRegs.CP0.n.Status);
#endif
break; break;
} }
} }
@ -1134,9 +1122,7 @@ void hwWrite128(u32 mem, const u64 *value) {
psHu64(mem ) = value[0]; psHu64(mem ) = value[0];
psHu64(mem+8) = value[1]; psHu64(mem+8) = value[1];
#ifdef PCSX2_DEVBUILD 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);
HW_LOG("Unknown Hardware write 128 at %x with value %x_%x (status=%x)\n", mem, value[1], value[0], cpuRegs.CP0.n.Status);
#endif
break; break;
} }
} }
@ -1146,7 +1132,7 @@ __forceinline void intcInterrupt() {
if ((cpuRegs.CP0.n.Status.val & 0x400) != 0x400) return; if ((cpuRegs.CP0.n.Status.val & 0x400) != 0x400) return;
if ((psHu32(INTC_STAT)) == 0) { if ((psHu32(INTC_STAT)) == 0) {
SysPrintf("*PCSX2*: intcInterrupt already cleared\n"); DevCon::Notice("*PCSX2*: intcInterrupt already cleared");
return; return;
} }
if ((psHu32(INTC_STAT) & psHu32(INTC_MASK)) == 0) return; if ((psHu32(INTC_STAT) & psHu32(INTC_MASK)) == 0) return;
@ -1160,24 +1146,13 @@ __forceinline void intcInterrupt() {
cpuException(0x400, cpuRegs.branch); cpuException(0x400, cpuRegs.branch);
} }
// fixme: dead/unused code?
/*void dmacTestInterrupt() {
cpuRegs.interrupt &= ~(1 << 31);
if ((cpuRegs.CP0.n.Status.val & 0x800) != 0x800) return;
if ((psHu16(0xe012) & psHu16(0xe010) ||
psHu16(0xe010) & 0x8000) == 0) return;
if((psHu32(DMAC_CTRL) & 0x1) == 0) return;
}*/
__forceinline void dmacInterrupt() __forceinline void dmacInterrupt()
{ {
cpuRegs.interrupt &= ~(1 << 31); cpuRegs.interrupt &= ~(1 << 31);
if ((cpuRegs.CP0.n.Status.val & 0x10807) != 0x10801) return; if ((cpuRegs.CP0.n.Status.val & 0x10807) != 0x10801) return;
if ((psHu16(0xe012) & psHu16(0xe010) || if( ((psHu16(0xe012) & psHu16(0xe010)) == 0 ) &&
psHu16(0xe010) & 0x8000) == 0) return; ( psHu16(0xe010) & 0x8000) == 0 ) return;
if((psHu32(DMAC_CTRL) & 0x1) == 0) return; if((psHu32(DMAC_CTRL) & 0x1) == 0) return;
@ -1188,10 +1163,8 @@ __forceinline void dmacInterrupt()
} }
void hwIntcIrq(int n) { void hwIntcIrq(int n) {
//if( psHu32(INTC_MASK) & (1<<n) ) { psHu32(INTC_STAT)|= 1<<n;
psHu32(INTC_STAT)|= 1<<n; cpuTestINTCInts();
cpuTestINTCInts();
//}
} }
void hwDmacIrq(int n) { void hwDmacIrq(int n) {

View File

@ -722,21 +722,23 @@ void _eeWriteConstMem16(u32 mem, int mmreg)
else MOV16RtoM(mem, mmreg); else MOV16RtoM(mem, mmreg);
} }
// op - 0 for AND, 1 for OR
void _eeWriteConstMem16OP(u32 mem, int mmreg, int op) void _eeWriteConstMem16OP(u32 mem, int mmreg, int op)
{ {
assert( !IS_XMMREG(mmreg) && !IS_MMXREG(mmreg) ); assert( !IS_XMMREG(mmreg) && !IS_MMXREG(mmreg) );
switch(op) { switch(op) {
case 0: // and case 0: // AND operation
if( IS_EECONSTREG(mmreg) ) AND16ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); if( IS_EECONSTREG(mmreg) ) AND16ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]);
else if( IS_PSXCONSTREG(mmreg) ) AND16ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]); else if( IS_PSXCONSTREG(mmreg) ) AND16ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]);
else AND16RtoM(mem, mmreg); else AND16RtoM(mem, mmreg);
break; break;
case 1: // and case 1: // OR operation
if( IS_EECONSTREG(mmreg) ) OR16ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); 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 if( IS_PSXCONSTREG(mmreg) ) OR16ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]);
else OR16RtoM(mem, mmreg); else OR16RtoM(mem, mmreg);
break; break;
default: assert(0);
jNO_DEFAULT
} }
} }
@ -2595,7 +2597,12 @@ static u8* m_psAllMem = NULL;
int memInit() int memInit()
{ {
#ifdef __LINUX__ #ifdef __LINUX__
InstallLinuxExceptionHandler(); struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = &SysPageFaultExceptionFilter;
sigaction(SIGSEGV, &sa, NULL);
#endif #endif
if (!vtlb_Init()) return -1; if (!vtlb_Init()) return -1;
@ -2923,29 +2930,14 @@ int SysPageFaultExceptionFilter(EXCEPTION_POINTERS* eps)
} }
#else #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(). // Linux implementation of SIGSEGV handler. Bind it using sigaction().
// This is my shot in the dark. Probably needs some work. Good luck! (air) // This is my shot in the dark. Probably needs some work. Good luck! (air)
__forceinline void __fastcall SysPageFaultExceptionFilter( int signal, siginfo_t *info, void * ) __forceinline void __fastcall SysPageFaultExceptionFilter( int signal, siginfo_t *info, void * )
{ {
int err; //Console::Error("SysPageFaultExceptionFilter!");
u32 pagesize = getpagesize();
//DevCon::Error("SysPageFaultExceptionFilter!");
// get bad virtual address // get bad virtual address
u32 offset = (u8*)info->si_addr - psM; u32 offset = (u8*)info->si_addr - psM;
uptr pageoffset = ( offset / pagesize ) * pagesize;
if (offset>=Ps2MemSize::Base) if (offset>=Ps2MemSize::Base)
{ {
@ -2954,9 +2946,8 @@ __forceinline void __fastcall SysPageFaultExceptionFilter( int signal, siginfo_t
assert( false ); assert( false );
} }
err = mprotect( &psM[pageoffset], pagesize, PROT_READ | PROT_WRITE ); mprotect(&psM[offset], 1, PROT_READ|PROT_WRITE);
if (err) DevCon::Error("SysPageFaultExceptionFilter: %s", strerror(errno));
offset>>=12; offset>>=12;
psMPWC[(offset/32)]|=(1<<(offset&31)); psMPWC[(offset/32)]|=(1<<(offset&31));

View File

@ -16,6 +16,10 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 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 "PrecompiledHeader.h"
#include <math.h> #include <math.h>

View File

@ -26,60 +26,72 @@
// Dma11/12 in PsxSio2.c // Dma11/12 in PsxSio2.c
int iopsifbusy[2] = { 0, 0 }; 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); static void __fastcall psxDmaGeneric(u32 madr, u32 bcr, u32 chcr, u32 spuCore, _SPU2writeDMA4Mem spu2WriteFunc )
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);*/ 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) 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].sCycleT = psxRegs.cycle;
psxCounters[6].CycleT = size * 3; psxCounters[6].CycleT = size * 3;
psxNextCounter -= (psxRegs.cycle-psxNextsCounter); psxNextCounter -= (psxRegs.cycle-psxNextsCounter);
psxNextsCounter = psxRegs.cycle; psxNextsCounter = psxRegs.cycle;
if(psxCounters[6].CycleT < psxNextCounter) psxNextCounter = psxCounters[6].CycleT; if(psxCounters[6].CycleT < psxNextCounter)
psxNextCounter = psxCounters[6].CycleT;
} }
switch (chcr) { switch (chcr)
case 0x01000201: //cpu to spu transfer {
PSXDMA_LOG("*** DMA 4 - SPU mem2spu *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); case 0x01000201: //cpu to spu2 transfer
//SysPrintf("DMA4 write blocks %x, size per block %x\n", (bcr >> 16), (bcr & 0xFFFF)); PSXDMA_LOG("*** DMA %c - mem2spu *** %lx addr = %lx size = %lx\n", dmaNum, chcr, madr, bcr);
spu2WriteFunc((u16 *)PSXM(madr), size*2);
SPU2writeDMA4Mem((u16 *)PSXM(madr), size*2); break;
break;
case 0x01000200: //spu to cpu transfer case 0x01000200: //spu2 to cpu transfer
PSXDMA_LOG("*** DMA 4 - SPU spu2mem *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); PSXDMA_LOG("*** DMA %c - spu2mem *** %lx addr = %lx size = %lx\n", dmaNum, chcr, madr, bcr);
//SysPrintf("DMA4 read blocks %x, size per block %x\n", (bcr >> 16), (bcr & 0xFFFF)); spu2WriteFunc((u16 *)PSXM(madr), size*2);
psxCpu->Clear(spuCore ? HW_DMA7_MADR : HW_DMA4_MADR, size);
SPU2readDMA4Mem((u16 *)PSXM(madr), size*2); break;
psxCpu->Clear(HW_DMA4_MADR, size);
break;
default: default:
SysPrintf("*** DMA 4 - SPU unknown *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); Console::Error("*** DMA %c - SPU unknown *** %lx addr = %lx size = %lx\n", dmaNum, chcr, madr, bcr);
break; break;
} }
} }
int psxDma4Interrupt() { void psxDma4(u32 madr, u32 bcr, u32 chcr) // SPU2's Core 0
HW_DMA4_CHCR &= ~0x01000000; {
psxDmaInterrupt(4); psxDmaGeneric( madr, bcr, chcr, 0, SPU2writeDMA4Mem );
psxHu32(0x1070)|= 1<<9;
return 1;
} }
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; HW_DMA2_CHCR &= ~0x01000000;
psxDmaInterrupt(2); psxDmaInterrupt(2);
} }
void psxDma6(u32 madr, u32 bcr, u32 chcr) { void psxDma6(u32 madr, u32 bcr, u32 chcr)
{
u32 *mem = (u32 *)PSXM(madr); u32 *mem = (u32 *)PSXM(madr);
PSXDMA_LOG("*** DMA 6 - OT *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); 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); psxDmaInterrupt(6);
} }
void psxDma7(u32 madr, u32 bcr, u32 chcr) { void psxDma7(u32 madr, u32 bcr, u32 chcr) // SPU2's Core 1
int size = (bcr >> 16) * (bcr & 0xFFFF); {
psxDmaGeneric( madr, bcr, chcr, 1, SPU2writeDMA7Mem );
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;
}
} }
int psxDma7Interrupt() { int psxDma7Interrupt()
HW_DMA7_CHCR &= ~0x01000000; {
psxDmaInterrupt2(0); HW_DMA7_CHCR &= ~0x01000000;
return 1; psxDmaInterrupt2(0);
//iopIntcIrq( 9 );
return 1;
} }
extern int eesifbusy[2]; 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); SIF_LOG("IOP: dmaSIF0 chcr = %lx, madr = %lx, bcr = %lx, tadr = %lx\n", chcr, madr, bcr, HW_DMA9_TADR);
iopsifbusy[0] = 1; iopsifbusy[0] = 1;
@ -171,25 +155,23 @@ void psxDma10(u32 madr, u32 bcr, u32 chcr) {
} }
void psxDma8(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) { switch (chcr & 0x01000201) {
case 0x01000201: //cpu to dev9 transfer case 0x01000201: //cpu to dev9 transfer
PSXDMA_LOG("*** DMA 8 - DEV9 mem2dev9 *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); 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 case 0x01000200: //dev9 to cpu transfer
PSXDMA_LOG("*** DMA 8 - DEV9 dev9mem *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); 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: default:
PSXDMA_LOG("*** DMA 8 - DEV9 unknown *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); PSXDMA_LOG("*** DMA 8 - DEV9 unknown *** %lx addr = %lx size = %lx\n", chcr, madr, bcr);
break; break;
} }
HW_DMA8_CHCR &= ~0x01000000; HW_DMA8_CHCR &= ~0x01000000;
psxDmaInterrupt2(1); psxDmaInterrupt2(1);
@ -198,8 +180,8 @@ void psxDma8(u32 madr, u32 bcr, u32 chcr) {
void dev9Interrupt() { void dev9Interrupt() {
if( (dev9Handler != NULL) && (dev9Handler() != 1) ) if( (dev9Handler != NULL) && (dev9Handler() != 1) )
return; return;
psxHu32(0x1070)|= 1<<13; iopIntcIrq( 13 );
hwIntcIrq(INTC_SBUS); hwIntcIrq(INTC_SBUS);
} }
@ -211,7 +193,7 @@ void usbInterrupt() {
if( usbHandler != NULL && (usbHandler() != 1) ) if( usbHandler != NULL && (usbHandler() != 1) )
return; return;
psxHu32(0x1070)|= 1<<22; iopIntcIrq( 22 );
hwIntcIrq(INTC_SBUS); hwIntcIrq(INTC_SBUS);
} }
@ -220,7 +202,7 @@ void usbIrq(int cycles) {
} }
void fwIrq() { void fwIrq() {
psxHu32(0x1070)|= 1<<24; iopIntcIrq( 24 );
hwIntcIrq(INTC_SBUS); hwIntcIrq(INTC_SBUS);
} }
@ -239,6 +221,12 @@ void spu2DMA7Irq() {
} }
void spu2Irq() { void spu2Irq() {
psxHu32(0x1070)|= 1<<9; iopIntcIrq( 9 );
hwIntcIrq(INTC_SBUS); hwIntcIrq(INTC_SBUS);
} }
void iopIntcIrq( uint irqType )
{
psxHu32(0x1070)|= 1<<irqType;
iopTestIntc();
}

View File

@ -37,6 +37,10 @@ void usbIrq(int cycles);
void fwIrq(); void fwIrq();
void spu2Irq(); void spu2Irq();
extern void iopIntcIrq( uint irqType );
extern void iopTestIntc();
extern DEV9handler dev9Handler; extern DEV9handler dev9Handler;
extern USBhandler usbHandler; extern USBhandler usbHandler;

View File

@ -704,9 +704,9 @@ void psxHwWrite16(u32 add, u16 value) {
if (add >= 0x1f801600 && add < 0x1f801700) { if (add >= 0x1f801600 && add < 0x1f801700) {
USBwrite16(add, value); return; USBwrite16(add, value); return;
} }
#ifdef PCSX2_DEVBUILD
if((add & 0xf) == 0x9) SysPrintf("16bit write (possible chcr set) %x value %x\n", add, value); if((add & 0xf) == 0x9) DevCon::WriteLn("16bit write (possible chcr set) %x value %x", add, value);
#endif
switch (add) { switch (add) {
case 0x1f801040: case 0x1f801040:
sioWrite8((u8)value); sioWrite8((u8)value);
@ -741,13 +741,23 @@ void psxHwWrite16(u32 add, u16 value) {
// if (Config.SpuIrq) psxHu16(0x1070) |= 0x200; // if (Config.SpuIrq) psxHu16(0x1070) |= 0x200;
psxHu16(0x1070) &= value; psxHu16(0x1070) &= value;
return; return;
case 0x1f801074: PSXHW_LOG("IMASK 16bit write %x\n", value);
case 0x1f801074:
PSXHW_LOG("IMASK 16bit write %x\n", value);
psxHu16(0x1074) = 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; return;
case 0x1f8010c4: case 0x1f8010c4:
PSXHW_LOG("DMA4 BCR_size 16bit write %lx\n", value); 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: case 0x1f8010c6:
PSXHW_LOG("DMA4 BCR_count 16bit write %lx\n", value); PSXHW_LOG("DMA4 BCR_count 16bit write %lx\n", value);
@ -868,6 +878,7 @@ void psxHwWrite32(u32 add, u32 value) {
psxHu32(add) = value; psxHu32(add) = value;
return; // Ram size return; // Ram size
//------------------------------------------------------------------
case 0x1f801070: case 0x1f801070:
PSXHW_LOG("IREG 32bit write %lx\n", value); PSXHW_LOG("IREG 32bit write %lx\n", value);
// if (Config.Sio) psxHu32(0x1070) |= 0x80; // if (Config.Sio) psxHu32(0x1070) |= 0x80;
@ -878,13 +889,16 @@ void psxHwWrite32(u32 add, u32 value) {
case 0x1f801074: case 0x1f801074:
PSXHW_LOG("IMASK 32bit write %lx\n", value); PSXHW_LOG("IMASK 32bit write %lx\n", value);
psxHu32(0x1074) = value; psxHu32(0x1074) = value;
iopTestIntc();
return; return;
case 0x1f801078: case 0x1f801078:
PSXHW_LOG("ICTRL 32bit write %lx\n", value); 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; return;
//------------------------------------------------------------------
//SSBus registers //SSBus registers
case 0x1f801000: case 0x1f801000:
psxHu32(0x1000) = value; psxHu32(0x1000) = value;
@ -958,6 +972,8 @@ void psxHwWrite32(u32 add, u32 value) {
psxHu32(0x1420) = value; psxHu32(0x1420) = value;
PSXHW_LOG("SSBUS <dev9_delay1> 32bit write %lx\n", value); PSXHW_LOG("SSBUS <dev9_delay1> 32bit write %lx\n", value);
return; return;
//------------------------------------------------------------------
case 0x1f801080: case 0x1f801080:
PSXHW_LOG("DMA0 MADR 32bit write %lx\n", value); PSXHW_LOG("DMA0 MADR 32bit write %lx\n", value);
HW_DMA0_MADR = value; return; // DMA0 madr HW_DMA0_MADR = value; return; // DMA0 madr
@ -970,6 +986,7 @@ void psxHwWrite32(u32 add, u32 value) {
// DmaExec(0); // DmaExec(0);
return; return;
//------------------------------------------------------------------
case 0x1f801090: case 0x1f801090:
PSXHW_LOG("DMA1 MADR 32bit write %lx\n", value); PSXHW_LOG("DMA1 MADR 32bit write %lx\n", value);
HW_DMA1_MADR = value; return; // DMA1 madr HW_DMA1_MADR = value; return; // DMA1 madr
@ -982,6 +999,7 @@ void psxHwWrite32(u32 add, u32 value) {
// DmaExec(1); // DmaExec(1);
return; return;
//------------------------------------------------------------------
case 0x1f8010a0: case 0x1f8010a0:
PSXHW_LOG("DMA2 MADR 32bit write %lx\n", value); PSXHW_LOG("DMA2 MADR 32bit write %lx\n", value);
HW_DMA2_MADR = value; return; // DMA2 madr HW_DMA2_MADR = value; return; // DMA2 madr
@ -994,6 +1012,7 @@ void psxHwWrite32(u32 add, u32 value) {
DmaExec(2); DmaExec(2);
return; return;
//------------------------------------------------------------------
case 0x1f8010b0: case 0x1f8010b0:
PSXHW_LOG("DMA3 MADR 32bit write %lx\n", value); PSXHW_LOG("DMA3 MADR 32bit write %lx\n", value);
HW_DMA3_MADR = value; return; // DMA3 madr HW_DMA3_MADR = value; return; // DMA3 madr
@ -1007,6 +1026,7 @@ void psxHwWrite32(u32 add, u32 value) {
return; return;
//------------------------------------------------------------------
case 0x1f8010c0: case 0x1f8010c0:
PSXHW_LOG("DMA4 MADR 32bit write %lx\n", value); PSXHW_LOG("DMA4 MADR 32bit write %lx\n", value);
SPU2WriteMemAddr(0,value); SPU2WriteMemAddr(0,value);
@ -1020,6 +1040,7 @@ void psxHwWrite32(u32 add, u32 value) {
DmaExec(4); DmaExec(4);
return; return;
//------------------------------------------------------------------
#if 0 #if 0
case 0x1f8010d0: break; //DMA5write_madr(); case 0x1f8010d0: break; //DMA5write_madr();
case 0x1f8010d4: break; //DMA5write_bcr(); case 0x1f8010d4: break; //DMA5write_bcr();
@ -1038,6 +1059,7 @@ void psxHwWrite32(u32 add, u32 value) {
DmaExec(6); DmaExec(6);
return; return;
//------------------------------------------------------------------
case 0x1f801500: case 0x1f801500:
PSXHW_LOG("DMA7 MADR 32bit write %lx\n", value); PSXHW_LOG("DMA7 MADR 32bit write %lx\n", value);
SPU2WriteMemAddr(1,value); SPU2WriteMemAddr(1,value);
@ -1051,6 +1073,7 @@ void psxHwWrite32(u32 add, u32 value) {
DmaExec2(7); DmaExec2(7);
return; return;
//------------------------------------------------------------------
case 0x1f801510: case 0x1f801510:
PSXHW_LOG("DMA8 MADR 32bit write %lx\n", value); PSXHW_LOG("DMA8 MADR 32bit write %lx\n", value);
HW_DMA8_MADR = value; return; // DMA8 madr HW_DMA8_MADR = value; return; // DMA8 madr
@ -1063,6 +1086,7 @@ void psxHwWrite32(u32 add, u32 value) {
DmaExec2(8); DmaExec2(8);
return; return;
//------------------------------------------------------------------
case 0x1f801520: case 0x1f801520:
PSXHW_LOG("DMA9 MADR 32bit write %lx\n", value); PSXHW_LOG("DMA9 MADR 32bit write %lx\n", value);
HW_DMA9_MADR = value; return; // DMA9 madr 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); PSXHW_LOG("DMA9 TADR 32bit write %lx\n", value);
HW_DMA9_TADR = value; return; // DMA9 tadr HW_DMA9_TADR = value; return; // DMA9 tadr
//------------------------------------------------------------------
case 0x1f801530: case 0x1f801530:
PSXHW_LOG("DMA10 MADR 32bit write %lx\n", value); PSXHW_LOG("DMA10 MADR 32bit write %lx\n", value);
HW_DMA10_MADR = value; return; // DMA10 madr HW_DMA10_MADR = value; return; // DMA10 madr
@ -1090,6 +1115,7 @@ void psxHwWrite32(u32 add, u32 value) {
DmaExec2(10); DmaExec2(10);
return; return;
//------------------------------------------------------------------
case 0x1f801540: case 0x1f801540:
PSXHW_LOG("DMA11 SIO2in MADR 32bit write %lx\n", value); PSXHW_LOG("DMA11 SIO2in MADR 32bit write %lx\n", value);
HW_DMA11_MADR = value; return; HW_DMA11_MADR = value; return;
@ -1103,6 +1129,7 @@ void psxHwWrite32(u32 add, u32 value) {
DmaExec2(11); DmaExec2(11);
return; return;
//------------------------------------------------------------------
case 0x1f801550: case 0x1f801550:
PSXHW_LOG("DMA12 SIO2out MADR 32bit write %lx\n", value); PSXHW_LOG("DMA12 SIO2out MADR 32bit write %lx\n", value);
HW_DMA12_MADR = value; return; HW_DMA12_MADR = value; return;
@ -1116,6 +1143,7 @@ void psxHwWrite32(u32 add, u32 value) {
DmaExec2(12); DmaExec2(12);
return; return;
//------------------------------------------------------------------
case 0x1f801570: case 0x1f801570:
psxHu32(0x1570) = value; psxHu32(0x1570) = value;
PSXHW_LOG("DMA PCR2 32bit write %lx\n", 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; u32 tmp = (~value) & HW_DMA_ICR;
HW_DMA_ICR = ((tmp ^ value) & 0xffffff) ^ tmp; HW_DMA_ICR = ((tmp ^ value) & 0xffffff) ^ tmp;
return;
} }
return;
case 0x1f801574: case 0x1f801574:
PSXHW_LOG("DMA ICR2 32bit write %lx\n", value); PSXHW_LOG("DMA ICR2 32bit write %lx\n", value);
{ {
u32 tmp = (~value) & HW_DMA_ICR2; u32 tmp = (~value) & HW_DMA_ICR2;
HW_DMA_ICR2 = ((tmp ^ value) & 0xffffff) ^ tmp; HW_DMA_ICR2 = ((tmp ^ value) & 0xffffff) ^ tmp;
return;
} }
return;
//------------------------------------------------------------------
/* case 0x1f801810: /* case 0x1f801810:
PSXHW_LOG("GPU DATA 32bit write %lx\n", value); PSXHW_LOG("GPU DATA 32bit write %lx\n", value);
GPU_writeData(value); return; GPU_writeData(value); return;
@ -1213,9 +1242,10 @@ void psxHwWrite32(u32 add, u32 value) {
PSXCNT_LOG("COUNTER 5 TARGET 32bit write %lx\n", value); PSXCNT_LOG("COUNTER 5 TARGET 32bit write %lx\n", value);
psxRcntWtarget32(5, value); return; psxRcntWtarget32(5, value); return;
//------------------------------------------------------------------
case 0x1f8014c0: case 0x1f8014c0:
PSXHW_LOG("RTC_HOLDMODE 32bit write %lx\n", value); 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; break;
case 0x1f801450: case 0x1f801450:
@ -1230,6 +1260,7 @@ void psxHwWrite32(u32 add, u32 value) {
psxHu32(0x1450) = /*(*/value/* & (~0x8)) | (psxHu32(0x1450) & 0x8)*/; psxHu32(0x1450) = /*(*/value/* & (~0x8)) | (psxHu32(0x1450) & 0x8)*/;
return; return;
//------------------------------------------------------------------
case 0x1F808200: case 0x1F808200:
case 0x1F808204: case 0x1F808204:
case 0x1F808208: case 0x1F808208:
@ -1279,6 +1310,7 @@ void psxHwWrite32(u32 add, u32 value) {
PSXHW_LOG("SIO2 write INTR <- %lx\n", value); PSXHW_LOG("SIO2 write INTR <- %lx\n", value);
sio2_setIntr(value); return; sio2_setIntr(value); return;
//------------------------------------------------------------------
default: default:
psxHu32(add) = value; psxHu32(add) = value;
PSXHW_LOG("*Unknown 32bit write at address %lx value %lx\n", 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 0x1f40200A: cdvdWrite0A(value); return;
case 0x1f40200F: cdvdWrite0F(value); return; case 0x1f40200F: cdvdWrite0F(value); return;
case 0x1f402014: cdvdWrite14(value); return; case 0x1f402014: cdvdWrite14(value); return;
case 0x1f402016: case 0x1f402016: cdvdWrite16(value); return;
cdvdWrite16(value);
//fixme - are these supposed to be here?
FreezeMMXRegs(0);
FreezeXMMRegs(0);
return;
case 0x1f402017: cdvdWrite17(value); return; case 0x1f402017: cdvdWrite17(value); return;
case 0x1f402018: cdvdWrite18(value); return; case 0x1f402018: cdvdWrite18(value); return;
case 0x1f40203A: cdvdWrite3A(value); return; case 0x1f40203A: cdvdWrite3A(value); return;
default: 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); //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; return;
} }
PSXHW_LOG("*Known 8bit write at address %lx value %x\n", add, value); 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))) { if (HW_DMA_ICR & (1 << (16 + n))) {
HW_DMA_ICR|= (1 << (24 + n)); HW_DMA_ICR|= (1 << (24 + n));
psxRegs.CP0.n.Cause |= 1 << (9 + 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)); HW_DMA_ICR2|= (1 << (24 + n));
psxRegs.CP0.n.Cause |= 1 << (16 + n); psxRegs.CP0.n.Cause |= 1 << (16 + n);
psxHu32(0x1070) |= 8; iopIntcIrq( 3 );
} }
} }

View File

@ -117,8 +117,7 @@ void sio2_setCtrl(u32 value){
if (sio2.ctrl & 1){ //recv packet if (sio2.ctrl & 1){ //recv packet
//handle data that had been sent //handle data that had been sent
//trigger interupt for SIO2 iopIntcIrq( 17 );
psxHu32(0x1070)|=0x20000;
//SBUS //SBUS
sio2.recvIndex=0; sio2.recvIndex=0;
sio2.ctrl &= ~1; sio2.ctrl &= ~1;

View File

@ -43,8 +43,9 @@ s32 psxCycleEE = -1;
// Used to signal to the EE when important actions that need IOP-attention have // 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 // happened (hsyncs, vsyncs, IOP exceptions, etc). IOP runs code whenever this
// is true, even if it's already running ahead a bit. // is true, even if it's already running ahead a bit.
int iopBranchAction = 0; bool iopBranchAction = false;
bool iopEventTestIsActive = false;
PCSX2_ALIGNED16(psxRegisters psxRegs); PCSX2_ALIGNED16(psxRegisters psxRegs);
@ -245,25 +246,38 @@ void psxBranchTest()
if( psxTestCycle( psxNextsCounter, psxNextCounter ) ) if( psxTestCycle( psxNextsCounter, psxNextCounter ) )
{ {
psxRcntUpdate(); psxRcntUpdate();
iopBranchAction = 1; iopBranchAction = true;
} }
// start the next branch at the next counter event by default // start the next branch at the next counter event by default
// the interrupt code below will assign nearer branches if needed. // the interrupt code below will assign nearer branches if needed.
g_psxNextBranchCycle = psxNextsCounter+psxNextCounter; g_psxNextBranchCycle = psxNextsCounter+psxNextCounter;
if (psxRegs.interrupt) _psxTestInterrupts(); if (psxRegs.interrupt)
{
if (psxHu32(0x1078)) { iopEventTestIsActive = true;
if(psxHu32(0x1070) & psxHu32(0x1074)){ _psxTestInterrupts();
if ((psxRegs.CP0.n.Status & 0xFE01) >= 0x401) iopEventTestIsActive = false;
{
// PSXCPU_LOG("Interrupt: %x %x\n", HWMu32(0x1070), HWMu32(0x1074));
psxException(0, 0);
iopBranchAction = 1;
}
}
} }
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() { void psxExecuteBios() {

View File

@ -214,6 +214,7 @@ void psxExecuteBios();
extern s32 psxNextCounter; extern s32 psxNextCounter;
extern u32 psxNextsCounter; extern u32 psxNextsCounter;
extern int iopBranchAction; extern bool iopBranchAction;
extern bool iopEventTestIsActive;
#endif /* __R3000A_H__ */ #endif /* __R3000A_H__ */

View File

@ -45,6 +45,8 @@ u32 bExecBIOS = 0; // set if the BIOS has already been executed
static bool cpuIsInitialized = false; static bool cpuIsInitialized = false;
static uint eeWaitCycles = 1024; static uint eeWaitCycles = 1024;
bool eeEventTestIsActive = false;
#ifdef _DEBUG #ifdef _DEBUG
extern u32 s_vucount; extern u32 s_vucount;
#endif #endif
@ -208,7 +210,7 @@ void cpuException(u32 code, u32 bd) {
} }
} else { } else {
offset = 0x180; //Overrride the cause 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) { if (cpuRegs.CP0.n.Status.b.BEV == 0) {
cpuRegs.pc = 0x80000000 + offset; cpuRegs.pc = 0x80000000 + offset;
@ -216,7 +218,7 @@ void cpuException(u32 code, u32 bd) {
cpuRegs.pc = 0xBFC00200 + offset; cpuRegs.pc = 0xBFC00200 + offset;
} }
} else { //Error Level 2 } 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 if((code & 0x38000) <= 0x8000 ) { //Reset / NMI
cpuRegs.pc = 0xBFC00000; cpuRegs.pc = 0xBFC00000;
Console::Notice("Reset request"); Console::Notice("Reset request");
@ -430,10 +432,6 @@ static __forceinline void _cpuTestInterrupts()
TESTINT(10, vifMFIFOInterrupt); TESTINT(10, vifMFIFOInterrupt);
TESTINT(11, gifMFIFOInterrupt); TESTINT(11, gifMFIFOInterrupt);
} }
if ((cpuRegs.CP0.n.Status.val & 0x10007) != 0x10001) return;
TESTINT(30, intcInterrupt);
TESTINT(31, dmacInterrupt);
} }
u32 s_iLastCOP0Cycle = 0; u32 s_iLastCOP0Cycle = 0;
@ -450,8 +448,9 @@ static __forceinline void _cpuTestTIMR()
// the Count or Compare registers are modified. // the Count or Compare registers are modified.
if ( (cpuRegs.CP0.n.Status.val & 0x8000) && if ( (cpuRegs.CP0.n.Status.val & 0x8000) &&
cpuRegs.CP0.n.Count >= cpuRegs.CP0.n.Compare && cpuRegs.CP0.n.Count < cpuRegs.CP0.n.Compare+1000 ) { 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); {
Console::Status("timr intr: %x, %x", cpuRegs.CP0.n.Count, cpuRegs.CP0.n.Compare);
cpuException(0x808000, cpuRegs.branch); 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 // if cpuRegs.cycle is greater than this cycle, should check cpuBranchTest for updates
u32 g_nextBranchCycle = 0; u32 g_nextBranchCycle = 0;
@ -485,6 +479,7 @@ u32 g_nextBranchCycle = 0;
// and the recompiler. (moved here to help alleviate redundant code) // and the recompiler. (moved here to help alleviate redundant code)
static __forceinline void _cpuBranchTest_Shared() static __forceinline void _cpuBranchTest_Shared()
{ {
eeEventTestIsActive = true;
g_nextBranchCycle = cpuRegs.cycle + eeWaitCycles; g_nextBranchCycle = cpuRegs.cycle + eeWaitCycles;
EEsCycle += cpuRegs.cycle - EEoCycle; EEsCycle += cpuRegs.cycle - EEoCycle;
@ -504,10 +499,6 @@ static __forceinline void _cpuBranchTest_Shared()
_cpuTestTIMR(); _cpuTestTIMR();
//#ifdef CPU_LOG
// cpuTestMissingHwInts();
//#endif
// ---- Interrupts ------------- // ---- Interrupts -------------
if( cpuRegs.interrupt ) if( cpuRegs.interrupt )
@ -537,41 +528,6 @@ static __forceinline void _cpuBranchTest_Shared()
psxCpu->ExecuteBlock(); 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 ------------- // ---- VU0 -------------
if (VU0.VI[REG_VPU_STAT].UL & 0x1) 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 // one shot always. That is, when a program is executed the VU1 doesn't even
// bother to return until the program is completely finished. // 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 #ifdef PCSX2_DEVBUILD
assert( !g_globalXMMSaved && !g_globalMMXSaved); assert( !g_globalXMMSaved && !g_globalMMXSaved);
#endif #endif
@ -616,28 +622,37 @@ __forceinline void CPU_INT( u32 n, s32 ecycle)
cpuSetNextBranchDelta( cpuRegs.eCycle[n] ); 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( (cpuRegs.CP0.n.Status.val & 0x10407) != 0x10401 ) return;
if( (psHu32(INTC_STAT) & psHu32(INTC_MASK)) == 0 ) 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 cpuRegs.interrupt|= 1 << 30;
// "late" already, so firing them immediately instead of after the next branch cpuRegs.sCycle[30] = cpuRegs.cycle;
// (in which case they'll be really late) would be a lot better in theory. cpuRegs.eCycle[30] = 0;
// However, setting this to zero for everything breaks games, so if it's done
// it needs to be done for counters only.
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() { __forceinline void cpuTestDMACInts() {
if ((cpuRegs.CP0.n.Status.val & 0x10807) != 0x10801) return;
if ( cpuRegs.interrupt & (1 << 31) ) return; if ( cpuRegs.interrupt & (1 << 31) ) return;
if ((cpuRegs.CP0.n.Status.val & 0x10807) != 0x10801) return;
if ( ( (psHu16(0xe012) & psHu16(0xe010)) == 0) && if ( ( (psHu16(0xe012) & psHu16(0xe010)) == 0) &&
( (psHu16(0xe010) & 0x8000) == 0) ) return; ( (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() { __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; g_EEFreezeRegs = true;
} }

View File

@ -127,6 +127,7 @@ struct cpuRegisters {
extern s32 EEsCycle; extern s32 EEsCycle;
extern u32 EEoCycle; extern u32 EEoCycle;
extern bool eeEventTestIsActive;
extern PCSX2_ALIGNED16_DECL(cpuRegisters cpuRegs); extern PCSX2_ALIGNED16_DECL(cpuRegisters cpuRegs);
// used for optimization // used for optimization

View File

@ -128,7 +128,7 @@ void _SPR0interleave() {
CPU_INT(8, cycles); CPU_INT(8, cycles);
} }
void _dmaSPR0() { static __forceinline void _dmaSPR0() {
if ((psHu32(DMAC_CTRL) & 0x30) == 0x20) { // STS == fromSPR if ((psHu32(DMAC_CTRL) & 0x30) == 0x20) { // STS == fromSPR

View File

@ -517,10 +517,6 @@ void SIO_FORCEINLINE sioInterrupt() {
void SaveState::sioFreeze() { void SaveState::sioFreeze() {
// eh, not supported anymore.. :)
//if( Mode == 0 && dwCurSaveStateVer == 0x7a30000e )
// savesize -= 4;
if( IsLoading() ) if( IsLoading() )
sio.count = 0; sio.count = 0;
Freeze( sio ); Freeze( sio );

View File

@ -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) // 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 ) if( bit != 32 )
{ {
@ -518,23 +519,23 @@ static __forceinline void ConstWrite_ExecTimer( uptr func, u8 index, u8 bit, int
} }
#define CONSTWRITE_TIMERS(bit) \ #define CONSTWRITE_TIMERS(bit) \
case 0x10000000: ConstWrite_ExecTimer((uptr)&rcntWcount, 0, bit, mmreg); break; \ case 0x10000000: ConstWrite_ExecTimer<bit>((uptr)&rcntWcount, 0, mmreg); break; \
case 0x10000010: ConstWrite_ExecTimer((uptr)&rcntWmode, 0, bit, mmreg); break; \ case 0x10000010: ConstWrite_ExecTimer<bit>((uptr)&rcntWmode, 0, mmreg); break; \
case 0x10000020: ConstWrite_ExecTimer((uptr)&rcntWtarget, 0, bit, mmreg); break; \ case 0x10000020: ConstWrite_ExecTimer<bit>((uptr)&rcntWtarget, 0, mmreg); break; \
case 0x10000030: ConstWrite_ExecTimer((uptr)&rcntWhold, 0, bit, mmreg); break; \ case 0x10000030: ConstWrite_ExecTimer<bit>((uptr)&rcntWhold, 0, mmreg); break; \
\ \
case 0x10000800: ConstWrite_ExecTimer((uptr)&rcntWcount, 1, bit, mmreg); break; \ case 0x10000800: ConstWrite_ExecTimer<bit>((uptr)&rcntWcount, 1, mmreg); break; \
case 0x10000810: ConstWrite_ExecTimer((uptr)&rcntWmode, 1, bit, mmreg); break; \ case 0x10000810: ConstWrite_ExecTimer<bit>((uptr)&rcntWmode, 1, mmreg); break; \
case 0x10000820: ConstWrite_ExecTimer((uptr)&rcntWtarget, 1, bit, mmreg); break; \ case 0x10000820: ConstWrite_ExecTimer<bit>((uptr)&rcntWtarget, 1, mmreg); break; \
case 0x10000830: ConstWrite_ExecTimer((uptr)&rcntWhold, 1, bit, mmreg); break; \ case 0x10000830: ConstWrite_ExecTimer<bit>((uptr)&rcntWhold, 1, mmreg); break; \
\ \
case 0x10001000: ConstWrite_ExecTimer((uptr)&rcntWcount, 2, bit, mmreg); break; \ case 0x10001000: ConstWrite_ExecTimer<bit>((uptr)&rcntWcount, 2, mmreg); break; \
case 0x10001010: ConstWrite_ExecTimer((uptr)&rcntWmode, 2, bit, mmreg); break; \ case 0x10001010: ConstWrite_ExecTimer<bit>((uptr)&rcntWmode, 2, mmreg); break; \
case 0x10001020: ConstWrite_ExecTimer((uptr)&rcntWtarget, 2, bit, mmreg); break; \ case 0x10001020: ConstWrite_ExecTimer<bit>((uptr)&rcntWtarget, 2, mmreg); break; \
\ \
case 0x10001800: ConstWrite_ExecTimer((uptr)&rcntWcount, 3, bit, mmreg); break; \ case 0x10001800: ConstWrite_ExecTimer<bit>((uptr)&rcntWcount, 3, mmreg); break; \
case 0x10001810: ConstWrite_ExecTimer((uptr)&rcntWmode, 3, bit, mmreg); break; \ case 0x10001810: ConstWrite_ExecTimer<bit>((uptr)&rcntWmode, 3, mmreg); break; \
case 0x10001820: ConstWrite_ExecTimer((uptr)&rcntWtarget, 3, bit, mmreg); break; \ case 0x10001820: ConstWrite_ExecTimer<bit>((uptr)&rcntWtarget, 3, mmreg); break; \
void hwConstWrite8(u32 mem, int mmreg) void hwConstWrite8(u32 mem, int mmreg)
{ {
@ -971,11 +972,10 @@ void hwConstWrite32(u32 mem, int mmreg)
_eeMoveMMREGtoR(EAX, mmreg); _eeMoveMMREGtoR(EAX, mmreg);
iFlushCall(0); iFlushCall(0);
MOV32RtoR(ECX, EAX); MOV32RtoR(ECX, EAX);
NOT32R(ECX);
AND16RtoM((uptr)&PS2MEM_HW[0xe010], ECX);
SHR32ItoR(EAX, 16); SHR32ItoR(EAX, 16);
NOT32R(ECX);
XOR16RtoM((uptr)&PS2MEM_HW[0xe012], EAX); XOR16RtoM((uptr)&PS2MEM_HW[0xe012], EAX);
AND16RtoM((uptr)&PS2MEM_HW[0xe010], ECX);
CALLFunc((uptr)cpuTestDMACInts); CALLFunc((uptr)cpuTestDMACInts);
break; break;
@ -1164,11 +1164,11 @@ void hwConstWrite64(u32 mem, int mmreg)
iFlushCall(0); iFlushCall(0);
MOV32RtoR(ECX, EAX); MOV32RtoR(ECX, EAX);
SHR32ItoR(EAX, 16);
NOT32R(ECX); NOT32R(ECX);
XOR16RtoM((uptr)&PS2MEM_HW[0xe012], EAX);
AND16RtoM((uptr)&PS2MEM_HW[0xe010], ECX); AND16RtoM((uptr)&PS2MEM_HW[0xe010], ECX);
SHR32ItoR(EAX, 16);
XOR16RtoM((uptr)&PS2MEM_HW[0xe012], EAX);
CALLFunc((uptr)cpuTestDMACInts); CALLFunc((uptr)cpuTestDMACInts);
break; break;

View File

@ -610,8 +610,21 @@ void psxHwConstWrite16(u32 add, int mmreg) {
_eeWriteConstMem16((uptr)&sio.BaudReg, mmreg); _eeWriteConstMem16((uptr)&sio.BaudReg, mmreg);
return; return;
case 0x1f801070: case 0x1f801070:
_eeWriteConstMem16OP((uptr)&psxH[(add) & 0xffff], mmreg, 0); _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; return;
// counters[0] // counters[0]
@ -807,7 +820,20 @@ void psxHwConstWrite32(u32 add, int mmreg)
return; return;
case 0x1f801070: 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; return;
// case 0x1f801088: // case 0x1f801088:
@ -1123,7 +1149,7 @@ int psxHw4ConstRead8(u32 x86reg, u32 add, u32 sign) {
case 0x1f402039: CONSTREAD8_CALL((uptr)cdvdRead39); return 1; case 0x1f402039: CONSTREAD8_CALL((uptr)cdvdRead39); return 1;
case 0x1f40203A: CONSTREAD8_CALL((uptr)cdvdRead3A); return 1; case 0x1f40203A: CONSTREAD8_CALL((uptr)cdvdRead3A); return 1;
default: default:
SysPrintf("*Unknown 8bit read at address %lx\n", add); Console::Notice("*Unknown 8bit read at address %lx\n", add);
XOR32RtoR(x86reg, x86reg); XOR32RtoR(x86reg, x86reg);
return 0; return 0;
} }
@ -1147,7 +1173,7 @@ void psxHw4ConstWrite8(u32 add, int mmreg) {
case 0x1f402018: CONSTWRITE_CALL(cdvdWrite18); return; case 0x1f402018: CONSTWRITE_CALL(cdvdWrite18); return;
case 0x1f40203A: CONSTWRITE_CALL(cdvdWrite3A); return; case 0x1f40203A: CONSTWRITE_CALL(cdvdWrite3A); return;
default: default:
SysPrintf("*Unknown 8bit write at address %lx\n", add); Console::Notice("*Unknown 8bit write at address %lx\n", add);
return; return;
} }
} }

View File

@ -1761,6 +1761,11 @@ void rpsxRFE()
SHR32ItoR(ECX, 2); SHR32ItoR(ECX, 2);
OR32RtoR (EAX, ECX); OR32RtoR (EAX, ECX);
MOV32RtoM((uptr)&psxRegs.CP0.n.Status, EAX); 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 // R3000A tables