mirror of https://github.com/PCSX2/pcsx2.git
More changes to the IOP's memory model. Some of these are experimental and might cause problems (needs testing). Quick rundown:
* The R3000 does not have a TLB, and has no valid addresses mapped above page 0x2000 in physical memory [lower 512M]. Thus all addresses can have the top 6 bits masked off and still retain full validity. For example, address 0xbfc0 is simply a mirror of physical address 0x1fc0. Technically speaking, a full emulation of the IOP memory model would raise bus error exceptions for accesses between 0x2000 to 0x8000 segments (instead of treating them as mirrors of the lower 0x2000 segment), but buss errors are generally fatal (unrecoverable) program errors that would never happen within the context of game emulation. * The IOP's SIF register space is only 256 bytes, and then mirrored repeatedly through it's 64k page at 0x1d00. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@814 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
f2477537f9
commit
a51b407cdb
560
pcsx2/IopMem.cpp
560
pcsx2/IopMem.cpp
|
@ -24,309 +24,10 @@
|
||||||
#include "Hw.h"
|
#include "Hw.h"
|
||||||
#include "iR3000A.h"
|
#include "iR3000A.h"
|
||||||
|
|
||||||
#ifdef PCSX2_VIRTUAL_MEM
|
|
||||||
void psxMemAlloc()
|
|
||||||
{
|
|
||||||
// In VirtualMemory land all mem taken care by memAlloc
|
|
||||||
}
|
|
||||||
|
|
||||||
void psxMemReset()
|
|
||||||
{
|
|
||||||
memzero_ptr<Ps2MemSize::IopRam>(psxM);
|
|
||||||
}
|
|
||||||
|
|
||||||
void psxMemShutdown()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 iopMemRead8(u32 mem)
|
|
||||||
{
|
|
||||||
u32 t = (mem >> 16) & 0x1fff;
|
|
||||||
|
|
||||||
switch(t) {
|
|
||||||
case 0x1f80:
|
|
||||||
mem&= 0x1fffffff;
|
|
||||||
if (mem < 0x1f801000)
|
|
||||||
return psxHu8(mem);
|
|
||||||
else
|
|
||||||
return psxHwRead8(mem);
|
|
||||||
break;
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
|
||||||
case 0x1d00: assert(0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
case 0x1f40:
|
|
||||||
mem &= 0x1fffffff;
|
|
||||||
return psxHw4Read8(mem);
|
|
||||||
|
|
||||||
case 0x1000: return DEV9read8(mem & 0x1FFFFFFF);
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert( g_psxWriteOk );
|
|
||||||
return *(u8*)PSXM(mem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
u16 iopMemRead16(u32 mem)
|
|
||||||
{
|
|
||||||
u32 t = (mem >> 16) & 0x1fff;
|
|
||||||
|
|
||||||
switch(t) {
|
|
||||||
case 0x1f80:
|
|
||||||
mem&= 0x1fffffff;
|
|
||||||
if (mem < 0x1f801000)
|
|
||||||
return psxHu16(mem);
|
|
||||||
else
|
|
||||||
return psxHwRead16(mem);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x1d00:
|
|
||||||
SIF_LOG("Sif reg read %x value %x\n", mem, psxHu16(mem));
|
|
||||||
switch(mem & 0xF0)
|
|
||||||
{
|
|
||||||
case 0x40: return psHu16(0x1000F240) | 0x0002;
|
|
||||||
case 0x60: return 0;
|
|
||||||
default: return *(u16*)(PS2MEM_HW+0xf200+(mem&0xf0));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x1f90:
|
|
||||||
return SPU2read(mem & 0x1FFFFFFF);
|
|
||||||
case 0x1000:
|
|
||||||
return DEV9read16(mem & 0x1FFFFFFF);
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert( g_psxWriteOk );
|
|
||||||
return *(u16*)PSXM(mem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 iopMemRead32(u32 mem)
|
|
||||||
{
|
|
||||||
u32 t = (mem >> 16) & 0x1fff;
|
|
||||||
|
|
||||||
switch(t) {
|
|
||||||
case 0x1f80:
|
|
||||||
mem&= 0x1fffffff;
|
|
||||||
if (mem < 0x1f801000)
|
|
||||||
return psxHu32(mem);
|
|
||||||
else
|
|
||||||
return psxHwRead32(mem);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x1d00:
|
|
||||||
SIF_LOG("Sif reg read %x value %x\n", mem, psxHu32(mem));
|
|
||||||
switch(mem & 0xF0)
|
|
||||||
{
|
|
||||||
case 0x40: return psHu32(0x1000F240) | 0xF0000002;
|
|
||||||
case 0x60: return 0;
|
|
||||||
default: return *(u32*)(PS2MEM_HW+0xf200+(mem&0xf0));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x1fff: return g_psxWriteOk;
|
|
||||||
case 0x1000:
|
|
||||||
return DEV9read32(mem & 0x1FFFFFFF);
|
|
||||||
|
|
||||||
default:
|
|
||||||
//assert(g_psxWriteOk);
|
|
||||||
if( mem == 0xfffe0130 )
|
|
||||||
return writectrl;
|
|
||||||
else if( mem == 0xffffffff )
|
|
||||||
return writectrl;
|
|
||||||
else if( g_psxWriteOk )
|
|
||||||
return *(u32*)PSXM(mem);
|
|
||||||
else return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void iopMemWrite8(u32 mem, u8 value)
|
|
||||||
{
|
|
||||||
u32 t = (mem >> 16) & 0x1fff;
|
|
||||||
|
|
||||||
switch(t) {
|
|
||||||
case 0x1f80:
|
|
||||||
mem&= 0x1fffffff;
|
|
||||||
if (mem < 0x1f801000)
|
|
||||||
psxHu8(mem) = value;
|
|
||||||
else
|
|
||||||
psxHwWrite8(mem, value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x1f40:
|
|
||||||
mem&= 0x1fffffff;
|
|
||||||
psxHw4Write8(mem, value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x1d00:
|
|
||||||
SysPrintf("sw8 [0x%08X]=0x%08X\n", mem, value);
|
|
||||||
*(u8*)(PS2MEM_HW+0xf200+(mem&0xff)) = value;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x1000:
|
|
||||||
DEV9write8(mem & 0x1fffffff, value);
|
|
||||||
return;
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert(g_psxWriteOk);
|
|
||||||
*(u8 *)PSXM(mem) = value;
|
|
||||||
psxCpu->Clear(mem&~3, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void iopMemWrite16(u32 mem, u16 value)
|
|
||||||
{
|
|
||||||
u32 t = (mem >> 16) & 0x1fff;
|
|
||||||
switch(t) {
|
|
||||||
case 0x1600:
|
|
||||||
//HACK: DEV9 VM crash fix
|
|
||||||
break;
|
|
||||||
case 0x1f80:
|
|
||||||
mem&= 0x1fffffff;
|
|
||||||
if (mem < 0x1f801000)
|
|
||||||
psxHu16(mem) = value;
|
|
||||||
else
|
|
||||||
psxHwWrite16(mem, value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x1d00:
|
|
||||||
switch (mem & 0xf0) {
|
|
||||||
case 0x10:
|
|
||||||
// write to ps2 mem
|
|
||||||
psHu16(0x1000F210) = value;
|
|
||||||
return;
|
|
||||||
case 0x40:
|
|
||||||
{
|
|
||||||
u32 temp = value & 0xF0;
|
|
||||||
// write to ps2 mem
|
|
||||||
if(value & 0x20 || value & 0x80)
|
|
||||||
{
|
|
||||||
psHu16(0x1000F240) &= ~0xF000;
|
|
||||||
psHu16(0x1000F240) |= 0x2000;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(psHu16(0x1000F240) & temp) psHu16(0x1000F240) &= ~temp;
|
|
||||||
else psHu16(0x1000F240) |= temp;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case 0x60:
|
|
||||||
psHu32(0x1000F260) = 0;
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
|
|
||||||
case 0x1f90:
|
|
||||||
SPU2write(mem & 0x1FFFFFFF, value); return;
|
|
||||||
|
|
||||||
case 0x1000:
|
|
||||||
DEV9write16(mem & 0x1fffffff, value); return;
|
|
||||||
default:
|
|
||||||
assert( g_psxWriteOk );
|
|
||||||
*(u16 *)PSXM(mem) = value;
|
|
||||||
psxCpu->Clear(mem&~3, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void iopMemWrite32(u32 mem, u32 value)
|
|
||||||
{
|
|
||||||
u32 t = (mem >> 16) & 0x1fff;
|
|
||||||
switch(t) {
|
|
||||||
case 0x1f80:
|
|
||||||
mem&= 0x1fffffff;
|
|
||||||
if (mem < 0x1f801000)
|
|
||||||
psxHu32(mem) = value;
|
|
||||||
else
|
|
||||||
psxHwWrite32(mem, value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x1d00:
|
|
||||||
switch (mem & 0xf0) {
|
|
||||||
case 0x10:
|
|
||||||
// write to ps2 mem
|
|
||||||
psHu32(0x1000F210) = value;
|
|
||||||
return;
|
|
||||||
case 0x20:
|
|
||||||
// write to ps2 mem
|
|
||||||
psHu32(0x1000F220) &= ~value;
|
|
||||||
return;
|
|
||||||
case 0x30:
|
|
||||||
// write to ps2 mem
|
|
||||||
psHu32(0x1000F230) |= value;
|
|
||||||
return;
|
|
||||||
case 0x40:
|
|
||||||
{
|
|
||||||
u32 temp = value & 0xF0;
|
|
||||||
// write to ps2 mem
|
|
||||||
if(value & 0x20 || value & 0x80)
|
|
||||||
{
|
|
||||||
psHu32(0x1000F240) &= ~0xF000;
|
|
||||||
psHu32(0x1000F240) |= 0x2000;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if(psHu32(0x1000F240) & temp) psHu32(0x1000F240) &= ~temp;
|
|
||||||
else psHu32(0x1000F240) |= temp;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case 0x60:
|
|
||||||
psHu32(0x1000F260) = 0;
|
|
||||||
return;
|
|
||||||
|
|
||||||
default:
|
|
||||||
*(u32*)(PS2MEM_HW+0xf200+(mem&0xf0)) = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
case 0x1000:
|
|
||||||
DEV9write32(mem & 0x1fffffff, value);
|
|
||||||
return;
|
|
||||||
|
|
||||||
case 0x1ffe:
|
|
||||||
if( mem == 0xfffe0130 ) {
|
|
||||||
writectrl = value;
|
|
||||||
switch (value) {
|
|
||||||
case 0x800: case 0x804:
|
|
||||||
case 0xc00: case 0xc04:
|
|
||||||
case 0xcc0: case 0xcc4:
|
|
||||||
case 0x0c4:
|
|
||||||
g_psxWriteOk = 0;
|
|
||||||
//PSXMEM_LOG("writectrl: writenot ok\n");
|
|
||||||
break;
|
|
||||||
case 0x1e988:
|
|
||||||
case 0x1edd8:
|
|
||||||
g_psxWriteOk = 1;
|
|
||||||
//PSXMEM_LOG("writectrl: write ok\n");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PSXMEM_LOG("unk %8.8lx = %x\n", mem, value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
|
|
||||||
if( g_psxWriteOk ) {
|
|
||||||
*(u32 *)PSXM(mem) = value;
|
|
||||||
psxCpu->Clear(mem&~3, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
u8 *psxM = NULL;
|
u8 *psxM = NULL;
|
||||||
u8 *psxP = NULL;
|
u8 *psxP = NULL;
|
||||||
u8 *psxH = NULL;
|
u8 *psxH = NULL; // standard hardware registers (0x000->0x3ff is the scratchpad)
|
||||||
u8 *psxS = NULL;
|
u8 *psxS = NULL; // 'undocumented' SIF communication registers
|
||||||
|
|
||||||
uptr *psxMemWLUT = NULL;
|
uptr *psxMemWLUT = NULL;
|
||||||
const uptr *psxMemRLUT = NULL;
|
const uptr *psxMemRLUT = NULL;
|
||||||
|
@ -336,7 +37,7 @@ static const uint m_psxMemSize =
|
||||||
Ps2MemSize::IopRam +
|
Ps2MemSize::IopRam +
|
||||||
Ps2MemSize::IopHardware +
|
Ps2MemSize::IopHardware +
|
||||||
0x00010000 + // psxP
|
0x00010000 + // psxP
|
||||||
0x00010000 ; // psxS
|
0x00000100 ; // psxS
|
||||||
|
|
||||||
void psxMemAlloc()
|
void psxMemAlloc()
|
||||||
{
|
{
|
||||||
|
@ -352,8 +53,8 @@ void psxMemAlloc()
|
||||||
psxH = curpos; curpos += Ps2MemSize::IopHardware;
|
psxH = curpos; curpos += Ps2MemSize::IopHardware;
|
||||||
psxS = curpos; //curpos += 0x00010000;
|
psxS = curpos; //curpos += 0x00010000;
|
||||||
|
|
||||||
psxMemWLUT = (uptr*)_aligned_malloc(0x10000 * sizeof(uptr) * 2, 16);
|
psxMemWLUT = (uptr*)_aligned_malloc(0x2000 * sizeof(uptr) * 2, 16);
|
||||||
psxMemRLUT = psxMemWLUT + 0x10000; //(uptr*)_aligned_malloc(0x10000 * sizeof(uptr),16);
|
psxMemRLUT = psxMemWLUT + 0x2000; //(uptr*)_aligned_malloc(0x10000 * sizeof(uptr),16);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note! Resetting the IOP's memory state is dependent on having *all* psx memory allocated,
|
// Note! Resetting the IOP's memory state is dependent on having *all* psx memory allocated,
|
||||||
|
@ -365,53 +66,53 @@ void psxMemReset()
|
||||||
|
|
||||||
DbgCon::Status( "psxMemReset > Resetting core memory!" );
|
DbgCon::Status( "psxMemReset > Resetting core memory!" );
|
||||||
|
|
||||||
memzero_ptr<0x10000 * sizeof(uptr) * 2>( psxMemWLUT ); // clears both allocations, RLUT and WLUT
|
memzero_ptr<0x2000 * sizeof(uptr) * 2>( psxMemWLUT ); // clears both allocations, RLUT and WLUT
|
||||||
memzero_ptr<m_psxMemSize>( m_psxAllMem );
|
memzero_ptr<m_psxMemSize>( m_psxAllMem );
|
||||||
|
|
||||||
// Trick! We're accessing RLUT here through WLUT, since it's the non-const pointer.
|
// Trick! We're accessing RLUT here through WLUT, since it's the non-const pointer.
|
||||||
// So the ones with a 1 prefixed (ala 0x18000, etc) are RLUT tables.
|
// So the ones with a 0x2000 prefixed are RLUT tables.
|
||||||
|
|
||||||
// Map IOP main memory, which is Read/Write, and mirrored three times
|
// Map IOP main memory, which is Read/Write, and mirrored three times
|
||||||
// at 0x0, 0x8000, and 0xa000:
|
// at 0x0, 0x8000, and 0xa000:
|
||||||
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 + 0x8000] = (uptr)&psxM[(i & 0x1f) << 16];
|
||||||
psxMemWLUT[i + 0xa000] = (uptr)&psxM[(i & 0x1f) << 16];
|
//psxMemWLUT[i + 0xa000] = (uptr)&psxM[(i & 0x1f) << 16];
|
||||||
|
|
||||||
// RLUTs, accessed through WLUT.
|
// RLUTs, accessed through WLUT.
|
||||||
psxMemWLUT[i + 0x10000] = (uptr)&psxM[(i & 0x1f) << 16];
|
psxMemWLUT[i + 0x2000] = (uptr)&psxM[(i & 0x1f) << 16];
|
||||||
psxMemWLUT[i + 0x18000] = (uptr)&psxM[(i & 0x1f) << 16];
|
//psxMemWLUT[i + 0x18000] = (uptr)&psxM[(i & 0x1f) << 16];
|
||||||
psxMemWLUT[i + 0x1a000] = (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.
|
||||||
psxMemWLUT[0x11f00] = (uptr)psxP;
|
psxMemWLUT[0x2000 + 0x1f00] = (uptr)psxP;
|
||||||
psxMemWLUT[0x11f80] = (uptr)psxH;
|
psxMemWLUT[0x2000 + 0x1f80] = (uptr)psxH;
|
||||||
psxMemWLUT[0x1bf80] = (uptr)psxH;
|
//psxMemWLUT[0x1bf80] = (uptr)psxH;
|
||||||
|
|
||||||
psxMemWLUT[0x1f00] = (uptr)psxP;
|
psxMemWLUT[0x1f00] = (uptr)psxP;
|
||||||
psxMemWLUT[0x1f80] = (uptr)psxH;
|
psxMemWLUT[0x1f80] = (uptr)psxH;
|
||||||
psxMemWLUT[0xbf80] = (uptr)psxH;
|
//psxMemWLUT[0xbf80] = (uptr)psxH;
|
||||||
|
|
||||||
// Read-only memory areas, so don't map WLUT for these...
|
// Read-only memory areas, so don't map WLUT for these...
|
||||||
for (int i=0; i<0x0040; i++)
|
for (int i=0; i<0x0040; i++)
|
||||||
{
|
{
|
||||||
psxMemWLUT[i + 0x11fc0] = (uptr)&PS2MEM_ROM[i << 16];
|
psxMemWLUT[i + 0x2000 + 0x1fc0] = (uptr)&PS2MEM_ROM[i << 16];
|
||||||
psxMemWLUT[i + 0x19fc0] = (uptr)&PS2MEM_ROM[i << 16];
|
//psxMemWLUT[i + 0x19fc0] = (uptr)&PS2MEM_ROM[i << 16];
|
||||||
psxMemWLUT[i + 0x1bfc0] = (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 + 0x11e00] = (uptr)&PS2MEM_ROM1[i << 16];
|
psxMemWLUT[i + 0x2000 + 0x1e00] = (uptr)&PS2MEM_ROM1[i << 16];
|
||||||
psxMemWLUT[i + 0x19e00] = (uptr)&PS2MEM_ROM1[i << 16];
|
//psxMemWLUT[i + 0x19e00] = (uptr)&PS2MEM_ROM1[i << 16];
|
||||||
psxMemWLUT[i + 0x1be00] = (uptr)&PS2MEM_ROM1[i << 16];
|
//psxMemWLUT[i + 0x1be00] = (uptr)&PS2MEM_ROM1[i << 16];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scratchpad! (which is read only? (air))
|
// sif!! (which is read only? (air))
|
||||||
psxMemWLUT[0x11d00] = (uptr)psxS;
|
psxMemWLUT[0x2000 + 0x1d00] = (uptr)psxS;
|
||||||
psxMemWLUT[0x1bd00] = (uptr)psxS;
|
//psxMemWLUT[0x1bd00] = (uptr)psxS;
|
||||||
|
|
||||||
// why isn't scratchpad read/write? (air)
|
// 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 + 0x1d00] = (uptr)&psxS[i << 16];
|
||||||
|
@ -433,50 +134,58 @@ void psxMemShutdown()
|
||||||
psxMemRLUT = NULL;
|
psxMemRLUT = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 iopMemRead8(u32 mem) {
|
u8 iopMemRead8(u32 mem)
|
||||||
const u8* p;
|
{
|
||||||
u32 t;
|
mem &= 0x1fffffff;
|
||||||
|
u32 t = mem >> 16;
|
||||||
|
|
||||||
t = (mem >> 16) & 0x1fff;
|
if (t == 0x1f80)
|
||||||
if (t == 0x1f80) {
|
{
|
||||||
mem&= 0x1fffffff;
|
|
||||||
if (mem < 0x1f801000)
|
if (mem < 0x1f801000)
|
||||||
return psxHu8(mem);
|
return psxHu8(mem);
|
||||||
else
|
else
|
||||||
return psxHwRead8(mem);
|
return psxHwRead8(mem);
|
||||||
} else
|
}
|
||||||
if (t == 0x1f40) {
|
else if (t == 0x1f40)
|
||||||
mem&= 0x1fffffff;
|
|
||||||
return psxHw4Read8(mem);
|
|
||||||
} else
|
|
||||||
{
|
{
|
||||||
p = (const u8*)(psxMemRLUT[mem >> 16]);
|
return psxHw4Read8(mem);
|
||||||
if (p != NULL) {
|
}
|
||||||
return ( psxRegs.CP0.n.Status & 0x10000 ) ? 0 : *(const u8 *)(p + (mem & 0xffff));
|
else
|
||||||
} else {
|
{
|
||||||
if (t == 0x1000) return DEV9read8(mem & 0x1FFFFFFF);
|
const u8* p = (const u8*)(psxMemRLUT[mem >> 16]);
|
||||||
|
if (p != NULL)
|
||||||
|
{
|
||||||
|
return *(const u8 *)(p + (mem & 0xffff));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (t == 0x1000)
|
||||||
|
return DEV9read8(mem);
|
||||||
PSXMEM_LOG("err lb %8.8lx\n", mem);
|
PSXMEM_LOG("err lb %8.8lx\n", mem);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 iopMemRead16(u32 mem) {
|
u16 iopMemRead16(u32 mem)
|
||||||
const u8* p;
|
{
|
||||||
u32 t;
|
mem &= 0x1fffffff;
|
||||||
|
u32 t = mem >> 16;
|
||||||
|
|
||||||
t = (mem >> 16) & 0x1fff;
|
if (t == 0x1f80)
|
||||||
if (t == 0x1f80) {
|
{
|
||||||
mem&= 0x1fffffff;
|
|
||||||
if (mem < 0x1f801000)
|
if (mem < 0x1f801000)
|
||||||
return psxHu16(mem);
|
return psxHu16(mem);
|
||||||
else
|
else
|
||||||
return psxHwRead16(mem);
|
return psxHwRead16(mem);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
p = (const u8*)(psxMemRLUT[mem >> 16]);
|
const u8* p = (const u8*)(psxMemRLUT[mem >> 16]);
|
||||||
if (p != NULL) {
|
if (p != NULL)
|
||||||
if (t == 0x1d00) {
|
{
|
||||||
|
if (t == 0x1d00)
|
||||||
|
{
|
||||||
u16 ret;
|
u16 ret;
|
||||||
switch(mem & 0xF0)
|
switch(mem & 0xF0)
|
||||||
{
|
{
|
||||||
|
@ -493,32 +202,33 @@ u16 iopMemRead16(u32 mem) {
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if( !(psxRegs.CP0.n.Status & 0x10000) )
|
ret = psxHu16(mem);
|
||||||
ret = psxHu16(mem);
|
|
||||||
else
|
|
||||||
ret = 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
SIF_LOG("Sif reg read %x value %x\n", mem, ret);
|
SIF_LOG("Sif reg read %x value %x\n", mem, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
return *(const u16 *)(p + (mem & 0xffff));
|
return *(const u16 *)(p + (mem & 0xffff));
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if (t == 0x1F90)
|
if (t == 0x1F90)
|
||||||
return SPU2read(mem & 0x1FFFFFFF);
|
return SPU2read(mem);
|
||||||
if (t == 0x1000) return DEV9read16(mem & 0x1FFFFFFF);
|
if (t == 0x1000)
|
||||||
|
return DEV9read16(mem);
|
||||||
PSXMEM_LOG("err lh %8.8lx\n", mem);
|
PSXMEM_LOG("err lh %8.8lx\n", mem);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 iopMemRead32(u32 mem) {
|
u32 iopMemRead32(u32 mem)
|
||||||
const u8* p;
|
{
|
||||||
u32 t;
|
mem &= 0x1fffffff;
|
||||||
t = (mem >> 16) & 0x1fff;
|
u32 t = mem >> 16;
|
||||||
if (t == 0x1f80) {
|
|
||||||
mem&= 0x1fffffff;
|
if (t == 0x1f80)
|
||||||
|
{
|
||||||
if (mem < 0x1f801000)
|
if (mem < 0x1f801000)
|
||||||
return psxHu32(mem);
|
return psxHu32(mem);
|
||||||
else
|
else
|
||||||
|
@ -526,9 +236,11 @@ u32 iopMemRead32(u32 mem) {
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
//see also Hw.c
|
//see also Hw.c
|
||||||
p = (const u8*)(psxMemRLUT[mem >> 16]);
|
const u8* p = (const u8*)(psxMemRLUT[mem >> 16]);
|
||||||
if (p != NULL) {
|
if (p != NULL)
|
||||||
if (t == 0x1d00) {
|
{
|
||||||
|
if (t == 0x1d00)
|
||||||
|
{
|
||||||
u32 ret;
|
u32 ret;
|
||||||
switch(mem & 0xF0)
|
switch(mem & 0xF0)
|
||||||
{
|
{
|
||||||
|
@ -551,42 +263,42 @@ u32 iopMemRead32(u32 mem) {
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if( !(psxRegs.CP0.n.Status & 0x10000) )
|
ret = psxHu32(mem);
|
||||||
ret = psxHu32(mem);
|
|
||||||
else
|
|
||||||
ret = 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
SIF_LOG("Sif reg read %x value %x\n", mem, ret);
|
SIF_LOG("Sif reg read %x value %x\n", mem, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
return *(const u32 *)(p + (mem & 0xffff));
|
return *(const u32 *)(p + (mem & 0xffff));
|
||||||
} else {
|
}
|
||||||
if (t == 0x1000) return DEV9read32(mem & 0x1FFFFFFF);
|
else
|
||||||
|
{
|
||||||
|
if (t == 0x1000)
|
||||||
|
return DEV9read32(mem);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void iopMemWrite8(u32 mem, u8 value) {
|
void iopMemWrite8(u32 mem, u8 value)
|
||||||
char *p;
|
{
|
||||||
u32 t;
|
mem &= 0x1fffffff;
|
||||||
|
u32 t = mem >> 16;
|
||||||
t = (mem >> 16) & 0x1fff;
|
|
||||||
if (t == 0x1f80) {
|
if (t == 0x1f80)
|
||||||
mem&= 0x1fffffff;
|
{
|
||||||
if (mem < 0x1f801000)
|
if (mem < 0x1f801000)
|
||||||
psxHu8(mem) = value;
|
psxHu8(mem) = value;
|
||||||
else
|
else
|
||||||
psxHwWrite8(mem, value);
|
psxHwWrite8(mem, value);
|
||||||
} else
|
}
|
||||||
if (t == 0x1f40) {
|
else if (t == 0x1f40)
|
||||||
mem&= 0x1fffffff;
|
|
||||||
psxHw4Write8(mem, value);
|
|
||||||
} else
|
|
||||||
{
|
{
|
||||||
p = (char *)(psxMemWLUT[mem >> 16]);
|
psxHw4Write8(mem, value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u8* p = (u8 *)(psxMemWLUT[mem >> 16]);
|
||||||
if (p != NULL && !(psxRegs.CP0.n.Status & 0x10000) )
|
if (p != NULL && !(psxRegs.CP0.n.Status & 0x10000) )
|
||||||
{
|
{
|
||||||
*(u8 *)(p + (mem & 0xffff)) = value;
|
*(u8 *)(p + (mem & 0xffff)) = value;
|
||||||
|
@ -594,35 +306,35 @@ void iopMemWrite8(u32 mem, u8 value) {
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((t & 0x1FFF)==0x1D00) SysPrintf("sw8 [0x%08X]=0x%08X\n", mem, value);
|
if (t == 0x1D00) SysPrintf("sw8 [0x%08X]=0x%08X\n", mem, value);
|
||||||
if (t == 0x1d00) {
|
if (t == 0x1d00) {
|
||||||
psxSu8(mem) = value; return;
|
psxSu8(mem) = value; return;
|
||||||
}
|
}
|
||||||
if (t == 0x1000) {
|
if (t == 0x1000) {
|
||||||
DEV9write8(mem & 0x1fffffff, value); return;
|
DEV9write8(mem, value); return;
|
||||||
}
|
}
|
||||||
PSXMEM_LOG("err sb %8.8lx = %x\n", mem, value);
|
PSXMEM_LOG("err sb %8.8lx = %x\n", mem, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void iopMemWrite16(u32 mem, u16 value) {
|
void iopMemWrite16(u32 mem, u16 value)
|
||||||
char *p;
|
{
|
||||||
u32 t;
|
mem &= 0x1fffffff;
|
||||||
|
u32 t = mem >> 16;
|
||||||
|
|
||||||
t = (mem >> 16) & 0x1fff;
|
if (t == 0x1f80)
|
||||||
if (t == 0x1f80) {
|
{
|
||||||
mem&= 0x1fffffff;
|
|
||||||
if (mem < 0x1f801000)
|
if (mem < 0x1f801000)
|
||||||
psxHu16(mem) = value;
|
psxHu16(mem) = value;
|
||||||
else
|
else
|
||||||
psxHwWrite16(mem, value);
|
psxHwWrite16(mem, value);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
p = (char *)(psxMemWLUT[mem >> 16]);
|
u8* p = (u8 *)(psxMemWLUT[mem >> 16]);
|
||||||
if (p != NULL && !(psxRegs.CP0.n.Status & 0x10000) )
|
if (p != NULL && !(psxRegs.CP0.n.Status & 0x10000) )
|
||||||
{
|
{
|
||||||
if ((t & 0x1FFF)==0x1D00) SysPrintf("sw16 [0x%08X]=0x%08X\n", mem, value);
|
if( t==0x1D00 ) SysPrintf("sw16 [0x%08X]=0x%08X\n", mem, value);
|
||||||
*(u16 *)(p + (mem & 0xffff)) = value;
|
*(u16 *)(p + (mem & 0xffff)) = value;
|
||||||
psxCpu->Clear(mem&~3, 1);
|
psxCpu->Clear(mem&~3, 1);
|
||||||
}
|
}
|
||||||
|
@ -659,23 +371,23 @@ void iopMemWrite16(u32 mem, u16 value) {
|
||||||
psxSu16(mem) = value; return;
|
psxSu16(mem) = value; return;
|
||||||
}
|
}
|
||||||
if (t == 0x1F90) {
|
if (t == 0x1F90) {
|
||||||
SPU2write(mem & 0x1FFFFFFF, value); return;
|
SPU2write(mem, value); return;
|
||||||
}
|
}
|
||||||
if (t == 0x1000) {
|
if (t == 0x1000) {
|
||||||
DEV9write16(mem & 0x1fffffff, value); return;
|
DEV9write16(mem, value); return;
|
||||||
}
|
}
|
||||||
PSXMEM_LOG("err sh %8.8lx = %x\n", mem, value);
|
PSXMEM_LOG("err sh %8.8lx = %x\n", mem, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void iopMemWrite32(u32 mem, u32 value) {
|
void iopMemWrite32(u32 mem, u32 value)
|
||||||
char *p;
|
{
|
||||||
u32 t;
|
mem &= 0x1fffffff;
|
||||||
|
u32 t = mem >> 16;
|
||||||
|
|
||||||
t = (mem >> 16) & 0x1fff;
|
if (t == 0x1f80)
|
||||||
if (t == 0x1f80) {
|
{
|
||||||
mem&= 0x1fffffff;
|
|
||||||
if (mem < 0x1f801000)
|
if (mem < 0x1f801000)
|
||||||
psxHu32(mem) = value;
|
psxHu32(mem) = value;
|
||||||
else
|
else
|
||||||
|
@ -683,7 +395,7 @@ void iopMemWrite32(u32 mem, u32 value) {
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
//see also Hw.c
|
//see also Hw.c
|
||||||
p = (char *)(psxMemWLUT[mem >> 16]);
|
u8* p = (u8 *)(psxMemWLUT[mem >> 16]);
|
||||||
if( p != NULL && !(psxRegs.CP0.n.Status & 0x10000) )
|
if( p != NULL && !(psxRegs.CP0.n.Status & 0x10000) )
|
||||||
{
|
{
|
||||||
*(u32 *)(p + (mem & 0xffff)) = value;
|
*(u32 *)(p + (mem & 0xffff)) = value;
|
||||||
|
@ -696,22 +408,24 @@ void iopMemWrite32(u32 mem, u32 value) {
|
||||||
MEM_LOG("iop Sif reg write %x value %x\n", mem, value);
|
MEM_LOG("iop Sif reg write %x value %x\n", mem, value);
|
||||||
switch (mem & 0xf0)
|
switch (mem & 0xf0)
|
||||||
{
|
{
|
||||||
case 0x10:
|
case 0x00: // EE write path (EE/IOP readable)
|
||||||
// write to ps2 mem
|
return; // this is the IOP, so read-only (do nothing)
|
||||||
|
|
||||||
|
case 0x10: // IOP write path (EE/IOP readable)
|
||||||
psHu32(0x1000F210) = value;
|
psHu32(0x1000F210) = value;
|
||||||
return;
|
return;
|
||||||
case 0x20:
|
|
||||||
// write to ps2 mem
|
case 0x20: // Bits cleared when written from IOP.
|
||||||
psHu32(0x1000F220) &= ~value;
|
psHu32(0x1000F220) &= ~value;
|
||||||
return;
|
return;
|
||||||
case 0x30:
|
|
||||||
// write to ps2 mem
|
case 0x30: // bits set when written from IOP
|
||||||
psHu32(0x1000F230) |= value;
|
psHu32(0x1000F230) |= value;
|
||||||
return;
|
return;
|
||||||
case 0x40:
|
|
||||||
|
case 0x40: // Control Register
|
||||||
{
|
{
|
||||||
u32 temp = value & 0xF0;
|
u32 temp = value & 0xF0;
|
||||||
// write to ps2 mem
|
|
||||||
if(value & 0x20 || value & 0x80)
|
if(value & 0x20 || value & 0x80)
|
||||||
{
|
{
|
||||||
psHu32(0x1000F240) &= ~0xF000;
|
psHu32(0x1000F240) &= ~0xF000;
|
||||||
|
@ -719,28 +433,28 @@ void iopMemWrite32(u32 mem, u32 value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(psHu32(0x1000F240) & temp) psHu32(0x1000F240) &= ~temp;
|
if(psHu32(0x1000F240) & temp)
|
||||||
else psHu32(0x1000F240) |= temp;
|
psHu32(0x1000F240) &= ~temp;
|
||||||
|
else
|
||||||
|
psHu32(0x1000F240) |= temp;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x60:
|
case 0x60:
|
||||||
psHu32(0x1000F260) = 0;
|
psHu32(0x1000F260) = 0;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
psxSu32(mem) = value;
|
psxSu32(mem) = value;
|
||||||
|
|
||||||
// write to ps2 mem
|
// wtf? why were we writing to the EE's sif space? Commenting this out doesn't
|
||||||
if( (mem & 0xf0) != 0x60 )
|
// break any of my games, and should be more correct, but I guess we'll see. --air
|
||||||
*(u32*)(PS2MEM_HW+0xf200+(mem&0xf0)) = value;
|
//*(u32*)(PS2MEM_HW+0xf200+(mem&0xf0)) = value;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (t == 0x1000)
|
else if (t == 0x1000)
|
||||||
{
|
{
|
||||||
DEV9write32(mem & 0x1fffffff, value); return;
|
DEV9write32(mem, value); return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -46,7 +46,8 @@ static __forceinline T* iopVirtMemW( u32 mem )
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static __forceinline const T* iopVirtMemR( u32 mem )
|
static __forceinline const T* iopVirtMemR( u32 mem )
|
||||||
{
|
{
|
||||||
return (psxMemRLUT[(mem) >> 16] == 0) ? NULL : (const T*)(psxMemRLUT[(mem) >> 16] + ((mem) & 0xffff));
|
mem &= 0x1fffffff;
|
||||||
|
return (psxMemRLUT[mem >> 16] == 0) ? NULL : (const T*)(psxMemRLUT[mem >> 16] + (mem & 0xffff));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtains a pointer to the IOP's physical mapping (bypasses the TLB)
|
// Obtains a pointer to the IOP's physical mapping (bypasses the TLB)
|
||||||
|
@ -56,11 +57,11 @@ static __forceinline u8* iopPhysMem( u32 addr )
|
||||||
}
|
}
|
||||||
|
|
||||||
#define psxSs8(mem) psxS[(mem) & 0xffff]
|
#define psxSs8(mem) psxS[(mem) & 0xffff]
|
||||||
#define psxSs16(mem) (*(s16*)&psxS[(mem) & 0xffff])
|
#define psxSs16(mem) (*(s16*)&psxS[(mem) & 0x00ff])
|
||||||
#define psxSs32(mem) (*(s32*)&psxS[(mem) & 0xffff])
|
#define psxSs32(mem) (*(s32*)&psxS[(mem) & 0x00ff])
|
||||||
#define psxSu8(mem) (*(u8*) &psxS[(mem) & 0xffff])
|
#define psxSu8(mem) (*(u8*) &psxS[(mem) & 0x00ff])
|
||||||
#define psxSu16(mem) (*(u16*)&psxS[(mem) & 0xffff])
|
#define psxSu16(mem) (*(u16*)&psxS[(mem) & 0x00ff])
|
||||||
#define psxSu32(mem) (*(u32*)&psxS[(mem) & 0xffff])
|
#define psxSu32(mem) (*(u32*)&psxS[(mem) & 0x00ff])
|
||||||
|
|
||||||
#define psxPs8(mem) psxP[(mem) & 0xffff]
|
#define psxPs8(mem) psxP[(mem) & 0xffff]
|
||||||
#define psxPs16(mem) (*(s16*)&psxP[(mem) & 0xffff])
|
#define psxPs16(mem) (*(s16*)&psxP[(mem) & 0xffff])
|
||||||
|
|
Loading…
Reference in New Issue