*Experimental* Made new IopHwRead and IopHwWrite from scratch, in pre-preparation for a new lookup-based IOP memory manager. Could be some lingering bugs or typos. :/

Win32/vcproj: Re-structured the folder layout of the project.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1116 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2009-05-02 10:48:41 +00:00
parent b560f325ae
commit 56545f0b7d
11 changed files with 2808 additions and 1527 deletions

View File

@ -1,40 +0,0 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __EEREGS_H__
#define __EEREGS_H__
#define at cpuRegs.GPR.n.at
#define k0 cpuRegs.GPR.n.k0
#define k1 cpuRegs.GPR.n.k1
#define v0 cpuRegs.GPR.n.v0
#define v1 cpuRegs.GPR.n.v1
#define a0 cpuRegs.GPR.n.a0
#define a1 cpuRegs.GPR.n.a1
#define a2 cpuRegs.GPR.n.a2
#define a3 cpuRegs.GPR.n.a3
#define t0 cpuRegs.GPR.n.t0
#define s0 cpuRegs.GPR.n.s0
#define gp cpuRegs.GPR.n.gp
#define fp cpuRegs.GPR.n.s8
#define sp cpuRegs.GPR.n.sp
#define ra cpuRegs.GPR.n.ra
#define pc0 cpuRegs.pc
#endif /* __EEREGS_H__ */

View File

