mirror of https://github.com/PCSX2/pcsx2.git
*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:
parent
bbfb6ac41a
commit
4524fd919e
|
@ -206,7 +206,7 @@ static void CDVD_INT(int eCycle)
|
|||
static void cdvdSetIrq( uint id = (1<<Irq_CommandComplete) )
|
||||
{
|
||||
cdvd.PwOff |= id;
|
||||
psxHu32(0x1070)|= 0x4;
|
||||
iopIntcIrq( 2 );
|
||||
hwIntcIrq(INTC_SBUS);
|
||||
psxSetNextBranchDelta( 20 );
|
||||
}
|
||||
|
|
|
@ -489,7 +489,8 @@ void cdrInterrupt() {
|
|||
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);
|
||||
}
|
||||
|
@ -554,7 +555,7 @@ void cdrReadInterrupt() {
|
|||
CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime);
|
||||
}
|
||||
|
||||
psxHu32(0x1070)|=0x4;
|
||||
psxHu32(0x1070)|= 0x4;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -827,7 +828,8 @@ void cdrWrite1(u8 rt) {
|
|||
CDR_LOG("Unknown Cmd: %x\n", cdr.Cmd);
|
||||
return;
|
||||
}
|
||||
if (cdr.Stat != NoIntr) psxHu32(0x1070)|=0x4;
|
||||
if (cdr.Stat != NoIntr)
|
||||
iopIntcIrq( 2 );
|
||||
}
|
||||
|
||||
u8 cdrRead2(void) {
|
||||
|
|
|
@ -391,24 +391,38 @@ static __forceinline void frameLimit()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static __forceinline void VSyncStart(u32 sCycle) // VSync Start
|
||||
static __forceinline void VSyncStart(u32 sCycle)
|
||||
{
|
||||
vSyncDebugStuff(); // EE Profiling and Debug code
|
||||
if ((CSRw & 0x8)) GSCSRr|= 0x8;
|
||||
if (!(GSIMR&0x800)) gsIrq(); //GS Irq
|
||||
|
||||
hwIntcIrq(2); // HW Irq
|
||||
psxVBlankStart(); // psxCounters vBlank Start
|
||||
// HACK : For some inexplicable reason, having the IntcIrq(2) handled during the
|
||||
// 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 (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++;
|
||||
|
||||
// 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 )
|
||||
{
|
||||
gsPostVsyncEnd( false );
|
||||
|
|
75
pcsx2/Hw.cpp
75
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<<i;
|
||||
}
|
||||
}
|
||||
if ((cpuRegs.CP0.n.Status.val & 0x10807) == 0x10801)
|
||||
cpuTestDMACInts();
|
||||
cpuTestDMACInts();
|
||||
break;
|
||||
|
||||
case 0x1000f590: // DMAC_ENABLEW
|
||||
|
@ -1084,17 +1073,17 @@ void hwWrite64(u32 mem, u64 value) {
|
|||
|
||||
case 0x1000f000: // INTC_STAT
|
||||
HW_LOG("INTC_STAT Write 64bit %x\n", value);
|
||||
psHu32(0xf000)&=~value;
|
||||
psHu32(INTC_STAT)&=~value;
|
||||
cpuTestINTCInts();
|
||||
break;
|
||||
|
||||
case 0x1000f010: // INTC_MASK
|
||||
HW_LOG("INTC_MASK Write 32bit %x\n", value);
|
||||
for (i=0; i<16; i++) { // reverse on 1
|
||||
int s = (1<<i);
|
||||
const int s = (1<<i);
|
||||
if (value & s) {
|
||||
if (psHu32(0xf010) & (1<<i)) psHu32(0xf010)&= ~(1<<i);
|
||||
else psHu32(0xf010)|= 1<<i;
|
||||
if (psHu32(INTC_MASK) & s) psHu32(INTC_MASK)&= ~s;
|
||||
else psHu32(INTC_MASK)|= s;
|
||||
}
|
||||
}
|
||||
cpuTestINTCInts();
|
||||
|
@ -1104,12 +1093,11 @@ void hwWrite64(u32 mem, u64 value) {
|
|||
case 0x1000f410:
|
||||
case 0x1000f430:
|
||||
break;
|
||||
|
||||
default:
|
||||
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);
|
||||
#endif
|
||||
|
||||
HW_LOG("Unknown Hardware write 64 at %x with value %x (status=%x)\n",mem,value, cpuRegs.CP0.n.Status.val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1134,9 +1122,7 @@ void hwWrite128(u32 mem, const u64 *value) {
|
|||
psHu64(mem ) = value[0];
|
||||
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);
|
||||
#endif
|
||||
HW_LOG("Unknown Hardware write 128 at %x with value %x_%x (status=%x)\n", mem, value[1], value[0], cpuRegs.CP0.n.Status.val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1146,7 +1132,7 @@ __forceinline void intcInterrupt() {
|
|||
if ((cpuRegs.CP0.n.Status.val & 0x400) != 0x400) return;
|
||||
|
||||
if ((psHu32(INTC_STAT)) == 0) {
|
||||
SysPrintf("*PCSX2*: intcInterrupt already cleared\n");
|
||||
DevCon::Notice("*PCSX2*: intcInterrupt already cleared");
|
||||
return;
|
||||
}
|
||||
if ((psHu32(INTC_STAT) & psHu32(INTC_MASK)) == 0) return;
|
||||
|
@ -1160,24 +1146,13 @@ __forceinline void intcInterrupt() {
|
|||
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()
|
||||
{
|
||||
cpuRegs.interrupt &= ~(1 << 31);
|
||||
if ((cpuRegs.CP0.n.Status.val & 0x10807) != 0x10801) return;
|
||||
|
||||
if ((psHu16(0xe012) & psHu16(0xe010) ||
|
||||
psHu16(0xe010) & 0x8000) == 0) return;
|
||||
if( ((psHu16(0xe012) & psHu16(0xe010)) == 0 ) &&
|
||||
( psHu16(0xe010) & 0x8000) == 0 ) return;
|
||||
|
||||
if((psHu32(DMAC_CTRL) & 0x1) == 0) return;
|
||||
|
||||
|
@ -1188,10 +1163,8 @@ __forceinline void dmacInterrupt()
|
|||
}
|
||||
|
||||
void hwIntcIrq(int n) {
|
||||
//if( psHu32(INTC_MASK) & (1<<n) ) {
|
||||
psHu32(INTC_STAT)|= 1<<n;
|
||||
cpuTestINTCInts();
|
||||
//}
|
||||
psHu32(INTC_STAT)|= 1<<n;
|
||||
cpuTestINTCInts();
|
||||
}
|
||||
|
||||
void hwDmacIrq(int n) {
|
||||
|
|
|
@ -722,21 +722,23 @@ void _eeWriteConstMem16(u32 mem, int mmreg)
|
|||
else MOV16RtoM(mem, mmreg);
|
||||
}
|
||||
|
||||
// op - 0 for AND, 1 for OR
|
||||
void _eeWriteConstMem16OP(u32 mem, int mmreg, int op)
|
||||
{
|
||||
assert( !IS_XMMREG(mmreg) && !IS_MMXREG(mmreg) );
|
||||
switch(op) {
|
||||
case 0: // and
|
||||
case 0: // AND operation
|
||||
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 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));
|
||||
|
||||
|
|
|
@ -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 <math.h>
|
||||
|
|
160
pcsx2/PsxDma.cpp
160
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<<irqType;
|
||||
iopTestIntc();
|
||||
}
|
||||
|
|
|
@ -37,6 +37,10 @@ void usbIrq(int cycles);
|
|||
void fwIrq();
|
||||
void spu2Irq();
|
||||
|
||||
extern void iopIntcIrq( uint irqType );
|
||||
extern void iopTestIntc();
|
||||
|
||||
|
||||
extern DEV9handler dev9Handler;
|
||||
extern USBhandler usbHandler;
|
||||
|
||||
|
|
|
@ -704,9 +704,9 @@ void psxHwWrite16(u32 add, u16 value) {
|
|||
if (add >= 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 <dev9_delay1> 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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -214,6 +214,7 @@ void psxExecuteBios();
|
|||
|
||||
extern s32 psxNextCounter;
|
||||
extern u32 psxNextsCounter;
|
||||
extern int iopBranchAction;
|
||||
extern bool iopBranchAction;
|
||||
extern bool iopEventTestIsActive;
|
||||
|
||||
#endif /* __R3000A_H__ */
|
||||
|
|
145
pcsx2/R5900.cpp
145
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;
|
||||
}
|
||||
|
|
|
@ -127,6 +127,7 @@ struct cpuRegisters {
|
|||
|
||||
extern s32 EEsCycle;
|
||||
extern u32 EEoCycle;
|
||||
extern bool eeEventTestIsActive;
|
||||
extern PCSX2_ALIGNED16_DECL(cpuRegisters cpuRegs);
|
||||
|
||||
// used for optimization
|
||||
|
|
|
@ -128,7 +128,7 @@ void _SPR0interleave() {
|
|||
CPU_INT(8, cycles);
|
||||
}
|
||||
|
||||
void _dmaSPR0() {
|
||||
static __forceinline void _dmaSPR0() {
|
||||
|
||||
|
||||
if ((psHu32(DMAC_CTRL) & 0x30) == 0x20) { // STS == fromSPR
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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<bit>((uptr)&rcntWcount, 0, mmreg); break; \
|
||||
case 0x10000010: ConstWrite_ExecTimer<bit>((uptr)&rcntWmode, 0, mmreg); break; \
|
||||
case 0x10000020: ConstWrite_ExecTimer<bit>((uptr)&rcntWtarget, 0, mmreg); break; \
|
||||
case 0x10000030: ConstWrite_ExecTimer<bit>((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<bit>((uptr)&rcntWcount, 1, mmreg); break; \
|
||||
case 0x10000810: ConstWrite_ExecTimer<bit>((uptr)&rcntWmode, 1, mmreg); break; \
|
||||
case 0x10000820: ConstWrite_ExecTimer<bit>((uptr)&rcntWtarget, 1, mmreg); break; \
|
||||
case 0x10000830: ConstWrite_ExecTimer<bit>((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<bit>((uptr)&rcntWcount, 2, mmreg); break; \
|
||||
case 0x10001010: ConstWrite_ExecTimer<bit>((uptr)&rcntWmode, 2, mmreg); break; \
|
||||
case 0x10001020: ConstWrite_ExecTimer<bit>((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<bit>((uptr)&rcntWcount, 3, mmreg); break; \
|
||||
case 0x10001810: ConstWrite_ExecTimer<bit>((uptr)&rcntWmode, 3, mmreg); break; \
|
||||
case 0x10001820: ConstWrite_ExecTimer<bit>((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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue