mirror of https://github.com/PCSX2/pcsx2.git
*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:
parent
b560f325ae
commit
56545f0b7d
|
@ -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__ */
|
|
@ -479,7 +479,9 @@ void psxRcntUpdate()
|
|||
for (i=0; i<6; i++) _rcntSet( i );
|
||||
}
|
||||
|
||||
void psxRcntWcount16(int index, u32 value)
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void psxRcntWcount16(int index, u16 value)
|
||||
{
|
||||
u32 change;
|
||||
|
||||
|
@ -500,6 +502,8 @@ void psxRcntWcount16(int index, u32 value)
|
|||
_rcntSet( index );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void psxRcntWcount32(int index, u32 value)
|
||||
{
|
||||
u32 change;
|
||||
|
@ -521,159 +525,119 @@ void psxRcntWcount32(int index, u32 value)
|
|||
_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;
|
||||
psxCounters[0].mode|= 0x0400;
|
||||
psxCounters[0].rate = 1;
|
||||
jASSUME( index >= 0 && index < 3 );
|
||||
psxCounter& counter = psxCounters[index];
|
||||
|
||||
if(value & IOPCNT_ALT_SOURCE)
|
||||
psxCounters[0].rate = PSXPIXEL;
|
||||
|
||||
if(psxCounters[0].mode & IOPCNT_ENABLE_GATE)
|
||||
counter.mode = value;
|
||||
counter.mode |= 0x0400;
|
||||
|
||||
if( index == 2 )
|
||||
{
|
||||
// gated counters are added up as per the h/vblank timers.
|
||||
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;
|
||||
switch(value & 0x200)
|
||||
{
|
||||
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)
|
||||
{
|
||||
//Console::WriteLn("Gate set on IOP C2, disabling");
|
||||
psxCounters[2].mode |= IOPCNT_STOPPED;
|
||||
}
|
||||
|
||||
psxCounters[2].count = 0;
|
||||
psxCounters[2].sCycleT = psxRegs.cycle;
|
||||
psxCounters[2].target &= 0xffff;
|
||||
_rcntSet( 2 );
|
||||
counter.count = 0;
|
||||
counter.sCycleT = psxRegs.cycle;
|
||||
counter.target &= 0xffff;
|
||||
|
||||
_rcntSet( index );
|
||||
}
|
||||
|
||||
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;
|
||||
psxCounters[3].rate = 1;
|
||||
psxCounters[3].mode|= 0x0400;
|
||||
jASSUME( index >= 3 && index < 6 );
|
||||
psxCounter& counter = psxCounters[index];
|
||||
|
||||
if(value & IOPCNT_ALT_SOURCE)
|
||||
psxCounters[3].rate = PSXHBLANK;
|
||||
|
||||
if(psxCounters[3].mode & IOPCNT_ENABLE_GATE)
|
||||
counter.mode = value;
|
||||
counter.mode |= 0x0400;
|
||||
|
||||
if( index == 3 )
|
||||
{
|
||||
PSXCNT_LOG("IOP Counter[3] Gate Check set, value = %x", value);
|
||||
psxvblankgate |= 1<<3;
|
||||
}
|
||||
else psxvblankgate &= ~(1<<3);
|
||||
// Counter 3 has the HBlank as an alternate source.
|
||||
counter.rate = 1;
|
||||
if(value & IOPCNT_ALT_SOURCE)
|
||||
counter.rate = PSXHBLANK;
|
||||
|
||||
psxCounters[3].count = 0;
|
||||
psxCounters[3].sCycleT = psxRegs.cycle;
|
||||
psxCounters[3].target &= 0xffffffff;
|
||||
_rcntSet( 3 );
|
||||
}
|
||||
|
||||
void psxRcnt4Wmode(u32 value)
|
||||
{
|
||||
PSXCNT_LOG("IOP Counter[4] writeMode = %lx", value);
|
||||
|
||||
psxCounters[4].mode = value;
|
||||
psxCounters[4].mode|= 0x0400;
|
||||
|
||||
switch(value & 0x6000)
|
||||
{
|
||||
case 0x0000: psxCounters[4].rate = 1; break;
|
||||
case 0x2000: psxCounters[4].rate = 8; break;
|
||||
case 0x4000: psxCounters[4].rate = 16; break;
|
||||
case 0x6000: psxCounters[4].rate = 256; break;
|
||||
}
|
||||
// Need to set a rate and target
|
||||
if((psxCounters[4].mode & 0x7) == 0x7 || (psxCounters[4].mode & 0x7) == 0x1)
|
||||
{
|
||||
Console::WriteLn("Gate set on IOP C4, disabling");
|
||||
psxCounters[4].mode |= IOPCNT_STOPPED;
|
||||
}
|
||||
|
||||
psxCounters[4].count = 0;
|
||||
psxCounters[4].sCycleT = psxRegs.cycle;
|
||||
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 );
|
||||
if(counter.mode & IOPCNT_ENABLE_GATE)
|
||||
{
|
||||
PSXCNT_LOG("IOP Counter[3] Gate Check set, value = %x", value);
|
||||
psxvblankgate |= 1<<3;
|
||||
}
|
||||
else psxvblankgate &= ~(1<<3);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(value & 0x6000)
|
||||
{
|
||||
case 0x0000: counter.rate = 1; break;
|
||||
case 0x2000: counter.rate = 8; break;
|
||||
case 0x4000: counter.rate = 16; break;
|
||||
case 0x6000: counter.rate = 256; break;
|
||||
}
|
||||
|
||||
// Need to set a rate and target
|
||||
if((counter.mode & 0x7) == 0x7 || (counter.mode & 0x7) == 0x1)
|
||||
{
|
||||
Console::WriteLn( "Gate set on IOP Counter %d, disabling", params index );
|
||||
counter.mode |= IOPCNT_STOPPED;
|
||||
}
|
||||
}
|
||||
|
||||
counter.count = 0;
|
||||
counter.sCycleT = psxRegs.cycle;
|
||||
counter.target &= 0xffffffff;
|
||||
_rcntSet( index );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void psxRcntWtarget16(int index, u32 value)
|
||||
{
|
||||
assert( index < 3 );
|
||||
|
|
|
@ -34,30 +34,24 @@ struct psxCounter {
|
|||
#endif
|
||||
|
||||
extern psxCounter psxCounters[NUM_COUNTERS];
|
||||
extern s32 psxNextCounter;
|
||||
extern u32 psxNextsCounter;
|
||||
|
||||
void psxRcntInit();
|
||||
void psxRcntUpdate();
|
||||
void cntspu2async();
|
||||
void psxRcntWcount16(int index, u32 value);
|
||||
void psxRcntWcount32(int index, u32 value);
|
||||
void psxRcnt0Wmode(u32 value);
|
||||
void psxRcnt1Wmode(u32 value);
|
||||
void psxRcnt2Wmode(u32 value);
|
||||
void psxRcnt3Wmode(u32 value);
|
||||
void psxRcnt4Wmode(u32 value);
|
||||
void psxRcnt5Wmode(u32 value);
|
||||
void psxRcntWtarget16(int index, u32 value);
|
||||
void psxRcntWtarget32(int index, u32 value);
|
||||
u16 psxRcntRcount16(int index);
|
||||
u32 psxRcntRcount32(int index);
|
||||
u64 psxRcntCycles(int index);
|
||||
extern void psxRcntInit();
|
||||
extern void psxRcntUpdate();
|
||||
extern void cntspu2async();
|
||||
extern void psxRcntWcount16(int index, u16 value);
|
||||
extern void psxRcntWcount32(int index, u32 value);
|
||||
extern void psxRcntWmode16(int index, u32 value);
|
||||
extern void psxRcntWmode32(int index, u32 value);
|
||||
extern void psxRcntWtarget16(int index, u32 value);
|
||||
extern void psxRcntWtarget32(int index, u32 value);
|
||||
extern u16 psxRcntRcount16(int index);
|
||||
extern u32 psxRcntRcount32(int index);
|
||||
extern u64 psxRcntCycles(int index);
|
||||
|
||||
void psxVBlankStart();
|
||||
void psxVBlankEnd();
|
||||
void psxCheckStartGate16(int i);
|
||||
void psxCheckEndGate16(int i);
|
||||
extern void psxVBlankStart();
|
||||
extern void psxVBlankEnd();
|
||||
extern void psxCheckStartGate16(int i);
|
||||
extern void psxCheckEndGate16(int i);
|
||||
//static void psxCheckStartGate32(int i);
|
||||
//static void psxCheckEndGate32(int i);
|
||||
|
||||
|
|
|
@ -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.
|
||||
s8 g_pbuf[1024];
|
||||
int g_pbufi;
|
||||
static s8 g_pbuf[1024];
|
||||
static int g_pbufi;
|
||||
void psxHwWrite8(u32 add, u8 value) {
|
||||
if (add >= HW_USB_START && add < HW_USB_END) {
|
||||
USBwrite8(add, value); return;
|
||||
|
@ -768,7 +768,7 @@ void psxHwWrite16(u32 add, u16 value) {
|
|||
psxRcntWcount16(0, value); return;
|
||||
case IOP_T0_MODE:
|
||||
PSXCNT_LOG("COUNTER 0 MODE 16bit write %x", value);
|
||||
psxRcnt0Wmode(value); return;
|
||||
psxRcntWmode16(0, value); return;
|
||||
case IOP_T0_TARGET:
|
||||
PSXCNT_LOG("COUNTER 0 TARGET 16bit write %x", value);
|
||||
psxRcntWtarget16(0, value); return;
|
||||
|
@ -778,7 +778,7 @@ void psxHwWrite16(u32 add, u16 value) {
|
|||
psxRcntWcount16(1, value); return;
|
||||
case IOP_T1_MODE:
|
||||
PSXCNT_LOG("COUNTER 1 MODE 16bit write %x", value);
|
||||
psxRcnt1Wmode(value); return;
|
||||
psxRcntWmode16(1, value); return;
|
||||
case IOP_T1_TARGET:
|
||||
PSXCNT_LOG("COUNTER 1 TARGET 16bit write %x", value);
|
||||
psxRcntWtarget16(1, value); return;
|
||||
|
@ -788,7 +788,7 @@ void psxHwWrite16(u32 add, u16 value) {
|
|||
psxRcntWcount16(2, value); return;
|
||||
case IOP_T2_MODE:
|
||||
PSXCNT_LOG("COUNTER 2 MODE 16bit write %x", value);
|
||||
psxRcnt2Wmode(value); return;
|
||||
psxRcntWmode16(2, value); return;
|
||||
case IOP_T2_TARGET:
|
||||
PSXCNT_LOG("COUNTER 2 TARGET 16bit write %x", value);
|
||||
psxRcntWtarget16(2, value); return;
|
||||
|
@ -803,7 +803,7 @@ void psxHwWrite16(u32 add, u16 value) {
|
|||
psxRcntWcount32(3, value); return;
|
||||
case IOP_T3_MODE:
|
||||
PSXCNT_LOG("COUNTER 3 MODE 16bit write %lx", value);
|
||||
psxRcnt3Wmode(value); return;
|
||||
psxRcntWmode32(3, value); return;
|
||||
case IOP_T3_TARGET:
|
||||
PSXCNT_LOG("COUNTER 3 TARGET 16bit write %lx", value);
|
||||
psxRcntWtarget32(3, value); return;
|
||||
|
@ -813,7 +813,7 @@ void psxHwWrite16(u32 add, u16 value) {
|
|||
psxRcntWcount32(4, value); return;
|
||||
case IOP_T4_MODE:
|
||||
PSXCNT_LOG("COUNTER 4 MODE 16bit write %lx", value);
|
||||
psxRcnt4Wmode(value); return;
|
||||
psxRcntWmode32(4, value); return;
|
||||
case IOP_T4_TARGET:
|
||||
PSXCNT_LOG("COUNTER 4 TARGET 16bit write %lx", value);
|
||||
psxRcntWtarget32(4, value); return;
|
||||
|
@ -823,7 +823,7 @@ void psxHwWrite16(u32 add, u16 value) {
|
|||
psxRcntWcount32(5, value); return;
|
||||
case IOP_T5_MODE:
|
||||
PSXCNT_LOG("COUNTER 5 MODE 16bit write %lx", value);
|
||||
psxRcnt5Wmode(value); return;
|
||||
psxRcntWmode32(5, value); return;
|
||||
case IOP_T5_TARGET:
|
||||
PSXCNT_LOG("COUNTER 5 TARGET 16bit write %lx", value);
|
||||
psxRcntWtarget32(5, value); return;
|
||||
|
@ -1180,7 +1180,7 @@ void psxHwWrite32(u32 add, u32 value) {
|
|||
psxRcntWcount16(0, value ); return;
|
||||
case IOP_T0_MODE:
|
||||
PSXCNT_LOG("COUNTER 0 MODE 32bit write %lx", value);
|
||||
psxRcnt0Wmode(value); return;
|
||||
psxRcntWmode16(0, value); return;
|
||||
case IOP_T0_TARGET:
|
||||
PSXCNT_LOG("COUNTER 0 TARGET 32bit write %lx", value);
|
||||
psxRcntWtarget16(0, value ); return;
|
||||
|
@ -1190,7 +1190,7 @@ void psxHwWrite32(u32 add, u32 value) {
|
|||
psxRcntWcount16(1, value ); return;
|
||||
case IOP_T1_MODE:
|
||||
PSXCNT_LOG("COUNTER 1 MODE 32bit write %lx", value);
|
||||
psxRcnt1Wmode(value); return;
|
||||
psxRcntWmode16(1, value); return;
|
||||
case IOP_T1_TARGET:
|
||||
PSXCNT_LOG("COUNTER 1 TARGET 32bit write %lx", value);
|
||||
psxRcntWtarget16(1, value ); return;
|
||||
|
@ -1200,7 +1200,7 @@ void psxHwWrite32(u32 add, u32 value) {
|
|||
psxRcntWcount16(2, value ); return;
|
||||
case IOP_T2_MODE:
|
||||
PSXCNT_LOG("COUNTER 2 MODE 32bit write %lx", value);
|
||||
psxRcnt2Wmode(value); return;
|
||||
psxRcntWmode16(0, value); return;
|
||||
case IOP_T2_TARGET:
|
||||
PSXCNT_LOG("COUNTER 2 TARGET 32bit write %lx", value);
|
||||
psxRcntWtarget16(2, value); return;
|
||||
|
@ -1210,7 +1210,7 @@ void psxHwWrite32(u32 add, u32 value) {
|
|||
psxRcntWcount32(3, value); return;
|
||||
case IOP_T3_MODE:
|
||||
PSXCNT_LOG("COUNTER 3 MODE 32bit write %lx", value);
|
||||
psxRcnt3Wmode(value); return;
|
||||
psxRcntWmode32(3, value); return;
|
||||
case IOP_T3_TARGET:
|
||||
PSXCNT_LOG("COUNTER 3 TARGET 32bit write %lx", value);
|
||||
psxRcntWtarget32(3, value); return;
|
||||
|
@ -1220,7 +1220,7 @@ void psxHwWrite32(u32 add, u32 value) {
|
|||
psxRcntWcount32(4, value); return;
|
||||
case IOP_T4_MODE:
|
||||
PSXCNT_LOG("COUNTER 4 MODE 32bit write %lx", value);
|
||||
psxRcnt4Wmode(value); return;
|
||||
psxRcntWmode32(4, value); return;
|
||||
case IOP_T4_TARGET:
|
||||
PSXCNT_LOG("COUNTER 4 TARGET 32bit write %lx", value);
|
||||
psxRcntWtarget32(4, value); return;
|
||||
|
@ -1230,7 +1230,7 @@ void psxHwWrite32(u32 add, u32 value) {
|
|||
psxRcntWcount32(5, value); return;
|
||||
case IOP_T5_MODE:
|
||||
PSXCNT_LOG("COUNTER 5 MODE 32bit write %lx", value);
|
||||
psxRcnt5Wmode(value); return;
|
||||
psxRcntWmode32(5, value); return;
|
||||
case IOP_T5_TARGET:
|
||||
PSXCNT_LOG("COUNTER 5 TARGET 32bit write %lx", value);
|
||||
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);
|
||||
}
|
||||
|
||||
void psxDmaInterrupt(int n) {
|
||||
if (HW_DMA_ICR & (1 << (16 + n))) {
|
||||
void psxDmaInterrupt(int n)
|
||||
{
|
||||
if (HW_DMA_ICR & (1 << (16 + n)))
|
||||
{
|
||||
HW_DMA_ICR|= (1 << (24 + n));
|
||||
psxRegs.CP0.n.Cause |= 1 << (9 + n);
|
||||
iopIntcIrq( 3 );
|
||||
}
|
||||
}
|
||||
|
||||
void psxDmaInterrupt2(int n) {
|
||||
if (HW_DMA_ICR2 & (1 << (16 + n))) {
|
||||
void psxDmaInterrupt2(int n)
|
||||
{
|
||||
if (HW_DMA_ICR2 & (1 << (16 + n)))
|
||||
{
|
||||
/* if (HW_DMA_ICR2 & (1 << (24 + n))) {
|
||||
Console::WriteLn("*PCSX2*: HW_DMA_ICR2 n=%d already set", params n);
|
||||
}
|
||||
|
|
|
@ -16,18 +16,69 @@
|
|||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef __PSXHW_H__
|
||||
#define __PSXHW_H__
|
||||
#pragma once
|
||||
|
||||
#include "R3000A.h"
|
||||
#include "IopMem.h"
|
||||
|
||||
#define HW_USB_START 0x1f801600
|
||||
#define HW_USB_END 0x1f801700
|
||||
#define HW_FW_START 0x1f808400
|
||||
#define HW_FW_END 0x1f808550
|
||||
#define HW_SPU2_START 0x1f801c00
|
||||
#define HW_SPU2_END 0x1f801e00
|
||||
static const u32
|
||||
HW_USB_START = 0x1f801600,
|
||||
HW_USB_END = 0x1f801700,
|
||||
HW_FW_START = 0x1f808400,
|
||||
HW_FW_END = 0x1f808550, // end addr for FW is a guess...
|
||||
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 */
|
||||
enum IOPCountRegs
|
||||
|
@ -37,7 +88,7 @@ enum IOPCountRegs
|
|||
IOP_T2_COUNT = 0x1f801120,
|
||||
IOP_T3_COUNT = 0x1f801480,
|
||||
IOP_T4_COUNT = 0x1f801490,
|
||||
IOP_T5_COUNT = 0x1f8014a0,
|
||||
IOP_T5_COUNT = 0x1f8014a0,
|
||||
|
||||
IOP_T0_MODE = 0x1f801104,
|
||||
IOP_T1_MODE = 0x1f801114,
|
||||
|
@ -46,7 +97,7 @@ enum IOPCountRegs
|
|||
IOP_T4_MODE = 0x1f801494,
|
||||
IOP_T5_MODE = 0x1f8014a4,
|
||||
|
||||
IOP_T0_TARGET= 0x1f801108,
|
||||
IOP_T0_TARGET = 0x1f801108,
|
||||
IOP_T1_TARGET = 0x1f801118,
|
||||
IOP_T2_TARGET = 0x1f801128,
|
||||
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 psxSetNextBranchDelta( s32 delta );
|
||||
extern int iopTestCycle( u32 startCycle, s32 delta );
|
||||
extern void _iopTestInterrupts();
|
||||
|
||||
void psxHwReset();
|
||||
u8 psxHwRead8 (u32 add);
|
||||
|
@ -192,5 +245,3 @@ void psxHwConstWrite16(u32 add, int mmreg);
|
|||
void psxHwConstWrite32(u32 add, int mmreg);
|
||||
int psxHw4ConstRead8 (u32 x86reg, u32 add, u32 sign);
|
||||
void psxHw4ConstWrite8(u32 add, int mmreg);
|
||||
|
||||
#endif /* __PSXHW_H__ */
|
||||
|
|
152
pcsx2/IopMem.cpp
152
pcsx2/IopMem.cpp
|
@ -72,13 +72,9 @@ void psxMemReset()
|
|||
for (int i=0; i<0x0080; i++)
|
||||
{
|
||||
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.
|
||||
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.
|
||||
|
@ -94,25 +90,17 @@ void psxMemReset()
|
|||
for (int i=0; i<0x0040; i++)
|
||||
{
|
||||
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++)
|
||||
{
|
||||
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))
|
||||
psxMemWLUT[0x2000 + 0x1d00] = (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,
|
||||
// but leaving it in for reference (air)
|
||||
//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 (mem < 0x1f801000)
|
||||
return psxHu8(mem);
|
||||
else
|
||||
return psxHwRead8(mem);
|
||||
switch( mem & 0xf000 )
|
||||
{
|
||||
case 0x1000: return IopMemory::iopHwRead8_Page1(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)
|
||||
{
|
||||
|
@ -169,10 +168,21 @@ u16 iopMemRead16(u32 mem)
|
|||
|
||||
if (t == 0x1f80)
|
||||
{
|
||||
if (mem < 0x1f801000)
|
||||
return psxHu16(mem);
|
||||
else
|
||||
return psxHwRead16(mem);
|
||||
switch( mem & 0xf000 )
|
||||
{
|
||||
case 0x1000: return IopMemory::iopHwRead16_Page1(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
|
||||
{
|
||||
|
@ -224,10 +234,21 @@ u32 iopMemRead32(u32 mem)
|
|||
|
||||
if (t == 0x1f80)
|
||||
{
|
||||
if (mem < 0x1f801000)
|
||||
return psxHu32(mem);
|
||||
else
|
||||
return psxHwRead32(mem);
|
||||
switch( mem & 0xf000 )
|
||||
{
|
||||
case 0x1000: return IopMemory::iopHwRead32_Page1(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
|
||||
{
|
||||
//see also Hw.c
|
||||
|
@ -282,10 +303,31 @@ void iopMemWrite8(u32 mem, u8 value)
|
|||
|
||||
if (t == 0x1f80)
|
||||
{
|
||||
if (mem < 0x1f801000)
|
||||
psxHu8(mem) = value;
|
||||
else
|
||||
psxHwWrite8(mem, value);
|
||||
switch( mem & 0xf000 )
|
||||
{
|
||||
// Regression testing: selectively pass ranges of registers to new or old
|
||||
// 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)
|
||||
{
|
||||
|
@ -323,10 +365,29 @@ void iopMemWrite16(u32 mem, u16 value)
|
|||
|
||||
if (t == 0x1f80)
|
||||
{
|
||||
if (mem < 0x1f801000)
|
||||
psxHu16(mem) = value;
|
||||
else
|
||||
psxHwWrite16(mem, value);
|
||||
switch( mem & 0xf000 )
|
||||
{
|
||||
// Regression testing: selectively pass ranges of registers to new or old
|
||||
// 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
|
||||
{
|
||||
u8* p = (u8 *)(psxMemWLUT[mem >> 16]);
|
||||
|
@ -386,10 +447,29 @@ void iopMemWrite32(u32 mem, u32 value)
|
|||
|
||||
if (t == 0x1f80)
|
||||
{
|
||||
if (mem < 0x1f801000)
|
||||
psxHu32(mem) = value;
|
||||
else
|
||||
psxHwWrite32(mem, value);
|
||||
switch( mem & 0xf000 )
|
||||
{
|
||||
// Regression testing: selectively pass ranges of registers to new or old
|
||||
// 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
|
||||
{
|
||||
//see also Hw.c
|
||||
|
|
|
@ -16,8 +16,7 @@
|
|||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef __PSXMEMORY_H__
|
||||
#define __PSXMEMORY_H__
|
||||
#pragma once
|
||||
|
||||
extern u8 *psxM;
|
||||
extern u8 *psxP;
|
||||
|
@ -90,21 +89,40 @@ void iopMemWrite32(u32 mem, u32 value);
|
|||
|
||||
// x86reg and mmreg are always x86 regs
|
||||
void psxRecMemRead8();
|
||||
int psxRecMemConstRead8(u32 x86reg, u32 mem, u32 sign);
|
||||
|
||||
void psxRecMemRead16();
|
||||
int psxRecMemConstRead16(u32 x86reg, u32 mem, u32 sign);
|
||||
|
||||
void psxRecMemRead32();
|
||||
int psxRecMemConstRead32(u32 x86reg, u32 mem);
|
||||
|
||||
void psxRecMemWrite8();
|
||||
int psxRecMemConstWrite8(u32 mem, int mmreg);
|
||||
|
||||
void psxRecMemWrite16();
|
||||
int psxRecMemConstWrite16(u32 mem, int mmreg);
|
||||
|
||||
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 );
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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 );
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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
Loading…
Reference in New Issue