@ -479,7 +479,9 @@ void psxRcntUpdate()
for (i=0; i<6; i++) _rcntSet( i ); for (i=0; i<6; i++) _rcntSet( i );
} }
void psxRcntWcount16(int index, u32 value) //////////////////////////////////////////////////////////////////////////////////////////
//
void psxRcntWcount16(int index, u16 value)
{ {
u32 change; u32 change;
@ -500,6 +502,8 @@ void psxRcntWcount16(int index, u32 value)
_rcntSet( index ); _rcntSet( index );
} }
//////////////////////////////////////////////////////////////////////////////////////////
//
void psxRcntWcount32(int index, u32 value) void psxRcntWcount32(int index, u32 value)
{ {
u32 change; u32 change;
@ -521,159 +525,119 @@ void psxRcntWcount32(int index, u32 value)
_rcntSet( index ); _rcntSet( index );
} }
void psxRcnt0Wmode(u32 value) //////////////////////////////////////////////////////////////////////////////////////////
//
__forceinline void psxRcntWmode16( int index, u32 value )
{ {
PSXCNT_LOG("IOP Counter[0] writeMode = %lx", value); PSXCNT_LOG( "IOP Counter[%d] writeMode = 0x%04X", index, value );
psxCounters[0].mode = value; jASSUME( index >= 0 && index < 3 );
psxCounters[0].mode|= 0x0400; psxCounter& counter = psxCounters[index];
psxCounters[0].rate = 1;
if(value & IOPCNT_ALT_SOURCE) counter.mode = value;
psxCounters[0].rate = PSXPIXEL; counter.mode |= 0x0400;
if(psxCounters[0].mode & IOPCNT_ENABLE_GATE) if( index == 2 )
{ {
// gated counters are added up as per the h/vblank timers. switch(value & 0x200)
PSXCNT_LOG("IOP Counter[0] Gate Check set, value = %x", value); {
psxhblankgate |= 1;
}
else psxhblankgate &= ~1;
psxCounters[0].count = 0;
psxCounters[0].sCycleT = psxRegs.cycle;
psxCounters[0].target &= 0xffff;
_rcntSet( 0 );
}
void psxRcnt1Wmode(u32 value)
{
PSXCNT_LOG("IOP Counter[0] writeMode = %lx", value);
psxCounters[1].mode = value;
psxCounters[1].mode|= 0x0400;
psxCounters[1].rate = 1;
if(value & IOPCNT_ALT_SOURCE)
psxCounters[1].rate = PSXHBLANK;
if(psxCounters[1].mode & IOPCNT_ENABLE_GATE)
{
PSXCNT_LOG("IOP Counter[1] Gate Check set, value = %x", value);
psxvblankgate |= 1<<1;
}
else psxvblankgate &= ~(1<<1);
psxCounters[1].count = 0;
psxCounters[1].sCycleT = psxRegs.cycle;
psxCounters[1].target &= 0xffff;
_rcntSet( 1 );
}
void psxRcnt2Wmode(u32 value)
{
PSXCNT_LOG("IOP Counter[0] writeMode = %lx", value);
psxCounters[2].mode = value;
psxCounters[2].mode|= 0x0400;
switch(value & 0x200)
{
case 0x200: psxCounters[2].rate = 8; break;
case 0x000: psxCounters[2].rate = 1; break; case 0x000: psxCounters[2].rate = 1; break;
case 0x200: psxCounters[2].rate = 8; break;
jNO_DEFAULT;
}
if((counter.mode & 0x7) == 0x7 || (counter.mode & 0x7) == 0x1)
{
counter.mode |= IOPCNT_STOPPED;
}
}
else
{
// Counters 0 and 1 can select PIXEL or HSYNC as an alternate source:
counter.rate = 1;
if(value & IOPCNT_ALT_SOURCE)
counter.rate = (index==0) ? PSXPIXEL : PSXHBLANK;
if(counter.mode & IOPCNT_ENABLE_GATE)
{
// gated counters are added up as per the h/vblank timers.
// (the PIXEL alt source becomes a vsync gate)
PSXCNT_LOG( "IOP Counter[%d] Gate Check set, value = 0x%04X", index, value );
if( index == 0 )
psxhblankgate |= 1; // fixme: these gate flags should be one var >_<
else
psxvblankgate |= 1<<1;
}
else
{
if( index == 0 )
psxhblankgate &= ~1;
else
psxvblankgate &= ~(1<<1);
}
} }
if((psxCounters[2].mode & 0x7) == 0x7 || (psxCounters[2].mode & 0x7) == 0x1) counter.count = 0;
{ counter.sCycleT = psxRegs.cycle;
//Console::WriteLn("Gate set on IOP C2, disabling"); counter.target &= 0xffff;
psxCounters[2].mode |= IOPCNT_STOPPED;
} _rcntSet( index );
psxCounters[2].count = 0;
psxCounters[2].sCycleT = psxRegs.cycle;
psxCounters[2].target &= 0xffff;
_rcntSet( 2 );
} }
void psxRcnt3Wmode(u32 value) //////////////////////////////////////////////////////////////////////////////////////////
//
__forceinline void psxRcntWmode32( int index, u32 value )
{ {
PSXCNT_LOG("IOP Counter[3] writeMode = %lx", value); PSXCNT_LOG( "IOP Counter[%d] writeMode = 0x%04x", index, value );
psxCounters[3].mode = value; jASSUME( index >= 3 && index < 6 );
psxCounters[3].rate = 1; psxCounter& counter = psxCounters[index];
psxCounters[3].mode|= 0x0400;
if(value & IOPCNT_ALT_SOURCE) counter.mode = value;
psxCounters[3].rate = PSXHBLANK; counter.mode |= 0x0400;
if(psxCounters[3].mode & IOPCNT_ENABLE_GATE) if( index == 3 )
{ {
PSXCNT_LOG("IOP Counter[3] Gate Check set, value = %x", value); // Counter 3 has the HBlank as an alternate source.
psxvblankgate |= 1<<3; counter.rate = 1;
} if(value & IOPCNT_ALT_SOURCE)
else psxvblankgate &= ~(1<<3); counter.rate = PSXHBLANK;
psxCounters[3].count = 0; if(counter.mode & IOPCNT_ENABLE_GATE)
psxCounters[3].sCycleT = psxRegs.cycle; {
psxCounters[3].target &= 0xffffffff; PSXCNT_LOG("IOP Counter[3] Gate Check set, value = %x", value);
_rcntSet( 3 ); psxvblankgate |= 1<<3;
} }
else psxvblankgate &= ~(1<<3);
void psxRcnt4Wmode(u32 value) }
{ else
PSXCNT_LOG("IOP Counter[4] writeMode = %lx", value); {
switch(value & 0x6000)
psxCounters[4].mode = value; {
psxCounters[4].mode|= 0x0400; case 0x0000: counter.rate = 1; break;
case 0x2000: counter.rate = 8; break;
switch(value & 0x6000) case 0x4000: counter.rate = 16; break;
{ case 0x6000: counter.rate = 256; break;
case 0x0000: psxCounters[4].rate = 1; break; }
case 0x2000: psxCounters[4].rate = 8; break;
case 0x4000: psxCounters[4].rate = 16; break; // Need to set a rate and target
case 0x6000: psxCounters[4].rate = 256; break; if((counter.mode & 0x7) == 0x7 || (counter.mode & 0x7) == 0x1)
} {
// Need to set a rate and target Console::WriteLn( "Gate set on IOP Counter %d, disabling", params index );
if((psxCounters[4].mode & 0x7) == 0x7 || (psxCounters[4].mode & 0x7) == 0x1) counter.mode |= IOPCNT_STOPPED;
{ }
Console::WriteLn("Gate set on IOP C4, disabling"); }
psxCounters[4].mode |= IOPCNT_STOPPED;
} counter.count = 0;
counter.sCycleT = psxRegs.cycle;
psxCounters[4].count = 0; counter.target &= 0xffffffff;
psxCounters[4].sCycleT = psxRegs.cycle; _rcntSet( index );
psxCounters[4].target &= 0xffffffff;
_rcntSet( 4 );
}
void psxRcnt5Wmode(u32 value)
{
PSXCNT_LOG("IOP Counter[5] writeMode = %lx", value);
psxCounters[5].mode = value;
psxCounters[5].mode|= 0x0400;
switch(value & 0x6000)
{
case 0x0000: psxCounters[5].rate = 1; break;
case 0x2000: psxCounters[5].rate = 8; break;
case 0x4000: psxCounters[5].rate = 16; break;
case 0x6000: psxCounters[5].rate = 256; break;
}
// Need to set a rate and target
if((psxCounters[5].mode & 0x7) == 0x7 || (psxCounters[5].mode & 0x7) == 0x1)
{
Console::WriteLn("Gate set on IOP C5, disabling");
psxCounters[5].mode |= IOPCNT_STOPPED;
}
psxCounters[5].count = 0;
psxCounters[5].sCycleT = psxRegs.cycle;
psxCounters[5].target &= 0xffffffff;
_rcntSet( 5 );
} }
//////////////////////////////////////////////////////////////////////////////////////////
//
void psxRcntWtarget16(int index, u32 value) void psxRcntWtarget16(int index, u32 value)
{ {
assert( index < 3 ); assert( index < 3 );

View File

@ -34,30 +34,24 @@ struct psxCounter {
#endif #endif
extern psxCounter psxCounters[NUM_COUNTERS]; extern psxCounter psxCounters[NUM_COUNTERS];
extern s32 psxNextCounter;
extern u32 psxNextsCounter;
void psxRcntInit(); extern void psxRcntInit();
void psxRcntUpdate(); extern void psxRcntUpdate();
void cntspu2async(); extern void cntspu2async();
void psxRcntWcount16(int index, u32 value); extern void psxRcntWcount16(int index, u16 value);
void psxRcntWcount32(int index, u32 value); extern void psxRcntWcount32(int index, u32 value);
void psxRcnt0Wmode(u32 value); extern void psxRcntWmode16(int index, u32 value);
void psxRcnt1Wmode(u32 value); extern void psxRcntWmode32(int index, u32 value);
void psxRcnt2Wmode(u32 value); extern void psxRcntWtarget16(int index, u32 value);
void psxRcnt3Wmode(u32 value); extern void psxRcntWtarget32(int index, u32 value);
void psxRcnt4Wmode(u32 value); extern u16 psxRcntRcount16(int index);
void psxRcnt5Wmode(u32 value); extern u32 psxRcntRcount32(int index);
void psxRcntWtarget16(int index, u32 value); extern u64 psxRcntCycles(int index);
void psxRcntWtarget32(int index, u32 value);
u16 psxRcntRcount16(int index);
u32 psxRcntRcount32(int index);
u64 psxRcntCycles(int index);
void psxVBlankStart(); extern void psxVBlankStart();
void psxVBlankEnd(); extern void psxVBlankEnd();
void psxCheckStartGate16(int i); extern void psxCheckStartGate16(int i);
void psxCheckEndGate16(int i); extern void psxCheckEndGate16(int i);
//static void psxCheckStartGate32(int i); //static void psxCheckStartGate32(int i);
//static void psxCheckEndGate32(int i); //static void psxCheckEndGate32(int i);

View File

@ -618,8 +618,8 @@ u32 psxHwRead32(u32 add) {
} }
// A buffer that stores messages until it gets a /n or the number of chars (g_pbufi) is more then 1023. // A buffer that stores messages until it gets a /n or the number of chars (g_pbufi) is more then 1023.
s8 g_pbuf[1024]; static s8 g_pbuf[1024];
int g_pbufi; static int g_pbufi;
void psxHwWrite8(u32 add, u8 value) { void psxHwWrite8(u32 add, u8 value) {
if (add >= HW_USB_START && add < HW_USB_END) { if (add >= HW_USB_START && add < HW_USB_END) {
USBwrite8(add, value); return; USBwrite8(add, value); return;
@ -768,7 +768,7 @@ void psxHwWrite16(u32 add, u16 value) {
psxRcntWcount16(0, value); return; psxRcntWcount16(0, value); return;
case IOP_T0_MODE: case IOP_T0_MODE:
PSXCNT_LOG("COUNTER 0 MODE 16bit write %x", value); PSXCNT_LOG("COUNTER 0 MODE 16bit write %x", value);
psxRcnt0Wmode(value); return; psxRcntWmode16(0, value); return;
case IOP_T0_TARGET: case IOP_T0_TARGET:
PSXCNT_LOG("COUNTER 0 TARGET 16bit write %x", value); PSXCNT_LOG("COUNTER 0 TARGET 16bit write %x", value);
psxRcntWtarget16(0, value); return; psxRcntWtarget16(0, value); return;
@ -778,7 +778,7 @@ void psxHwWrite16(u32 add, u16 value) {
psxRcntWcount16(1, value); return; psxRcntWcount16(1, value); return;
case IOP_T1_MODE: case IOP_T1_MODE:
PSXCNT_LOG("COUNTER 1 MODE 16bit write %x", value); PSXCNT_LOG("COUNTER 1 MODE 16bit write %x", value);
psxRcnt1Wmode(value); return; psxRcntWmode16(1, value); return;
case IOP_T1_TARGET: case IOP_T1_TARGET:
PSXCNT_LOG("COUNTER 1 TARGET 16bit write %x", value); PSXCNT_LOG("COUNTER 1 TARGET 16bit write %x", value);
psxRcntWtarget16(1, value); return; psxRcntWtarget16(1, value); return;
@ -788,7 +788,7 @@ void psxHwWrite16(u32 add, u16 value) {
psxRcntWcount16(2, value); return; psxRcntWcount16(2, value); return;
case IOP_T2_MODE: case IOP_T2_MODE:
PSXCNT_LOG("COUNTER 2 MODE 16bit write %x", value); PSXCNT_LOG("COUNTER 2 MODE 16bit write %x", value);
psxRcnt2Wmode(value); return; psxRcntWmode16(2, value); return;
case IOP_T2_TARGET: case IOP_T2_TARGET:
PSXCNT_LOG("COUNTER 2 TARGET 16bit write %x", value); PSXCNT_LOG("COUNTER 2 TARGET 16bit write %x", value);
psxRcntWtarget16(2, value); return; psxRcntWtarget16(2, value); return;
@ -803,7 +803,7 @@ void psxHwWrite16(u32 add, u16 value) {
psxRcntWcount32(3, value); return; psxRcntWcount32(3, value); return;
case IOP_T3_MODE: case IOP_T3_MODE:
PSXCNT_LOG("COUNTER 3 MODE 16bit write %lx", value); PSXCNT_LOG("COUNTER 3 MODE 16bit write %lx", value);
psxRcnt3Wmode(value); return; psxRcntWmode32(3, value); return;
case IOP_T3_TARGET: case IOP_T3_TARGET:
PSXCNT_LOG("COUNTER 3 TARGET 16bit write %lx", value); PSXCNT_LOG("COUNTER 3 TARGET 16bit write %lx", value);
psxRcntWtarget32(3, value); return; psxRcntWtarget32(3, value); return;
@ -813,7 +813,7 @@ void psxHwWrite16(u32 add, u16 value) {
psxRcntWcount32(4, value); return; psxRcntWcount32(4, value); return;
case IOP_T4_MODE: case IOP_T4_MODE:
PSXCNT_LOG("COUNTER 4 MODE 16bit write %lx", value); PSXCNT_LOG("COUNTER 4 MODE 16bit write %lx", value);
psxRcnt4Wmode(value); return; psxRcntWmode32(4, value); return;
case IOP_T4_TARGET: case IOP_T4_TARGET:
PSXCNT_LOG("COUNTER 4 TARGET 16bit write %lx", value); PSXCNT_LOG("COUNTER 4 TARGET 16bit write %lx", value);
psxRcntWtarget32(4, value); return; psxRcntWtarget32(4, value); return;
@ -823,7 +823,7 @@ void psxHwWrite16(u32 add, u16 value) {
psxRcntWcount32(5, value); return; psxRcntWcount32(5, value); return;
case IOP_T5_MODE: case IOP_T5_MODE:
PSXCNT_LOG("COUNTER 5 MODE 16bit write %lx", value); PSXCNT_LOG("COUNTER 5 MODE 16bit write %lx", value);
psxRcnt5Wmode(value); return; psxRcntWmode32(5, value); return;
case IOP_T5_TARGET: case IOP_T5_TARGET:
PSXCNT_LOG("COUNTER 5 TARGET 16bit write %lx", value); PSXCNT_LOG("COUNTER 5 TARGET 16bit write %lx", value);
psxRcntWtarget32(5, value); return; psxRcntWtarget32(5, value); return;
@ -1180,7 +1180,7 @@ void psxHwWrite32(u32 add, u32 value) {
psxRcntWcount16(0, value ); return; psxRcntWcount16(0, value ); return;
case IOP_T0_MODE: case IOP_T0_MODE:
PSXCNT_LOG("COUNTER 0 MODE 32bit write %lx", value); PSXCNT_LOG("COUNTER 0 MODE 32bit write %lx", value);
psxRcnt0Wmode(value); return; psxRcntWmode16(0, value); return;
case IOP_T0_TARGET: case IOP_T0_TARGET:
PSXCNT_LOG("COUNTER 0 TARGET 32bit write %lx", value); PSXCNT_LOG("COUNTER 0 TARGET 32bit write %lx", value);
psxRcntWtarget16(0, value ); return; psxRcntWtarget16(0, value ); return;
@ -1190,7 +1190,7 @@ void psxHwWrite32(u32 add, u32 value) {
psxRcntWcount16(1, value ); return; psxRcntWcount16(1, value ); return;
case IOP_T1_MODE: case IOP_T1_MODE:
PSXCNT_LOG("COUNTER 1 MODE 32bit write %lx", value); PSXCNT_LOG("COUNTER 1 MODE 32bit write %lx", value);
psxRcnt1Wmode(value); return; psxRcntWmode16(1, value); return;
case IOP_T1_TARGET: case IOP_T1_TARGET:
PSXCNT_LOG("COUNTER 1 TARGET 32bit write %lx", value); PSXCNT_LOG("COUNTER 1 TARGET 32bit write %lx", value);
psxRcntWtarget16(1, value ); return; psxRcntWtarget16(1, value ); return;
@ -1200,7 +1200,7 @@ void psxHwWrite32(u32 add, u32 value) {
psxRcntWcount16(2, value ); return; psxRcntWcount16(2, value ); return;
case IOP_T2_MODE: case IOP_T2_MODE:
PSXCNT_LOG("COUNTER 2 MODE 32bit write %lx", value); PSXCNT_LOG("COUNTER 2 MODE 32bit write %lx", value);
psxRcnt2Wmode(value); return; psxRcntWmode16(0, value); return;
case IOP_T2_TARGET: case IOP_T2_TARGET:
PSXCNT_LOG("COUNTER 2 TARGET 32bit write %lx", value); PSXCNT_LOG("COUNTER 2 TARGET 32bit write %lx", value);
psxRcntWtarget16(2, value); return; psxRcntWtarget16(2, value); return;
@ -1210,7 +1210,7 @@ void psxHwWrite32(u32 add, u32 value) {
psxRcntWcount32(3, value); return; psxRcntWcount32(3, value); return;
case IOP_T3_MODE: case IOP_T3_MODE:
PSXCNT_LOG("COUNTER 3 MODE 32bit write %lx", value); PSXCNT_LOG("COUNTER 3 MODE 32bit write %lx", value);
psxRcnt3Wmode(value); return; psxRcntWmode32(3, value); return;
case IOP_T3_TARGET: case IOP_T3_TARGET:
PSXCNT_LOG("COUNTER 3 TARGET 32bit write %lx", value); PSXCNT_LOG("COUNTER 3 TARGET 32bit write %lx", value);
psxRcntWtarget32(3, value); return; psxRcntWtarget32(3, value); return;
@ -1220,7 +1220,7 @@ void psxHwWrite32(u32 add, u32 value) {
psxRcntWcount32(4, value); return; psxRcntWcount32(4, value); return;
case IOP_T4_MODE: case IOP_T4_MODE:
PSXCNT_LOG("COUNTER 4 MODE 32bit write %lx", value); PSXCNT_LOG("COUNTER 4 MODE 32bit write %lx", value);
psxRcnt4Wmode(value); return; psxRcntWmode32(4, value); return;
case IOP_T4_TARGET: case IOP_T4_TARGET:
PSXCNT_LOG("COUNTER 4 TARGET 32bit write %lx", value); PSXCNT_LOG("COUNTER 4 TARGET 32bit write %lx", value);
psxRcntWtarget32(4, value); return; psxRcntWtarget32(4, value); return;
@ -1230,7 +1230,7 @@ void psxHwWrite32(u32 add, u32 value) {
psxRcntWcount32(5, value); return; psxRcntWcount32(5, value); return;
case IOP_T5_MODE: case IOP_T5_MODE:
PSXCNT_LOG("COUNTER 5 MODE 32bit write %lx", value); PSXCNT_LOG("COUNTER 5 MODE 32bit write %lx", value);
psxRcnt5Wmode(value); return; psxRcntWmode32(5, value); return;
case IOP_T5_TARGET: case IOP_T5_TARGET:
PSXCNT_LOG("COUNTER 5 TARGET 32bit write %lx", value); PSXCNT_LOG("COUNTER 5 TARGET 32bit write %lx", value);
psxRcntWtarget32(5, value); return; psxRcntWtarget32(5, value); return;
@ -1335,16 +1335,20 @@ void psxHw4Write8(u32 add, u8 value)
PSXHW_LOG("Known 8bit write to addr 0x%x = 0x%x", add, value); PSXHW_LOG("Known 8bit write to addr 0x%x = 0x%x", add, value);
} }
void psxDmaInterrupt(int n) { 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);
iopIntcIrq( 3 ); iopIntcIrq( 3 );
} }
} }
void psxDmaInterrupt2(int n) { void psxDmaInterrupt2(int n)
if (HW_DMA_ICR2 & (1 << (16 + n))) { {
if (HW_DMA_ICR2 & (1 << (16 + n)))
{
/* if (HW_DMA_ICR2 & (1 << (24 + n))) { /* if (HW_DMA_ICR2 & (1 << (24 + n))) {
Console::WriteLn("*PCSX2*: HW_DMA_ICR2 n=%d already set", params n); Console::WriteLn("*PCSX2*: HW_DMA_ICR2 n=%d already set", params n);
} }

View File

@ -16,18 +16,69 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#ifndef __PSXHW_H__ #pragma once
#define __PSXHW_H__
#include "R3000A.h"
#include "IopMem.h" #include "IopMem.h"
#define HW_USB_START 0x1f801600 static const u32
#define HW_USB_END 0x1f801700 HW_USB_START = 0x1f801600,
#define HW_FW_START 0x1f808400 HW_USB_END = 0x1f801700,
#define HW_FW_END 0x1f808550 HW_FW_START = 0x1f808400,
#define HW_SPU2_START 0x1f801c00 HW_FW_END = 0x1f808550, // end addr for FW is a guess...
#define HW_SPU2_END 0x1f801e00 HW_SPU2_START = 0x1f801c00,
HW_SPU2_END = 0x1f801e00;
static const u32
HW_SSBUS_SPD_ADDR = 0x1f801000,
HW_SSBUS_PIO_ADDR = 0x1f801004,
HW_SSBUS_SPD_DELAY = 0x1f801008,
HW_SSBUS_DEV1_DELAY = 0x1f80100C,
HW_SSBUS_ROM_DELAY = 0x1f801010,
HW_SSBUS_SPU_DELAY = 0x1f801014,
HW_SSBUS_DEV5_DELAY = 0x1f801018,
HW_SSBUS_PIO_DELAY = 0x1f80101c,
HW_SSBUS_COM_DELAY = 0x1f801020,
HW_SIO_DATA = 0x1f801040, // SIO read/write register
HW_SIO_STAT = 0x1f801044,
HW_SIO_MODE = 0x1f801048,
HW_SIO_CTRL = 0x1f80104a,
HW_SIO_BAUD = 0x1f80104e,
HW_IREG = 0x1f801070,
HW_IMASK = 0x1f801074,
HW_ICTRL = 0x1f801078,
HW_SSBUS_DEV1_ADDR = 0x1f801400,
HW_SSBUS_SPU_ADDR = 0x1f801404,
HW_SSBUS_DEV5_ADDR = 0x1f801408,
HW_SSBUS_SPU1_ADDR = 0x1f80140c,
HW_SSBUS_DEV9_ADDR3 = 0x1f801410,
HW_SSBUS_SPU1_DELAY = 0x1f801414,
HW_SSBUS_DEV9_DELAY2= 0x1f801418,
HW_SSBUS_DEV9_DELAY3= 0x1f80141c,
HW_SSBUS_DEV9_DELAY1= 0x1f801420,
HW_ICFG = 0x1f801450,
HW_DEV9_DATA = 0x1f80146e, // DEV9 read/write register
// CDRom registers are used for various command, status, and data stuff.
HW_CDR_DATA0 = 0x1f801800, // CDROM multipurpose data register 1
HW_CDR_DATA1 = 0x1f801801, // CDROM multipurpose data register 2
HW_CDR_DATA2 = 0x1f801802, // CDROM multipurpose data register 3
HW_CDR_DATA3 = 0x1f801803, // CDROM multipurpose data register 4
// SIO2 is a DMA interface for the SIO.
HW_SIO2_DATAIN = 0x1F808260,
HW_SIO2_FIFO = 0x1f808264,
HW_SIO2_CTRL = 0x1f808268,
HW_SIO2_RECV1 = 0x1f80826c,
HW_SIO2_RECV2 = 0x1f808270,
HW_SIO2_RECV3 = 0x1f808274,
HW_SIO2_INTR = 0x1f808280;
/* Registers for the IOP Counters */ /* Registers for the IOP Counters */
enum IOPCountRegs enum IOPCountRegs
@ -37,7 +88,7 @@ enum IOPCountRegs
IOP_T2_COUNT = 0x1f801120, IOP_T2_COUNT = 0x1f801120,
IOP_T3_COUNT = 0x1f801480, IOP_T3_COUNT = 0x1f801480,
IOP_T4_COUNT = 0x1f801490, IOP_T4_COUNT = 0x1f801490,
IOP_T5_COUNT = 0x1f8014a0, IOP_T5_COUNT = 0x1f8014a0,
IOP_T0_MODE = 0x1f801104, IOP_T0_MODE = 0x1f801104,
IOP_T1_MODE = 0x1f801114, IOP_T1_MODE = 0x1f801114,
@ -46,7 +97,7 @@ enum IOPCountRegs
IOP_T4_MODE = 0x1f801494, IOP_T4_MODE = 0x1f801494,
IOP_T5_MODE = 0x1f8014a4, IOP_T5_MODE = 0x1f8014a4,
IOP_T0_TARGET= 0x1f801108, IOP_T0_TARGET = 0x1f801108,
IOP_T1_TARGET = 0x1f801118, IOP_T1_TARGET = 0x1f801118,
IOP_T2_TARGET = 0x1f801128, IOP_T2_TARGET = 0x1f801128,
IOP_T3_TARGET = 0x1f801488, IOP_T3_TARGET = 0x1f801488,
@ -166,6 +217,8 @@ extern void PSX_INT( IopEventId n, s32 ecycle);
extern void psxSetNextBranch( u32 startCycle, s32 delta ); extern void psxSetNextBranch( u32 startCycle, s32 delta );
extern void psxSetNextBranchDelta( s32 delta ); extern void psxSetNextBranchDelta( s32 delta );
extern int iopTestCycle( u32 startCycle, s32 delta );
extern void _iopTestInterrupts();
void psxHwReset(); void psxHwReset();
u8 psxHwRead8 (u32 add); u8 psxHwRead8 (u32 add);
@ -192,5 +245,3 @@ void psxHwConstWrite16(u32 add, int mmreg);
void psxHwConstWrite32(u32 add, int mmreg); void psxHwConstWrite32(u32 add, int mmreg);
int psxHw4ConstRead8 (u32 x86reg, u32 add, u32 sign); int psxHw4ConstRead8 (u32 x86reg, u32 add, u32 sign);
void psxHw4ConstWrite8(u32 add, int mmreg); void psxHw4ConstWrite8(u32 add, int mmreg);
#endif /* __PSXHW_H__ */

View File

@ -72,13 +72,9 @@ void psxMemReset()
for (int i=0; i<0x0080; i++) for (int i=0; i<0x0080; i++)
{ {
psxMemWLUT[i + 0x0000] = (uptr)&psxM[(i & 0x1f) << 16]; psxMemWLUT[i + 0x0000] = (uptr)&psxM[(i & 0x1f) << 16];
//psxMemWLUT[i + 0x8000] = (uptr)&psxM[(i & 0x1f) << 16];
//psxMemWLUT[i + 0xa000] = (uptr)&psxM[(i & 0x1f) << 16];
// RLUTs, accessed through WLUT. // RLUTs, accessed through WLUT.
psxMemWLUT[i + 0x2000] = (uptr)&psxM[(i & 0x1f) << 16]; psxMemWLUT[i + 0x2000] = (uptr)&psxM[(i & 0x1f) << 16];
//psxMemWLUT[i + 0x18000] = (uptr)&psxM[(i & 0x1f) << 16];
//psxMemWLUT[i + 0x1a000] = (uptr)&psxM[(i & 0x1f) << 16];
} }
// A few single-page allocations for things we store in special locations. // A few single-page allocations for things we store in special locations.
@ -94,25 +90,17 @@ void psxMemReset()
for (int i=0; i<0x0040; i++) for (int i=0; i<0x0040; i++)
{ {
psxMemWLUT[i + 0x2000 + 0x1fc0] = (uptr)&PS2MEM_ROM[i << 16]; psxMemWLUT[i + 0x2000 + 0x1fc0] = (uptr)&PS2MEM_ROM[i << 16];
//psxMemWLUT[i + 0x19fc0] = (uptr)&PS2MEM_ROM[i << 16];
//psxMemWLUT[i + 0x1bfc0] = (uptr)&PS2MEM_ROM[i << 16];
} }
for (int i=0; i<0x0004; i++) for (int i=0; i<0x0004; i++)
{ {
psxMemWLUT[i + 0x2000 + 0x1e00] = (uptr)&PS2MEM_ROM1[i << 16]; psxMemWLUT[i + 0x2000 + 0x1e00] = (uptr)&PS2MEM_ROM1[i << 16];
//psxMemWLUT[i + 0x19e00] = (uptr)&PS2MEM_ROM1[i << 16];
//psxMemWLUT[i + 0x1be00] = (uptr)&PS2MEM_ROM1[i << 16];
} }
// sif!! (which is read only? (air)) // sif!! (which is read only? (air))
psxMemWLUT[0x2000 + 0x1d00] = (uptr)psxS; psxMemWLUT[0x2000 + 0x1d00] = (uptr)psxS;
//psxMemWLUT[0x1bd00] = (uptr)psxS; //psxMemWLUT[0x1bd00] = (uptr)psxS;
// why isn't scratchpad read/write? (air)
//for (i=0; i<0x0001; i++) psxMemWLUT[i + 0x1d00] = (uptr)&psxS[i << 16];
//for (i=0; i<0x0001; i++) psxMemWLUT[i + 0xbd00] = (uptr)&psxS[i << 16];
// this one looks like an old hack for some special write-only memory area, // this one looks like an old hack for some special write-only memory area,
// but leaving it in for reference (air) // but leaving it in for reference (air)
//for (i=0; i<0x0008; i++) psxMemWLUT[i + 0xbfc0] = (uptr)&psR[i << 16]; //for (i=0; i<0x0008; i++) psxMemWLUT[i + 0xbfc0] = (uptr)&psR[i << 16];
@ -136,10 +124,21 @@ u8 iopMemRead8(u32 mem)
if (t == 0x1f80) if (t == 0x1f80)
{ {
if (mem < 0x1f801000) switch( mem & 0xf000 )
return psxHu8(mem); {
else case 0x1000: return IopMemory::iopHwRead8_Page1(mem);
return psxHwRead8(mem); case 0x3000: return IopMemory::iopHwRead8_Page3(mem);
case 0x8000: return IopMemory::iopHwRead8_Page8(mem);
// code for regression testing -- selectively enable these to help narrow out
// which register became buggy with the new Hw handlers.
//case 0x1000: return psxHwRead8(mem);
//case 0x3000: return psxHwRead8(mem);
//case 0x8000: return psxHwRead8(mem);
default:
return psxHu8(mem);
}
} }
else if (t == 0x1f40) else if (t == 0x1f40)
{ {
@ -169,10 +168,21 @@ u16 iopMemRead16(u32 mem)
if (t == 0x1f80) if (t == 0x1f80)
{ {
if (mem < 0x1f801000) switch( mem & 0xf000 )
return psxHu16(mem); {
else case 0x1000: return IopMemory::iopHwRead16_Page1(mem);
return psxHwRead16(mem); case 0x3000: return IopMemory::iopHwRead16_Page3(mem);
case 0x8000: return IopMemory::iopHwRead16_Page8(mem);
// code for regression testing -- selectively enable these to help narrow out
// which register became buggy with the new Hw handlers.
//case 0x1000: return psxHwRead16(mem);
//case 0x3000: return psxHwRead16(mem);
//case 0x8000: return psxHwRead16(mem);
default:
return psxHu16(mem);
}
} }
else else
{ {
@ -224,10 +234,21 @@ u32 iopMemRead32(u32 mem)
if (t == 0x1f80) if (t == 0x1f80)
{ {
if (mem < 0x1f801000) switch( mem & 0xf000 )
return psxHu32(mem); {
else case 0x1000: return IopMemory::iopHwRead32_Page1(mem);
return psxHwRead32(mem); case 0x3000: return IopMemory::iopHwRead32_Page3(mem);
case 0x8000: return IopMemory::iopHwRead32_Page8(mem);
// code for regression testing -- selectively enable these to help narrow out
// which register became buggy with the new Hw handlers.
//case 0x1000: return psxHwRead32(mem);
//case 0x3000: return psxHwRead32(mem);
//case 0x8000: return psxHwRead32(mem);
default:
return psxHu32(mem);
}
} else } else
{ {
//see also Hw.c //see also Hw.c
@ -282,10 +303,31 @@ void iopMemWrite8(u32 mem, u8 value)
if (t == 0x1f80) if (t == 0x1f80)
{ {
if (mem < 0x1f801000) switch( mem & 0xf000 )
psxHu8(mem) = value; {
else // Regression testing: selectively pass ranges of registers to new or old
psxHwWrite8(mem, value); // handlers. Helps narrow out which area of registers is erroring out.
/*case 0x1000:
if( mem >= 0x1f801000 )
psxHwWrite8( mem, value );
else
IopMemory::iopHwWrite8_Page1(mem,value);
break;*/
case 0x1000: IopMemory::iopHwWrite8_Page1(mem,value); break;
case 0x3000: IopMemory::iopHwWrite8_Page3(mem,value); break;
case 0x8000: IopMemory::iopHwWrite8_Page8(mem,value); break;
// code for regression testing -- selectively enable these to help narrow out
// which register became buggy with the new Hw handlers.
//case 0x1000: psxHwWrite8(mem,value); break;
//case 0x3000: psxHwWrite8(mem,value); break;
//case 0x8000: psxHwWrite8(mem,value); break;
default:
psxHu8(mem) = value;
break;
}
} }
else if (t == 0x1f40) else if (t == 0x1f40)
{ {
@ -323,10 +365,29 @@ void iopMemWrite16(u32 mem, u16 value)
if (t == 0x1f80) if (t == 0x1f80)
{ {
if (mem < 0x1f801000) switch( mem & 0xf000 )
psxHu16(mem) = value; {
else // Regression testing: selectively pass ranges of registers to new or old
psxHwWrite16(mem, value); // handlers. Helps narrow out which area of registers is erroring out.
/*case 0x1000:
if( mem >= 0x1f801000 )
psxHwWrite16( mem, value );
else
IopMemory::iopHwWrite16_Page1(mem,value);
break;*/
case 0x1000: IopMemory::iopHwWrite16_Page1(mem,value); break;
case 0x3000: IopMemory::iopHwWrite16_Page3(mem,value); break;
case 0x8000: IopMemory::iopHwWrite16_Page8(mem,value); break;
//case 0x1000: psxHwWrite16(mem,value); break;
//case 0x3000: psxHwWrite16(mem,value); break;
//case 0x8000: psxHwWrite16(mem,value); break;
default:
psxHu16(mem) = value;
break;
}
} else } else
{ {
u8* p = (u8 *)(psxMemWLUT[mem >> 16]); u8* p = (u8 *)(psxMemWLUT[mem >> 16]);
@ -386,10 +447,29 @@ void iopMemWrite32(u32 mem, u32 value)
if (t == 0x1f80) if (t == 0x1f80)
{ {
if (mem < 0x1f801000) switch( mem & 0xf000 )
psxHu32(mem) = value; {
else // Regression testing: selectively pass ranges of registers to new or old
psxHwWrite32(mem, value); // handlers. Helps narrow out which area of registers is erroring out.
/*case 0x1000:
if( mem >= 0x1f801528 )
psxHwWrite32( mem, value );
else
IopMemory::iopHwWrite32_Page1(mem,value);
break;*/
case 0x1000: IopMemory::iopHwWrite32_Page1(mem,value); break;
case 0x3000: IopMemory::iopHwWrite32_Page3(mem,value); break;
case 0x8000: IopMemory::iopHwWrite32_Page8(mem,value); break;
//case 0x1000: psxHwWrite32(mem,value); break;
//case 0x3000: psxHwWrite32(mem,value); break;
//case 0x8000: psxHwWrite32(mem,value); break;
default:
psxHu32(mem) = value;
break;
}
} else } else
{ {
//see also Hw.c //see also Hw.c

View File

@ -16,8 +16,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#ifndef __PSXMEMORY_H__ #pragma once
#define __PSXMEMORY_H__
extern u8 *psxM; extern u8 *psxM;
extern u8 *psxP; extern u8 *psxP;
@ -90,21 +89,40 @@ void iopMemWrite32(u32 mem, u32 value);
// x86reg and mmreg are always x86 regs // x86reg and mmreg are always x86 regs
void psxRecMemRead8(); void psxRecMemRead8();
int psxRecMemConstRead8(u32 x86reg, u32 mem, u32 sign);
void psxRecMemRead16(); void psxRecMemRead16();
int psxRecMemConstRead16(u32 x86reg, u32 mem, u32 sign);
void psxRecMemRead32(); void psxRecMemRead32();
int psxRecMemConstRead32(u32 x86reg, u32 mem);
void psxRecMemWrite8(); void psxRecMemWrite8();
int psxRecMemConstWrite8(u32 mem, int mmreg);
void psxRecMemWrite16(); void psxRecMemWrite16();
int psxRecMemConstWrite16(u32 mem, int mmreg);
void psxRecMemWrite32(); void psxRecMemWrite32();
int psxRecMemConstWrite32(u32 mem, int mmreg);
#endif /* __PSXMEMORY_H__ */ namespace IopMemory
{
// Sif functions not made yet (will for future Iop improvements):
extern u8 __fastcall SifRead8( u32 iopaddr );
extern u16 __fastcall SifRead16( u32 iopaddr );
extern u32 __fastcall SifRead32( u32 iopaddr );
extern void __fastcall SifWrite8( u32 iopaddr, u8 data );
extern void __fastcall SifWrite16( u32 iopaddr, u16 data );
extern void __fastcall SifWrite32( u32 iopaddr, u32 data );
extern u8 __fastcall iopHwRead8_Page1( u32 iopaddr );
extern u8 __fastcall iopHwRead8_Page3( u32 iopaddr );
extern u8 __fastcall iopHwRead8_Page8( u32 iopaddr );
extern u16 __fastcall iopHwRead16_Page1( u32 iopaddr );
extern u16 __fastcall iopHwRead16_Page3( u32 iopaddr );
extern u16 __fastcall iopHwRead16_Page8( u32 iopaddr );
extern u32 __fastcall iopHwRead32_Page1( u32 iopaddr );
extern u32 __fastcall iopHwRead32_Page3( u32 iopaddr );
extern u32 __fastcall iopHwRead32_Page8( u32 iopaddr );
extern void __fastcall iopHwWrite8_Page1( u32 iopaddr, u8 data );
extern void __fastcall iopHwWrite8_Page3( u32 iopaddr, u8 data );
extern void __fastcall iopHwWrite8_Page8( u32 iopaddr, u8 data );
extern void __fastcall iopHwWrite16_Page1( u32 iopaddr, u16 data );
extern void __fastcall iopHwWrite16_Page3( u32 iopaddr, u16 data );
extern void __fastcall iopHwWrite16_Page8( u32 iopaddr, u16 data );
extern void __fastcall iopHwWrite32_Page1( u32 iopaddr, u32 data );
extern void __fastcall iopHwWrite32_Page3( u32 iopaddr, u32 data );
extern void __fastcall iopHwWrite32_Page8( u32 iopaddr, u32 data );
}

445
pcsx2/ps2/Iop/IopHwRead.cpp Normal file
View File

@ -0,0 +1,445 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "PrecompiledHeader.h"
#include "IopHw_Internal.h"
namespace IopMemory
{
using namespace Internal;
//////////////////////////////////////////////////////////////////////////////////////////
//
u8 __fastcall iopHwRead8_Page1( u32 addr )
{
// all addresses are assumed to be prefixed with 0x1f801xxx:
jASSUME( (addr >> 12) == 0x1f801 );
u32 masked_addr = addr & 0x0fff;
u8 ret; // using a return var can be helpful in debugging.
switch( masked_addr )
{
mcase(HW_SIO_DATA): ret = sioRead8(); break;
// for use of serial port ignore for now
//case 0x50: ret = serial_read8(); break;
mcase(HW_DEV9_DATA): ret = DEV9read8( addr ); break;
mcase(HW_CDR_DATA0): ret = cdrRead0(); break;
mcase(HW_CDR_DATA1): ret = cdrRead1(); break;
mcase(HW_CDR_DATA2): ret = cdrRead2(); break;
mcase(HW_CDR_DATA3): ret = cdrRead3(); break;
default:
if( masked_addr >= 0x100 && masked_addr < 0x130 )
{
DevCon::Notice( "*Hardware Read8 from Counter16 [ignored] [addr=0x%02x]", params addr, psxHu8(addr) );
ret = psxHu8( addr );
}
else if( masked_addr >= 0x480 && masked_addr < 0x4a0 )
{
DevCon::Notice( "*Hardware Read8 from Counter32 [ignored] [addr=0x%02x]", params addr, psxHu8(addr) );
ret = psxHu8( addr );
}
else if( (masked_addr >= pgmsk(HW_USB_START)) && (masked_addr < pgmsk(HW_USB_END)) )
{
ret = USBread8( addr );
PSXHW_LOG( "Hardware Read8 from USB: addr 0x%08x = 0x%02x", addr, ret );
}
else
{
ret = psxHu8(addr);
PSXHW_LOG( "*Unknown Hardware Read8 from addr 0x%08x = 0x%02x", addr, ret );
}
return ret;
}
PSXHW_LOG( "*Hardware Read8 from %s, addr 0x%08x = 0x%02x", _log_GetIopHwName<u8>( addr ), addr, ret );
return ret;
}
//////////////////////////////////////////////////////////////////////////////////////////
//
u8 __fastcall iopHwRead8_Page3( u32 addr )
{
// all addresses are assumed to be prefixed with 0x1f803xxx:
jASSUME( (addr >> 12) == 0x1f803 );
u8 ret;
if( addr == 0x1f803100 ) // PS/EE/IOP conf related
ret = 0x10; // Dram 2M
else
ret = psxHu8( addr );
PSXHW_LOG( "Hardware Read8 from %s, addr 0x%08x = 0x%02x", _log_GetIopHwName<u8>( addr ), addr, psxHu8(addr) );
return ret;
}
//////////////////////////////////////////////////////////////////////////////////////////
//
u8 __fastcall iopHwRead8_Page8( u32 addr )
{
// all addresses are assumed to be prefixed with 0x1f808xxx:
jASSUME( (addr >> 12) == 0x1f808 );
u8 ret;
if( addr == HW_SIO2_FIFO )
ret = sio2_fifoOut();//sio2 serial data feed/fifo_out
else
ret = psxHu8( addr );
PSXHW_LOG( "Hardware Read8 from %s, addr 0x%08x = 0x%02x", _log_GetIopHwName<u8>( addr ), addr, psxHu8(addr) );
return ret;
}
//////////////////////////////////////////////////////////////////////////////////////////
//
template< typename T >
static __forceinline T _HwRead_16or32_Page1( u32 addr )
{
// all addresses are assumed to be prefixed with 0x1f801xxx:
jASSUME( (addr >> 12) == 0x1f801 );
// all addresses should be aligned to the data operand size:
jASSUME(
( sizeof(T) == 2 && (addr & 1) == 0 ) ||
( sizeof(T) == 4 && (addr & 3) == 0 )
);
u32 masked_addr = pgmsk( addr );
T ret;
// ------------------------------------------------------------------------
// Counters, 16-bit varieties!
//
if( masked_addr >= 0x100 && masked_addr < 0x130 )
{
int cntidx = ( masked_addr >> 4 ) & 0xf;
switch( masked_addr & 0xf )
{
case 0x0:
ret = (T)psxRcntRcount16( cntidx );
break;
case 0x4:
ret = psxCounters[cntidx].mode;
// hmm! The old code only did this bitwise math for 16 bit reads.
// Logic indicates it should do the math consistently. Question is,
// should it do the logic for both 16 and 32, or not do logic at all?
psxCounters[cntidx].mode &= ~0x1800;
psxCounters[cntidx].mode |= 0x400;
break;
case 0x8:
ret = psxCounters[cntidx].target;
break;
default:
ret = psxHu32(addr);
break;
}
}
// ------------------------------------------------------------------------
// Counters, 32-bit varieties!
//
else if( masked_addr >= 0x480 && masked_addr < 0x4b0 )
{
int cntidx = (( masked_addr >> 4 ) & 0xf) - 5;
switch( masked_addr & 0xf )
{
case 0x0:
ret = (T)psxRcntRcount32( cntidx );
break;
case 0x2:
ret = (T)(psxRcntRcount32( cntidx ) >> 16);
break;
case 0x4:
ret = psxCounters[cntidx].mode;
// hmm! The old code only did the following bitwise math for 16 bit reads.
// Logic indicates it should do the math consistently. Question is,
// should it do the logic for both 16 and 32, or not do logic at all?
psxCounters[cntidx].mode &= ~0x1800;
psxCounters[cntidx].mode |= 0x400;
break;
case 0x8:
ret = psxCounters[cntidx].target;
break;
case 0xa:
ret = psxCounters[cntidx].target >> 16;
break;
default:
ret = psxHu32(addr);
break;
}
}
// ------------------------------------------------------------------------
// USB, with both 16 and 32 bit interfaces
//
else if( masked_addr >= pgmsk(HW_USB_START) && masked_addr < pgmsk(HW_USB_END) )
{
ret = (sizeof(T) == 2) ? USBread16( addr ) : USBread32( addr );
}
// ------------------------------------------------------------------------
// SPU2, accessible in 16 bit mode only!
//
else if( masked_addr >= pgmsk(HW_SPU2_START) && masked_addr < pgmsk(HW_SPU2_END) )
{
if( sizeof(T) == 2 )
ret = SPU2read( addr );
else
{
DevCon::Notice( "*PCSX2* SPU2 Hardware Read32 (addr=0x%08X)? What manner of trickery is this?!", params addr );
ret = psxHu32(addr);
}
}
else
{
switch( masked_addr )
{
// ------------------------------------------------------------------------
mcase(HW_SIO_DATA):
ret = sioRead8();
ret |= sioRead8() << 8;
if( sizeof(T) == 4 )
{
ret |= sioRead8() << 16;
ret |= sioRead8() << 24;
}
break;
mcase(HW_SIO_STAT):
ret = sio.StatReg;
break;
mcase(HW_SIO_MODE):
ret = sio.ModeReg;
if( sizeof(T) == 4 )
{
// My guess on 32-bit accesses. Dunno yet what the real hardware does. --air
ret |= sio.CtrlReg << 16;
}
break;
mcase(HW_SIO_CTRL):
ret = sio.CtrlReg;
break;
mcase(HW_SIO_BAUD):
ret = sio.BaudReg;
break;
// ------------------------------------------------------------------------
//Serial port stuff not support now ;P
// case 0x050: hard = serial_read32(); break;
// case 0x054: hard = serial_status_read(); break;
// case 0x05a: hard = serial_control_read(); break;
// case 0x05e: hard = serial_baud_read(); break;
mcase(HW_ICTRL):
ret = psxHu32(0x1078);
psxHu32(0x1078) = 0;
break;
mcase(HW_ICTRL+2):
ret = psxHu16(0x107a);
psxHu32(0x1078) = 0; // most likely should clear all 32 bits here.
break;
// ------------------------------------------------------------------------
// Soon-to-be outdated SPU2 DMA hack (spu2 manages its own DMA MADR).
//
mcase(0x1f8010C0):
ret = SPU2ReadMemAddr(0);
break;
mcase(0x1f801500):
ret = SPU2ReadMemAddr(1);
break;
// ------------------------------------------------------------------------
// Legacy GPU emulation (not needed).
// The IOP emulates the GPU itself through the EE's hardware.
/*case 0x810:
PSXHW_LOG("GPU DATA 32bit write %lx", value);
GPU_writeData(value); return;
case 0x814:
PSXHW_LOG("GPU STATUS 32bit write %lx", value);
GPU_writeStatus(value); return;
case 0x820:
mdecWrite0(value); break;
case 0x824:
mdecWrite1(value); break;*/
// ------------------------------------------------------------------------
mcase(0x1f80146e):
ret = DEV9read16( addr );
break;
default:
ret = psxHu32(addr);
break;
}
}
PSXHW_LOG( "Hardware Read%s from %s, addr 0x%08x = 0x%04x",
(sizeof(T) == 2) ? "16" : "32", _log_GetIopHwName<T>( addr ), addr, ret
);
return ret;
}
// Some Page 2 mess? I love random question marks for comments!
//case 0x1f802030: hard = //int_2000????
//case 0x1f802040: hard =//dip switches...??
//////////////////////////////////////////////////////////////////////////////////////////
//
u16 __fastcall iopHwRead16_Page1( u32 addr )
{
return _HwRead_16or32_Page1<u16>( addr );
}
//////////////////////////////////////////////////////////////////////////////////////////
//
u16 __fastcall iopHwRead16_Page3( u32 addr )
{
// all addresses are assumed to be prefixed with 0x1f803xxx:
jASSUME( (addr >> 12) == 0x1f803 );
u16 ret = psxHu16(addr);
PSXHW_LOG( "Hardware Read16 from %s, addr 0x%08x = 0x%04x", _log_GetIopHwName<u16>( addr ), addr, ret );
return ret;
}
//////////////////////////////////////////////////////////////////////////////////////////
//
u16 __fastcall iopHwRead16_Page8( u32 addr )
{
// all addresses are assumed to be prefixed with 0x1f808xxx:
jASSUME( (addr >> 12) == 0x1f808 );
u16 ret = psxHu16(addr);
PSXHW_LOG( "Hardware Read16 from %s, addr 0x%08x = 0x%04x", _log_GetIopHwName<u16>( addr ), addr, ret );
return ret;
}
//////////////////////////////////////////////////////////////////////////////////////////
//
u32 __fastcall iopHwRead32_Page1( u32 addr )
{
return _HwRead_16or32_Page1<u32>( addr );
}
//////////////////////////////////////////////////////////////////////////////////////////
//
u32 __fastcall iopHwRead32_Page3( u32 addr )
{
// all addresses are assumed to be prefixed with 0x1f803xxx:
jASSUME( (addr >> 12) == 0x1f803 );
const u32 ret = psxHu32(addr);
PSXHW_LOG( "Hardware Read32 from %s, addr 0x%08x = 0x%08x", _log_GetIopHwName<u32>( addr ), addr, ret );
return ret;
}
//////////////////////////////////////////////////////////////////////////////////////////
//
u32 __fastcall iopHwRead32_Page8( u32 addr )
{
// all addresses are assumed to be prefixed with 0x1f808xxx:
jASSUME( (addr >> 12) == 0x1f808 );
u32 masked_addr = addr & 0x0fff;
u32 ret;
if( masked_addr >= 0x200 )
{
if( masked_addr < 0x240 )
{
const int parm = (masked_addr-0x200) / 4;
ret = sio2_getSend3( parm );
}
else if( masked_addr < 0x260 )
{
// SIO2 Send commands alternate registers. First reg maps to Send1, second
// to Send2, third to Send1, etc. And the following clever code does this:
const int parm = (masked_addr-0x240) / 8;
ret = (masked_addr & 4) ? sio2_getSend2( parm ) : sio2_getSend1( parm );
}
else
{
switch( masked_addr )
{
mcase(0x1f801264): // unknown / reserved.
ret = psxHu32(addr);
break;
mcase(HW_SIO2_CTRL):
ret = sio2_getCtrl();
break;
mcase(HW_SIO2_RECV1):
ret = sio2_getRecv1();
break;
mcase(HW_SIO2_RECV2):
ret = sio2_getRecv2();
break;
mcase(HW_SIO2_RECV3):
ret = sio2_getRecv3();
break;
mcase(0x1f808278):
ret = sio2_get8278();
break;
mcase(0x1f80827C):
ret = sio2_get827C();
break;
mcase(HW_SIO2_INTR):
ret = sio2_getIntr();
break;
jNO_DEFAULT;
}
}
}
else ret = psxHu32(addr);
PSXHW_LOG( "Hardware Read32 from %s, addr 0x%08x = 0x%02x", _log_GetIopHwName<u32>( addr ), addr, ret );
return ret;
}
}

View File

@ -0,0 +1,529 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "PrecompiledHeader.h"
#include "IopHw_Internal.h"
namespace IopMemory {
using namespace Internal;
//////////////////////////////////////////////////////////////////////////////////////////
//
void __fastcall iopHwWrite8_Page1( u32 addr, u8 val )
{
// all addresses are assumed to be prefixed with 0x1f801xxx:
jASSUME( (addr >> 12) == 0x1f801 );
u32 masked_addr = pgmsk( addr );
switch( masked_addr )
{
mcase(HW_SIO_DATA): sioWrite8( val ); break;
// for use of serial port ignore for now
//case 0x50: serial_write8( val ); break;
mcase(HW_DEV9_DATA): DEV9write8( addr, val ); break;
mcase(HW_CDR_DATA0): cdrWrite0( val ); break;
mcase(HW_CDR_DATA1): cdrWrite1( val ); break;
mcase(HW_CDR_DATA2): cdrWrite2( val ); break;
mcase(HW_CDR_DATA3): cdrWrite3( val ); break;
default:
if( masked_addr >= 0x100 && masked_addr < 0x130 )
{
DevCon::Notice( "*Hardware Write8 to Counter16 [ignored] [addr=0x%02x]", params addr, psxHu8(addr) );
psxHu8( addr ) = val;
}
else if( masked_addr >= 0x480 && masked_addr < 0x4a0 )
{
DevCon::Notice( "*Hardware Write8 to Counter32 [ignored] [addr=0x%02x]", params addr, psxHu8(addr) );
psxHu8( addr ) = val;
}
else if( masked_addr >= pgmsk(HW_USB_START) && masked_addr < pgmsk(HW_USB_END) )
{
USBwrite8( addr, val );
}
else
{
psxHu8(addr) = val;
}
break;
}
PSXHW_LOG( "*Hardware Write8 to %s, addr 0x%08x = 0x%02x\n", _log_GetIopHwName<u8>(addr), addr, val );
}
static char g_pbuf[1024];
static int g_pbufi;
void __fastcall iopHwWrite8_Page3( u32 addr, u8 val )
{
// all addresses are assumed to be prefixed with 0x1f803xxx:
jASSUME( (addr >> 12) == 0x1f803 );
if( addr == 0x1f80380c ) // STDOUT
{
bool flush = false;
// Terminate lines on CR or full buffers, and ignore \n's if the string contents
// are empty (otherwise terminate on \n too!)
if( ( val == '\r' ) || ( g_pbufi == 1023 ) ||
( val == '\n' && g_pbufi != 0 ) )
{
g_pbuf[g_pbufi] = 0;
DevCon::WriteLn( Color_Cyan, g_pbuf );
g_pbufi = 0;
}
else if( val != '\n' )
{
g_pbuf[g_pbufi++] = val;
}
}
PSXHW_LOG( "Hardware Write8 to %s, addr 0x%08x = 0x%02x", _log_GetIopHwName<u8>(addr), addr, psxHu8(addr) );
psxHu8( addr ) = val;
}
void __fastcall iopHwWrite8_Page8( u32 addr, u8 val )
{
// all addresses are assumed to be prefixed with 0x1f808xxx:
jASSUME( (addr >> 12) == 0x1f808 );
if( addr == HW_SIO2_DATAIN ) // sio2 serial data feed input
sio2_serialIn( val );
else
psxHu8( addr ) = val;
PSXHW_LOG( "Hardware Write8 to %s, addr 0x%08x = 0x%02x", _log_GetIopHwName<u8>(addr), addr, psxHu8(addr) );
}
// Template-compatible version of the psxHu macro. Used for writing.
#define psxHu(mem) (*(u32*)&psxH[(mem) & 0xffff])
//////////////////////////////////////////////////////////////////////////////////////////
// Templated handler for both 32 and 16 bit write operations, to Page 1 registers.
//
template< typename T >
static __forceinline void _HwWrite_16or32_Page1( u32 addr, T val )
{
// all addresses are assumed to be prefixed with 0x1f801xxx:
jASSUME( (addr >> 12) == 0x1f801 );
// all addresses should be aligned to the data operand size:
jASSUME(
( sizeof(T) == 2 && (addr & 1) == 0 ) ||
( sizeof(T) == 4 && (addr & 3) == 0 )
);
u32 masked_addr = addr & 0x0fff;
// ------------------------------------------------------------------------
// Counters, 16-bit varieties!
//
if( masked_addr >= 0x100 && masked_addr < 0x130 )
{
int cntidx = ( masked_addr >> 4 ) & 0xf;
switch( masked_addr & 0xf )
{
case 0x0:
psxRcntWcount16( cntidx, val );
break;
case 0x4:
psxRcntWmode16( cntidx, val );
break;
case 0x8:
psxRcntWtarget16( cntidx, val );
break;
default:
psxHu(addr) = val;
break;
}
}
// ------------------------------------------------------------------------
// Counters, 32-bit varieties!
//
else if( masked_addr >= 0x480 && masked_addr < 0x4b0 )
{
int cntidx = (( masked_addr >> 4 ) & 0xf) - 5;
switch( masked_addr & 0xf )
{
case 0x0:
psxRcntWcount32( cntidx, val );
break;
case 0x2: // Count HiWord
psxRcntWcount32( cntidx, (u32)val << 16 );
break;
case 0x4:
psxRcntWmode32( cntidx, val );
break;
case 0x8:
psxRcntWtarget32( cntidx, val );
break;
case 0xa: // Target HiWord
psxRcntWtarget32( cntidx, (u32)val << 16);
break;
default:
psxHu(addr) = val;
break;
}
}
// ------------------------------------------------------------------------
// USB, with both 16 and 32 bit interfaces
//
else if( (masked_addr >= pgmsk(HW_USB_START)) && (masked_addr < pgmsk(HW_USB_END)) )
{
if( sizeof(T) == 2 ) USBwrite16( addr, val ); else USBwrite32( addr, val );
}
// ------------------------------------------------------------------------
// SPU2, accessible in 16 bit mode only!
//
else if( (masked_addr >= pgmsk(HW_SPU2_START)) && (masked_addr < pgmsk(HW_SPU2_END)) )
{
if( sizeof(T) == 2 )
SPU2write( addr, val );
else
{
DevCon::Notice( "*PCSX2* SPU2 Hardware Write32 (addr=0x%08X)? What manner of trickery is this?!", params addr );
//psxHu(addr) = val;
}
}
else
{
switch( masked_addr )
{
// ------------------------------------------------------------------------
mcase(HW_SIO_DATA):
sioWrite8( (u8)val );
sioWrite8( (u8)(val >> 8) );
if( sizeof(T) == 4 )
{
// u32 gets rid of compiler warnings when using the u16 version of this template
sioWrite8( (u8)((u32)val >> 16) );
sioWrite8( (u8)((u32)val >> 24) );
}
break;
mcase(HW_SIO_STAT): // read-only?
//regname = "SIO_STAT (read-only?)";
//sio.StatReg;
break;
mcase(HW_SIO_MODE):
sio.ModeReg = (u16)val;
if( sizeof(T) == 4 )
{
// My guess on 32-bit accesses. Dunno yet what the real hardware does. --air
sio.CtrlReg = (u16)((u32)val >> 16);
}
break;
mcase(HW_SIO_CTRL):
sio.CtrlReg = (u16)val;
break;
mcase(HW_SIO_BAUD):
sio.BaudReg = (u16)val;
break;
// ------------------------------------------------------------------------
//Serial port stuff not support now ;P
// case 0x050: serial_write16( val ); break;
// case 0x054: serial_status_write( val ); break;
// case 0x05a: serial_control_write( val ); break;
// case 0x05e: serial_baud_write( val ); break;
mcase(HW_IREG):
psxHu(addr) &= val;
break;
mcase(HW_IREG+2):
psxHu(addr) &= val;
break;
mcase(HW_IMASK):
psxHu(addr) = val;
iopTestIntc();
break;
mcase(HW_IMASK+2):
psxHu(addr) = val;
iopTestIntc();
break;
mcase(HW_ICTRL):
psxHu(addr) = val;
iopTestIntc();
break;
mcase(HW_ICTRL+2):
psxHu(addr) = val;
iopTestIntc();
break;
// ------------------------------------------------------------------------
// Soon-to-be outdated SPU2 DMA hack (spu2 manages its own DMA MADR currently,
// as asinine as that may seem).
//
mcase(0x1f8010C0):
SPU2WriteMemAddr( 0, val );
HW_DMA4_MADR = val;
break;
mcase(0x1f801500):
SPU2WriteMemAddr( 1, val );
HW_DMA7_MADR = val;
break;
// ------------------------------------------------------------------------
//
/*
mcase(0x1f801088): // DMA0 CHCR -- MDEC IN [ignored]
DmaExec(0);
break;
mcase(0x1f801098): // DMA1 CHCR -- MDEC OUT [ignored]
DmaExec(1);
break;
mcase(0x1f8010a8): // DMA2 CHCR -- GPU [ignored]
DmaExec(2);
break;*/
mcase(0x1f8010b8): // DMA3 CHCR -- CDROM
psxHu(addr) = val;
DmaExec(3);
break;
mcase(0x1f8010c8): // DMA4 CHCR -- SPU2 Core 1
psxHu(addr) = val;
DmaExecNew(4);
break;
mcase(0x1f8010e8): // DMA6 CHCR -- OT clear
psxHu(addr) = val;
DmaExec(6);
break;
mcase(0x1f801508): // DMA7 CHCR -- SPU2 core 2
psxHu(addr) = val;
DmaExecNew2(7);
break;
mcase(0x1f801518): // DMA8 CHCR -- DEV9
psxHu(addr) = val;
DmaExec2(8);
break;
mcase(0x1f801528): // DMA9 CHCR -- SIF0
psxHu(addr) = val;
DmaExec2(9);
break;
mcase(0x1f801538): // DMA10 CHCR -- SIF1
psxHu(addr) = val;
DmaExec2(10);
break;
mcase(0x1f801548): // DMA11 CHCR -- SIO2 IN
psxHu(addr) = val;
DmaExec2(11);
break;
mcase(0x1f801558): // DMA12 CHCR -- SIO2 OUT
psxHu(addr) = val;
DmaExec2(12);
break;
// ------------------------------------------------------------------------
// DMA ICR handlers -- General XOR behavior!
mcase(0x1f8010f4):
{
u32 tmp = (~val) & HW_DMA_ICR;
psxHu(addr) = ((tmp ^ val) & 0xffffff) ^ tmp;
}
break;
mcase(0x1f8010f6): // ICR_hi (16 bit?) [dunno if it ever happens]
{
const u32 val2 = (u32)val << 16;
const u32 tmp = (~val2) & HW_DMA_ICR;
psxHu(addr) = (((tmp ^ val2) & 0xffffff) ^ tmp) >> 16;
}
break;
mcase(0x1f801574):
{
u32 tmp = (~val) & HW_DMA_ICR2;
psxHu(addr) = ((tmp ^ val) & 0xffffff) ^ tmp;
}
break;
mcase(0x1f801576): // ICR2_hi (16 bit?) [dunno if it ever happens]
{
const u32 val2 = (u32)val << 16;
const u32 tmp = (~val2) & HW_DMA_ICR2;
psxHu(addr) = (((tmp ^ val2) & 0xffffff) ^ tmp) >> 16;
}
break;
// ------------------------------------------------------------------------
// Legacy GPU emulation (not needed).
// The IOP emulates the GPU itself through the EE's hardware.
/*case 0x810:
PSXHW_LOG("GPU DATA 32bit write %lx", value);
GPU_writeData(value); return;
case 0x814:
PSXHW_LOG("GPU STATUS 32bit write %lx", value);
GPU_writeStatus(value); return;
case 0x820:
mdecWrite0(value); break;
case 0x824:
mdecWrite1(value); break;*/
// ------------------------------------------------------------------------
mcase(HW_DEV9_DATA):
DEV9write16( addr, val );
psxHu(addr) = val;
break;
default:
psxHu(addr) = val;
break;
}
}
PSXHW_LOG( "Hardware Write%s to %s, addr 0x%08x = 0x%04x",
sizeof(T) == 2 ? "16" : "32", _log_GetIopHwName<T>( addr ), addr, val
);
}
//////////////////////////////////////////////////////////////////////////////////////////
//
void __fastcall iopHwWrite16_Page1( u32 addr, u16 val )
{
_HwWrite_16or32_Page1<u16>( addr, val );
}
void __fastcall iopHwWrite16_Page3( u32 addr, u16 val )
{
// all addresses are assumed to be prefixed with 0x1f803xxx:
jASSUME( (addr >> 12) == 0x1f803 );
psxHu16(addr) = val;
PSXHW_LOG( "Hardware Write16 to %s, addr 0x%08x = 0x%04x", _log_GetIopHwName<u16>( addr ), addr, val );
}
void __fastcall iopHwWrite16_Page8( u32 addr, u16 val )
{
// all addresses are assumed to be prefixed with 0x1f808xxx:
jASSUME( (addr >> 12) == 0x1f808 );
psxHu16(addr) = val;
PSXHW_LOG( "Hardware Write16 to %s, addr 0x%08x = 0x%04x", _log_GetIopHwName<u16>( addr ), addr, val );
}
//////////////////////////////////////////////////////////////////////////////////////////
//
void __fastcall iopHwWrite32_Page1( u32 addr, u32 val )
{
_HwWrite_16or32_Page1<u32>( addr, val );
}
void __fastcall iopHwWrite32_Page3( u32 addr, u32 val )
{
// all addresses are assumed to be prefixed with 0x1f803xxx:
jASSUME( (addr >> 12) == 0x1f803 );
psxHu16(addr) = val;
PSXHW_LOG( "Hardware Write32 to %s, addr 0x%08x = 0x%04x", _log_GetIopHwName<u16>( addr ), addr, val );
}
void __fastcall iopHwWrite32_Page8( u32 addr, u32 val )
{
// all addresses are assumed to be prefixed with 0x1f808xxx:
jASSUME( (addr >> 12) == 0x1f808 );
u32 masked_addr = addr & 0x0fff;
if( masked_addr >= 0x200 )
{
if( masked_addr < 0x240 )
{
const int parm = (masked_addr-0x200) / 4;
sio2_setSend3( parm, val );
}
else if( masked_addr < 0x260 )
{
// SIO2 Send commands alternate registers. First reg maps to Send1, second
// to Send2, third to Send1, etc. And the following clever code does this:
const int parm = (masked_addr-0x240) / 8;
if(masked_addr & 4) sio2_setSend2( parm, val ); else sio2_setSend1( parm, val );
}
else
{
switch( masked_addr )
{
case 0x264: // unknown / reserved.
case 0x26C: // recv1 [read-only]
case 0x270: // recv2 [read-only]
case 0x274: // recv3 [read-only]
psxHu32(addr) = val;
break;
case 0x268:
sio2_setCtrl( val );
break;
case 0x278:
sio2_set8278( val );
break;
case 0x27C:
sio2_set827C( val );
break;
case 0x280:
sio2_setIntr( val );
break;
jNO_DEFAULT;
}
}
}
else psxHu32(addr) = val;
PSXHW_LOG( "Hardware Write32 to %s, addr 0x%08x = 0x%02x", _log_GetIopHwName<u32>( addr ), addr, val );
}
}

View File

@ -0,0 +1,204 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#pragma once
#include "IopCommon.h"
namespace IopMemory {
namespace Internal {
//////////////////////////////////////////////////////////////////////////////////////////
// Masking helper so that I can use the fully qualified address for case statements.
// Switches are based on the bottom 12 bits only, since MSVC tends to optimize switches
// better when it has a limited width operand to work with. :)
//
#define pgmsk( src ) ( (src) & 0x0fff )
#define mcase( src ) case pgmsk(src)
//////////////////////////////////////////////////////////////////////////////////////////
// Helper for debug logging of IOP Registers. Takes an input address and retuns a
// register name.
//
// This list is not yet exhaustive. If you spot something that's missing, feel free to
// fill it in any time. :)
//
template< typename T>
static __forceinline const char* _log_GetIopHwName( u32 addr )
{
switch( addr )
{
// ------------------------------------------------------------------------
// SSBUS -- Two Ess'es?
case HW_SSBUS_SPD_ADDR: return "SSBUS spd_addr";
case HW_SSBUS_PIO_ADDR: return "SSBUS pio_addr";
case HW_SSBUS_SPD_DELAY: return "SSBUS spd_delay";
case HW_SSBUS_DEV1_DELAY: return "SSBUS dev1_delay";
case HW_SSBUS_ROM_DELAY: return "SSBUS rom_delay";
case HW_SSBUS_SPU_DELAY: return "SSBUS spu_delay";
case HW_SSBUS_DEV5_DELAY: return "SSBUS dev5_delay";
case HW_SSBUS_PIO_DELAY: return "SSBUS pio_delay";
case HW_SSBUS_COM_DELAY: return "SSBUS com_delay";
case HW_SSBUS_DEV1_ADDR: return "SSBUS dev1_addr";
case HW_SSBUS_SPU_ADDR: return "SSBUS spu_addr";
case HW_SSBUS_DEV5_ADDR: return "SSBUS dev5_addr";
case HW_SSBUS_SPU1_ADDR: return "SSBUS spu1_addr";
case HW_SSBUS_DEV9_ADDR3: return "SSBUS dev9_addr3";
case HW_SSBUS_SPU1_DELAY: return "SSBUS spu1_delay";
case HW_SSBUS_DEV9_DELAY2: return "SSBUS dev9_delay2";
case HW_SSBUS_DEV9_DELAY3: return "SSBUS dev9_delay3";
case HW_SSBUS_DEV9_DELAY1: return "SSBUS dev9_delay1";
// ------------------------------------------------------------------------
case 0x1f801060:return "RAM_SIZE";
case HW_IREG: return "IREG";
case HW_IREG+2: return "IREG_hi";
case HW_IMASK: return "IMASK";
case HW_IMASK+2:return "IMASK_hi";
case HW_ICTRL: return "ICTRL";
case HW_ICTRL+2:return "ICTRL_hi";
case HW_ICFG: return "ICFG";
case HW_SIO_DATA: return "SIO";
case HW_SIO_STAT: return "SIO STAT";
case HW_SIO_MODE: return ( sizeof(T) == 4 ) ? "SIO_MODE+CTRL" : "SIO MODE";
case HW_SIO_CTRL: return "SIO CTRL";
case HW_SIO_BAUD: return "SIO BAUD";
case 0x1f8014c0: return "RTC_HOLDMODE";
case HW_DEV9_DATA: return "DEV9_R_REV/DATA";
// ------------------------------------------------------------------------
// BCR_LABEL -- Selects label for BCR depending on operand size (BCR has hi
// and low values of count and size, respectively)
#define BCR_LABEL( dma ) (sizeof(T)==4) ? dma" BCR" : dma" BCR_size";
case 0x1f8010a0: return "DMA2 MADR";
case 0x1f8010a4: return BCR_LABEL( "DMA2" );
case 0x1f8010a6: return "DMA2 BCR_count";
case 0x1f8010a8: return "DMA2 CHCR";
case 0x1f8010ac: return "DMA2 TADR";
case 0x1f8010b0: return "DMA3 MADR";
case 0x1f8010b4: return BCR_LABEL( "DMA3" );
case 0x1f8010b6: return "DMA3 BCR_count";
case 0x1f8010b8: return "DMA3 CHCR";
case 0x1f8010bc: return "DMA3 TADR";
case 0x1f8010c0: return "[SPU]DMA4 MADR";
case 0x1f8010c4: return BCR_LABEL( "DMA4" );
case 0x1f8010c6: return "[SPU]DMA4 BCR_count";
case 0x1f8010c8: return "[SPU]DMA4 CHCR";
case 0x1f8010cc: return "[SPU]DMA4 TADR";
case 0x1f8010f0: return "DMA PCR";
case 0x1f8010f4: return "DMA ICR";
case 0x1f8010f6: return "DMA ICR_hi";
case 0x1f801500: return "[SPU2]DMA7 MADR";
case 0x1f801504: return BCR_LABEL( "DMA7" );
case 0x1f801506: return "[SPU2]DMA7 BCR_count";
case 0x1f801508: return "[SPU2]DMA7 CHCR";
case 0x1f80150C: return "[SPU2]DMA7 TADR";
case 0x1f801520: return "DMA9 MADR";
case 0x1f801524: return BCR_LABEL( "DMA9" );
case 0x1f801526: return "DMA9 BCR_count";
case 0x1f801528: return "DMA9 CHCR";
case 0x1f80152C: return "DMA9 TADR";
case 0x1f801530: return "DMA10 MADR";
case 0x1f801534: return BCR_LABEL( "DMA10" );
case 0x1f801536: return "DMA10 BCR_count";
case 0x1f801538: return "DMA10 CHCR";
case 0x1f80153c: return "DMA10 TADR";
case 0x1f801570: return "DMA PCR2";
case 0x1f801574: return "DMA ICR2";
case 0x1f801576: return "DMA ICR2_hi";
case HW_CDR_DATA0: return "CDROM DATA0";
case HW_CDR_DATA1: return "CDROM DATA1";
case HW_CDR_DATA2: return "CDROM DATA2";
case HW_CDR_DATA3: return "CDROM DATA3";
case 0x1f80380c: return "STDOUT";
// ------------------------------------------------------------------------
case HW_SIO2_FIFO: return "SIO2 FIFO";
case HW_SIO2_CTRL: return "SIO2 CTRL";
case HW_SIO2_RECV1: return "SIO2 RECV1";
case HW_SIO2_RECV2: return "SIO2 RECV2";
case HW_SIO2_RECV3: return "SIO2 RECV3";
case HW_SIO2_INTR: return "SIO2 INTR";
case 0x1f808278: return "SIO2 8278";
case 0x1f80827C: return "SIO2 827C";
// ------------------------------------------------------------------------
// Check for "zoned" registers in the default case.
// And if all that fails, return "unknown"! :)
default:
if( addr >= 0x1f801100 && addr < 0x1f801130 )
{
switch( addr & 0xf )
{
case 0x0: return "CNT16_COUNT";
case 0x4: return "CNT16_MODE";
case 0x8: return "CNT16_TARGET";
default: return "Invalid Counter";
}
}
else if( addr >= 0x1f801480 && addr < 0x1f8014b0 )
{
switch( addr & 0xf )
{
case 0x0: return "CNT32_COUNT";
case 0x2: return "CNT32_COUNT_hi";
case 0x4: return "CNT32_MODE";
case 0x8: return "CNT32_TARGET";
case 0xa: return "CNT32_TARGET_hi";
default: return "Invalid Counter";
}
}
else if( (addr >= HW_USB_START) && (addr < HW_USB_END) )
{
return "USB";
}
else if( (addr >= HW_SPU2_START) && (addr < HW_SPU2_END) )
{
return "SPU2";
}
else if( addr >= 0x1f808200 )
{
if( addr < 0x1f808240 )
return "SIO2 param";
else if( addr < 0x260 )
return "SIO2 send";
}
return "Unknown";
}
}
} };

File diff suppressed because it is too large Load Diff