mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-22 22:05:38 +00:00
Added 8- and 16-bit tilegen VRAM access handlers to fix missing columns in Star Wars Trilogy tilemaps. Thanks to Spindizzi for initial confirmation that this was the problem.
This commit is contained in:
parent
9fb6acc92d
commit
61159c07f8
|
@ -858,19 +858,12 @@ void CModel3::WriteSystemRegister(unsigned reg, UINT8 data)
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
Optimized Address Space Access Handlers
|
Address Space Access Handlers
|
||||||
|
|
||||||
Although I have not yet profiled the code, these ought to be more optimal,
|
|
||||||
especially if the compiler can generate jump tables.
|
|
||||||
|
|
||||||
NOTE: Testing of some of the address ranges is not strict enough, especially
|
NOTE: Testing of some of the address ranges is not strict enough, especially
|
||||||
for the MPC10x. Write32() handles the MPC10x most correctly. For now,
|
for the MPC10x. Write32() handles the MPC10x most correctly.
|
||||||
accesses outside of the handled ranges have not been observed. Use the DEBUG
|
|
||||||
version of these handlers for validation of new games.
|
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#ifndef DEBUG
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CModel3::Read8(addr):
|
* CModel3::Read8(addr):
|
||||||
* CModel3::Read16(addr):
|
* CModel3::Read16(addr):
|
||||||
|
@ -936,6 +929,15 @@ UINT8 CModel3::Read8(UINT32 addr)
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Tile generator
|
||||||
|
case 0xF1:
|
||||||
|
if (addr < 0xF1120000)
|
||||||
|
{
|
||||||
|
// Tile generator accesses its RAM as little endian, no adjustment needed here
|
||||||
|
return TileGen.ReadRAM8(addr&0x1FFFFF);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
// 53C810 SCSI
|
// 53C810 SCSI
|
||||||
case 0xC0: // only on Step 1.0
|
case 0xC0: // only on Step 1.0
|
||||||
if (Game->step != 0x10)
|
if (Game->step != 0x10)
|
||||||
|
@ -1024,6 +1026,16 @@ UINT16 CModel3::Read16(UINT32 addr)
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Tile generator
|
||||||
|
case 0xF1:
|
||||||
|
if (addr < 0xF1120000)
|
||||||
|
{
|
||||||
|
// Tile generator accesses its RAM as little endian, no adjustment needed here
|
||||||
|
uint16_t data = TileGen.ReadRAM16(addr&0x1FFFFF);
|
||||||
|
return FLIPENDIAN16(data);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
// Unknown
|
// Unknown
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -1149,7 +1161,7 @@ UINT32 CModel3::Read32(UINT32 addr)
|
||||||
// Tile generator accesses its RAM as little endian, must flip for big endian PowerPC
|
// Tile generator accesses its RAM as little endian, must flip for big endian PowerPC
|
||||||
if (addr < 0xF1120000)
|
if (addr < 0xF1120000)
|
||||||
{
|
{
|
||||||
data = TileGen.ReadRAM(addr&0x1FFFFF);
|
data = TileGen.ReadRAM32(addr&0x1FFFFF);
|
||||||
return FLIPENDIAN32(data);
|
return FLIPENDIAN32(data);
|
||||||
}
|
}
|
||||||
else if ((addr>=0xF1180000) && (addr<0xF1180100))
|
else if ((addr>=0xF1180000) && (addr<0xF1180100))
|
||||||
|
@ -1262,6 +1274,16 @@ void CModel3::Write8(UINT32 addr, UINT8 data)
|
||||||
DebugLog("PC=%08X\twrite8 : %08X=%02X\n", ppc_get_pc(), addr, data);
|
DebugLog("PC=%08X\twrite8 : %08X=%02X\n", ppc_get_pc(), addr, data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Tile generator
|
||||||
|
case 0xF1:
|
||||||
|
if (addr < 0xF1120000)
|
||||||
|
{
|
||||||
|
// Tile generator accesses its RAM as little endian, no adjustment needed here
|
||||||
|
TileGen.WriteRAM8(addr&0x1FFFFF, data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
goto Unknown8;
|
||||||
|
|
||||||
// MPC105/106
|
// MPC105/106
|
||||||
case 0xF8:
|
case 0xF8:
|
||||||
PCIBridge.WriteRegister(addr&0xFF,data);
|
PCIBridge.WriteRegister(addr&0xFF,data);
|
||||||
|
@ -1333,6 +1355,15 @@ void CModel3::Write16(UINT32 addr, UINT16 data)
|
||||||
DebugLog("PC=%08X\twrite16 : %08X=%04X\n", ppc_get_pc(), addr, data);
|
DebugLog("PC=%08X\twrite16 : %08X=%04X\n", ppc_get_pc(), addr, data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Tile generator
|
||||||
|
case 0xF1:
|
||||||
|
if (addr < 0xF1120000)
|
||||||
|
{
|
||||||
|
// Tile generator accesses its RAM as little endian, no adjustment needed here
|
||||||
|
TileGen.WriteRAM16(addr&0x1FFFFF, FLIPENDIAN16(data));
|
||||||
|
}
|
||||||
|
goto Unknown16;
|
||||||
|
|
||||||
// MPC105/106
|
// MPC105/106
|
||||||
case 0xF8:
|
case 0xF8:
|
||||||
// Write in big endian order, like a real PowerPC
|
// Write in big endian order, like a real PowerPC
|
||||||
|
@ -1342,6 +1373,7 @@ void CModel3::Write16(UINT32 addr, UINT16 data)
|
||||||
|
|
||||||
// Unknown
|
// Unknown
|
||||||
default:
|
default:
|
||||||
|
Unknown16:
|
||||||
DebugLog("PC=%08X\twrite16: %08X=%04X\n", ppc_get_pc(), addr, data);
|
DebugLog("PC=%08X\twrite16: %08X=%04X\n", ppc_get_pc(), addr, data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1349,9 +1381,6 @@ void CModel3::Write16(UINT32 addr, UINT16 data)
|
||||||
|
|
||||||
void CModel3::Write32(UINT32 addr, UINT32 data)
|
void CModel3::Write32(UINT32 addr, UINT32 data)
|
||||||
{
|
{
|
||||||
// Debugging VF3 missing stage textures
|
|
||||||
//if ((addr == 0xb4000)) printf("B4000 written @ pc=%08x lr=%08x\n", ppc_get_pc(), ppc_get_lr());
|
|
||||||
|
|
||||||
if ((addr&3))
|
if ((addr&3))
|
||||||
{
|
{
|
||||||
Write16(addr+0,data>>16);
|
Write16(addr+0,data>>16);
|
||||||
|
@ -1502,7 +1531,7 @@ void CModel3::Write32(UINT32 addr, UINT32 data)
|
||||||
{
|
{
|
||||||
// Tile generator accesses its RAM as little endian, must flip for big endian PowerPC
|
// Tile generator accesses its RAM as little endian, must flip for big endian PowerPC
|
||||||
data = FLIPENDIAN32(data);
|
data = FLIPENDIAN32(data);
|
||||||
TileGen.WriteRAM(addr&0x1FFFFF,data);
|
TileGen.WriteRAM32(addr&0x1FFFFF,data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if ((addr>=0xF1180000) && (addr<0xF1180100))
|
else if ((addr>=0xF1180000) && (addr<0xF1180100))
|
||||||
|
@ -1549,344 +1578,6 @@ void CModel3::Write64(UINT32 addr, UINT64 data)
|
||||||
Write32(addr+4, (UINT32) data);
|
Write32(addr+4, (UINT32) data);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
Debug Mode (Strict) Address Space Access Handlers
|
|
||||||
|
|
||||||
Enabled only if DEBUG is defined. These perform stricter checks than the
|
|
||||||
"optimized" handlers but may be slower.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
|
|
||||||
/*
|
|
||||||
* CModel3::Read8(addr):
|
|
||||||
* CModel3::Read16(addr):
|
|
||||||
* CModel3::Read32(addr):
|
|
||||||
* CModel3::Read64(addr):
|
|
||||||
*
|
|
||||||
* Read handlers.
|
|
||||||
*/
|
|
||||||
UINT8 CModel3::Read8(UINT32 addr)
|
|
||||||
{
|
|
||||||
if (addr<0x00800000)
|
|
||||||
return ram[addr^3];
|
|
||||||
else if ((addr>=0xFF000000) && (addr<0xFF800000))
|
|
||||||
return cromBank[(addr&0x7FFFFF)^3];
|
|
||||||
else if (addr>=0xFF800000)
|
|
||||||
return crom[(addr&0x7FFFFF)^3];
|
|
||||||
else if ((addr>=0xC2000000) && (addr<0xC2000100))
|
|
||||||
return GPU.ReadDMARegister8(addr&0xFF);
|
|
||||||
else if (((addr>=0xF0040000) && (addr<0xF0040040)) || ((addr>=0xFE040000) && (addr<0xFE040040)))
|
|
||||||
return ReadInputs(addr&0x3F);
|
|
||||||
else if (((addr>=0xF0080000) && (addr<=0xF0080007)) || ((addr>=0xFE080000) && (addr<=0xFE080007)))
|
|
||||||
{
|
|
||||||
if ((addr&0xF) == 4) // MIDI control port
|
|
||||||
return 0xFF;
|
|
||||||
}
|
|
||||||
else if (((addr>=0xF00C0000) && (addr<0xF00DFFFF)) || ((addr>=0xFE0C0000) && (addr<0xFE0DFFFF)))
|
|
||||||
return backupRAM[(addr&0x1FFFF)^3];
|
|
||||||
else if (((addr>=0xF0100000) && (addr<0xF0100040)) || ((addr>=0xFE100000) && (addr<0xFE100040)))
|
|
||||||
return ReadSystemRegister(addr&0x3F);
|
|
||||||
else if (((addr>=0xF0140000) && (addr<0xF0140040)) || ((addr>=0xFE140000) && (addr<0xFE140040)))
|
|
||||||
{
|
|
||||||
if ((addr&3)==1) // battery voltage test
|
|
||||||
return 0x03;
|
|
||||||
else if ((addr&3)==0)
|
|
||||||
return RTC.ReadRegister((addr>>2)&0xF);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if (((addr>=0xF9000000) && (addr<0xF9000100)) || ((addr>=0xC1000000) && (addr<0xC1000100)) || ((Game->step==0x10) && ((addr>=0xC0000000) && (addr<0xC0000100))))
|
|
||||||
return SCSI.ReadRegister(addr&0xFF);
|
|
||||||
|
|
||||||
DebugLog("PC=%08X\tread8 : %08X\n", ppc_get_pc(), addr);
|
|
||||||
return 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT16 CModel3::Read16(UINT32 addr)
|
|
||||||
{
|
|
||||||
UINT16 data;
|
|
||||||
|
|
||||||
if ((addr&1))
|
|
||||||
{
|
|
||||||
data = Read8(addr+0)<<8;
|
|
||||||
data |= Read8(addr+1);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addr<0x00800000)
|
|
||||||
return *(UINT16 *) &ram[addr^2];
|
|
||||||
else if ((addr>=0xFF000000) && (addr<0xFF800000))
|
|
||||||
return *(UINT16 *) &cromBank[(addr&0x7FFFFF)^2];
|
|
||||||
else if (addr>=0xFF800000)
|
|
||||||
return *(UINT16 *) &crom[(addr&0x7FFFFF)^2];
|
|
||||||
else if (((addr>=0xF00C0000) && (addr<0xF00DFFFF)) || ((addr>=0xFE0C0000) && (addr<0xFE0DFFFF)))
|
|
||||||
return *(UINT16 *) &backupRAM[(addr&0x1FFFF)^2];
|
|
||||||
else if ((addr>=0xF0C00CF8) && (addr<0xF0C00D00)) // MPC105
|
|
||||||
return PCIBridge.ReadPCIConfigData(16,addr&3);
|
|
||||||
else if ((addr>=0xFEE00000) && (addr<0xFEF00000)) // MPC106
|
|
||||||
return PCIBridge.ReadPCIConfigData(16,addr&3);
|
|
||||||
|
|
||||||
DebugLog("PC=%08X\tread16: %08X\n", ppc_get_pc(), addr);
|
|
||||||
return 0xFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT32 CModel3::Read32(UINT32 addr)
|
|
||||||
{
|
|
||||||
UINT32 data;
|
|
||||||
|
|
||||||
if ((addr&3))
|
|
||||||
{
|
|
||||||
data = Read16(addr+0)<<16;
|
|
||||||
data |= Read16(addr+2);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addr<0x00800000)
|
|
||||||
return *(UINT32 *) &ram[addr];
|
|
||||||
else if ((addr>=0xFF000000) && (addr<0xFF800000))
|
|
||||||
return *(UINT32 *) &cromBank[(addr&0x7FFFFF)];
|
|
||||||
else if (addr>=0xFF800000)
|
|
||||||
return *(UINT32 *) &crom[(addr&0x7FFFFF)];
|
|
||||||
else if ((addr>=0x84000000) && (addr<0x8400003F))
|
|
||||||
return GPU.ReadRegister(addr&0x3F);
|
|
||||||
else if ((addr>=0xC2000000) && (addr<0xC2000100))
|
|
||||||
{
|
|
||||||
data = GPU.ReadDMARegister32(addr&0xFF);
|
|
||||||
return FLIPENDIAN32(data);
|
|
||||||
}
|
|
||||||
else if (((addr>=0xF0040000) && (addr<0xF0040040)) || ((addr>=0xFE040000) && (addr<0xFE040040)))
|
|
||||||
{
|
|
||||||
data = ReadInputs((addr&0x3F)+0) << 24;
|
|
||||||
data |= ReadInputs((addr&0x3F)+1) << 16;
|
|
||||||
data |= ReadInputs((addr&0x3F)+2) << 8;
|
|
||||||
data |= ReadInputs((addr&0x3F)+3) << 0;
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
else if (((addr>=0xF00C0000) && (addr<0xF00DFFFF)) || ((addr>=0xFE0C0000) && (addr<0xFE0DFFFF)))
|
|
||||||
return *(UINT32 *) &backupRAM[(addr&0x1FFFF)];
|
|
||||||
else if (((addr>=0xF0100000) && (addr<0xF0100040)) || ((addr>=0xFE100000) && (addr<0xFE100040)))
|
|
||||||
{
|
|
||||||
data = ReadSystemRegister((addr&0x3F)+0) << 24;
|
|
||||||
data |= ReadSystemRegister((addr&0x3F)+1) << 16;
|
|
||||||
data |= ReadSystemRegister((addr&0x3F)+2) << 8;
|
|
||||||
data |= ReadSystemRegister((addr&0x3F)+3) << 0;
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
else if ((addr>=0xF0C00CF8) && (addr<0xF0C00D00)) // MPC105
|
|
||||||
return PCIBridge.ReadPCIConfigData(32,0);
|
|
||||||
else if ((addr>=0xFEE00000) && (addr<0xFEF00000)) // MPC106
|
|
||||||
return PCIBridge.ReadPCIConfigData(32,0);
|
|
||||||
else if (((addr>=0xF0140000) && (addr<0xF0140040)) || ((addr>=0xFE140000) && (addr<0xFE140040)))
|
|
||||||
{
|
|
||||||
data = (RTC.ReadRegister((addr>>2)&0xF) << 24);
|
|
||||||
data |= 0x00030000; // set these bits to pass battery voltage test
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
else if (((addr>=0xF0180000) && (addr<0xF019FFFF)) || ((addr>=0xFE180000) && (addr<0xFE19FFFF)))
|
|
||||||
return *(UINT32 *) &securityRAM[(addr&0x1FFFF)]; // so far, only 32-bit access observed, so we use little endian access
|
|
||||||
else if (((addr>=0xF01A0000) && (addr<0xF01A003F)) || ((addr>=0xFE1A0000) && (addr<0xFE1A003F)))
|
|
||||||
return ReadSecurity(addr&0x3F);
|
|
||||||
else if ((addr>=0xF1000000) && (addr<0xF1120000))
|
|
||||||
{
|
|
||||||
// Tile generator accesses its RAM as little endian, must flip for big endian PowerPC
|
|
||||||
data = TileGen.ReadRAM(addr&0x1FFFFF);
|
|
||||||
return FLIPENDIAN32(data);
|
|
||||||
}
|
|
||||||
else if (((addr>=0xF9000000) && (addr<0xF9000100)) || ((addr>=0xC1000000) && (addr<0xC1000100)) || ((Game->step==0x10) && ((addr>=0xC0000000) && (addr<0xC0000100))))
|
|
||||||
{
|
|
||||||
data = (SCSI.ReadRegister((addr+0)&0xFF) << 24);
|
|
||||||
data |= (SCSI.ReadRegister((addr+1)&0xFF) << 16);
|
|
||||||
data |= (SCSI.ReadRegister((addr+2)&0xFF) << 8);
|
|
||||||
data |= (SCSI.ReadRegister((addr+3)&0xFF) << 0);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXES 2D GRAPHICS (to-do: integrate this into tilegen.cpp)
|
|
||||||
if (addr==0xF1180000)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
DebugLog("PC=%08X\tread32: %08X\n", ppc_get_pc(), addr);
|
|
||||||
return 0xFFFFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT64 CModel3::Read64(UINT32 addr)
|
|
||||||
{
|
|
||||||
UINT64 data;
|
|
||||||
|
|
||||||
data = Read32(addr+0);
|
|
||||||
data <<= 32;
|
|
||||||
data |= Read32(addr+4);
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* CModel3::Write8(addr, data):
|
|
||||||
* CModel3::Write16(addr, data):
|
|
||||||
* CModel3::Write32(addr, data):
|
|
||||||
* CModel3::Write64(addr, data):
|
|
||||||
*
|
|
||||||
* Write handlers.
|
|
||||||
*/
|
|
||||||
void CModel3::Write8(UINT32 addr, UINT8 data)
|
|
||||||
{
|
|
||||||
if (addr<0x00800000)
|
|
||||||
ram[addr^3] = data;
|
|
||||||
else if ((addr>=0xC2000000) && (addr<0xC2000100))
|
|
||||||
GPU.WriteDMARegister8(addr&0xFF,data);
|
|
||||||
else if (((addr>=0xF0040000) && (addr<0xF0040040)) || ((addr>=0xFE040000) && (addr<0xFE040040)))
|
|
||||||
WriteInputs(addr&0x3F,data);
|
|
||||||
else if (((addr>=0xF0080000) && (addr<=0xF0080007)) || ((addr>=0xFE080000) && (addr<=0xFE080007)))
|
|
||||||
{
|
|
||||||
if ((addr&0xF) == 0) // MIDI data port
|
|
||||||
SoundBoard.WriteMIDIPort(data);
|
|
||||||
else if ((addr&0xF) == 4) // MIDI control port
|
|
||||||
midiCtrlPort = data;
|
|
||||||
}
|
|
||||||
else if (((addr>=0xF00C0000) && (addr<0xF00E0000)) || ((addr>=0xFE0C0000) && (addr<0xFE0E0000)))
|
|
||||||
backupRAM[(addr&0x1FFFF)^3] = data;
|
|
||||||
else if (((addr>=0xF0100000) && (addr<0xF0100040)) || ((addr>=0xFE100000) && (addr<0xFE100040)))
|
|
||||||
WriteSystemRegister(addr&0x3F,data);
|
|
||||||
else if (((addr>=0xF0140000) && (addr<0xF0140040)) || ((addr>=0xFE140000) && (addr<0xFE140040)))
|
|
||||||
{
|
|
||||||
if ((addr&3)==0)
|
|
||||||
RTC.WriteRegister((addr>>2)&0xF,data);
|
|
||||||
}
|
|
||||||
else if ((addr>=0xF8FFF000) && (addr<0xF8FFF100))
|
|
||||||
PCIBridge.WriteRegister(addr&0xFF,data);
|
|
||||||
else if (((addr>=0xF9000000) && (addr<0xF9000100)) || ((addr>=0xC1000000) && (addr<0xC1000100)) || ((Game->step==0x10) && ((addr>=0xC0000000) && (addr<0xC0000100))))
|
|
||||||
SCSI.WriteRegister(addr&0xFF,data);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DebugLog("PC=%08X\twrite8 : %08X=%02X\n", ppc_get_pc(), addr, data);
|
|
||||||
//printf("PC=%08X\twrite8 : %08X=%02X\n", ppc_get_pc(), addr, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CModel3::Write16(UINT32 addr, UINT16 data)
|
|
||||||
{
|
|
||||||
if ((addr&1))
|
|
||||||
{
|
|
||||||
Write8(addr+0,data>>8);
|
|
||||||
Write8(addr+1,data&0xFF);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addr<0x00800000)
|
|
||||||
*(UINT16 *) &ram[addr^2] = data;
|
|
||||||
else if (((addr>=0xF00C0000) && (addr<0xF00E0000)) || ((addr>=0xFE0C0000) && (addr<0xFE0E0000)))
|
|
||||||
*(UINT16 *) &backupRAM[(addr&0x1FFFF)^2] = data;
|
|
||||||
else if ((addr>=0xF0C00CF8) && (addr<0xF0C00D00))
|
|
||||||
PCIBridge.WritePCIConfigData(16,addr&2,data);
|
|
||||||
else if ((addr>=0xF8FFF000) && (addr<0xF8FFF100))
|
|
||||||
{
|
|
||||||
// Write in big endian order, like a real PowerPC
|
|
||||||
PCIBridge.WriteRegister((addr&0xFF)+0,data>>8);
|
|
||||||
PCIBridge.WriteRegister((addr&0xFF)+1,data&0xFF);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DebugLog("PC=%08X\twrite16: %08X=%04X\n", ppc_get_pc(), addr, data);
|
|
||||||
//printf("PC=%08X\twrite16: %08X=%04X\n", ppc_get_pc(), addr, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CModel3::Write32(UINT32 addr, UINT32 data)
|
|
||||||
{
|
|
||||||
if ((addr&3))
|
|
||||||
{
|
|
||||||
Write16(addr+0,data>>16);
|
|
||||||
Write16(addr+2,data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addr<0x00800000)
|
|
||||||
*(UINT32 *) &ram[addr] = data;
|
|
||||||
else if ((addr>=0x88000000) && (addr<0x88000008))
|
|
||||||
GPU.Flush();
|
|
||||||
else if ((addr>=0x8C000000) && (addr<0x8C400000))
|
|
||||||
GPU.WriteLowCullingRAM(addr&0x3FFFFF,FLIPENDIAN32(data));
|
|
||||||
else if ((addr>=0x8E000000) && (addr<0x8E100000))
|
|
||||||
GPU.WriteHighCullingRAM(addr&0xFFFFF,FLIPENDIAN32(data));
|
|
||||||
else if ((addr>=0x90000000) && (addr<0x90000018))
|
|
||||||
GPU.WriteTexturePort(addr&0xFF,FLIPENDIAN32(data));
|
|
||||||
else if ((addr>=0x94000000) && (addr<0x94100000))
|
|
||||||
GPU.WriteTextureFIFO(FLIPENDIAN32(data));
|
|
||||||
else if ((addr>=0x98000000) && (addr<0x98400000))
|
|
||||||
GPU.WritePolygonRAM(addr&0x3FFFFF,FLIPENDIAN32(data));
|
|
||||||
else if ((addr>=0xC2000000) && (addr<0xC2000100))
|
|
||||||
GPU.WriteDMARegister32(addr&0xFF,FLIPENDIAN32(data));
|
|
||||||
else if (((addr>=0xF0040000) && (addr<0xF0040040)) || ((addr>=0xFE040000) && (addr<0xFE040040)))
|
|
||||||
{
|
|
||||||
WriteInputs((addr&0x3F)+0,(data>>24)&0xFF);
|
|
||||||
WriteInputs((addr&0x3F)+1,(data>>16)&0xFF);
|
|
||||||
WriteInputs((addr&0x3F)+2,(data>>8)&0xFF);
|
|
||||||
WriteInputs((addr&0x3F)+3,(data>>0)&0xFF);
|
|
||||||
}
|
|
||||||
else if (((addr>=0xF00C0000) && (addr<0xF00E0000)) || ((addr>=0xFE0C0000) && (addr<0xFE0E0000)))
|
|
||||||
*(UINT32 *) &backupRAM[(addr&0x1FFFF)] = data;
|
|
||||||
else if ((addr>=0xF0800CF8) && (addr<0xF0800D00)) // MPC105
|
|
||||||
PCIBridge.WritePCIConfigAddress(data);
|
|
||||||
else if ((addr>=0xF0C00CF8) && (addr<0xF0C00D00)) // MPC105
|
|
||||||
PCIBridge.WritePCIConfigData(32,0,data);
|
|
||||||
else if ((addr>=0xFEC00000) && (addr<0xFEE00000)) // MPC106
|
|
||||||
PCIBridge.WritePCIConfigAddress(data);
|
|
||||||
else if ((addr>=0xFEE00000) && (addr<0xFEF00000)) // MPC106
|
|
||||||
PCIBridge.WritePCIConfigData(32,0,data);
|
|
||||||
else if (((addr>=0xF0100000) && (addr<0xF0100040)) || ((addr>=0xFE100000) && (addr<0xFE100040)))
|
|
||||||
{
|
|
||||||
WriteSystemRegister((addr&0x3F)+0,(data>>24)&0xFF);
|
|
||||||
WriteSystemRegister((addr&0x3F)+1,(data>>16)&0xFF);
|
|
||||||
WriteSystemRegister((addr&0x3F)+2,(data>>8)&0xFF);
|
|
||||||
WriteSystemRegister((addr&0x3F)+3,(data>>0)&0xFF);
|
|
||||||
}
|
|
||||||
else if (((addr>=0xF0140000) && (addr<0xF0140040)) || ((addr>=0xFE140000) && (addr<0xFE140040)))
|
|
||||||
RTC.WriteRegister((addr>>2)&0xF,data);
|
|
||||||
else if (((addr>=0xF0180000) && (addr<0xF019FFFF)) || ((addr>=0xFE180000) && (addr<0xFE19FFFF)))
|
|
||||||
*(UINT32 *) &securityRAM[(addr&0x1FFFF)] = data; // so far, only 32-bit access observed, so just store little endian
|
|
||||||
else if (((addr>=0xF01A0000) && (addr<0xF01A003F)) || ((addr>=0xFE1A0000) && (addr<0xFE1A003F)))
|
|
||||||
WriteSecurity(addr&0x3F,data);
|
|
||||||
else if ((addr>=0xF1000000) && (addr<0xF1120000))
|
|
||||||
{
|
|
||||||
// Tile generator accesses its RAM as little endian, must flip for big endian PowerPC
|
|
||||||
data = FLIPENDIAN32(data);
|
|
||||||
TileGen.WriteRAM(addr&0x1FFFFF,data);
|
|
||||||
}
|
|
||||||
else if ((addr>=0xF1180000) && (addr<0xF1180100))
|
|
||||||
TileGen.WriteRegister(addr&0xFF,FLIPENDIAN32(data));
|
|
||||||
else if ((addr>=0xF8FFF000) && (addr<0xF8FFF100))
|
|
||||||
{
|
|
||||||
// Write in big endian order, like a real PowerPC
|
|
||||||
PCIBridge.WriteRegister((addr&0xFF)+0,(data>>24)&0xFF);
|
|
||||||
PCIBridge.WriteRegister((addr&0xFF)+1,(data>>16)&0xFF);
|
|
||||||
PCIBridge.WriteRegister((addr&0xFF)+2,(data>>8)&0xFF);
|
|
||||||
PCIBridge.WriteRegister((addr&0xFF)+3,data&0xFF);
|
|
||||||
}
|
|
||||||
else if (((addr>=0xF9000000) && (addr<0xF9000100)) || ((addr>=0xC1000000) && (addr<0xC1000100)) || ((Game->step==0x10) && ((addr>=0xC0000000) && (addr<0xC0000100))))
|
|
||||||
{
|
|
||||||
SCSI.WriteRegister((addr&0xFF)+0,(data>>24)&0xFF);
|
|
||||||
SCSI.WriteRegister((addr&0xFF)+1,(data>>16)&0xFF);
|
|
||||||
SCSI.WriteRegister((addr&0xFF)+2,(data>>8)&0xFF);
|
|
||||||
SCSI.WriteRegister((addr&0xFF)+3,data&0xFF);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//printf("%08X=%08X\n", addr, data);
|
|
||||||
DebugLog("PC=%08X\twrite32: %08X=%08X\n", ppc_get_pc(), addr, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CModel3::Write64(UINT32 addr, UINT64 data)
|
|
||||||
{
|
|
||||||
Write32(addr+0, (UINT32) (data>>32));
|
|
||||||
Write32(addr+4, (UINT32) data);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
Emulation and Interface Functions
|
Emulation and Interface Functions
|
||||||
|
|
|
@ -103,7 +103,7 @@ void CTileGen::LoadState(CBlockFile *SaveState)
|
||||||
UINT32 data;
|
UINT32 data;
|
||||||
|
|
||||||
SaveState->Read(&data, sizeof(data));
|
SaveState->Read(&data, sizeof(data));
|
||||||
WriteRAM(i, data);
|
WriteRAM32(i, data);
|
||||||
}
|
}
|
||||||
SaveState->Read(regs, sizeof(regs));
|
SaveState->Read(regs, sizeof(regs));
|
||||||
|
|
||||||
|
@ -267,12 +267,12 @@ void CTileGen::EndFrame(void)
|
||||||
Emulation Functions
|
Emulation Functions
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
UINT32 CTileGen::ReadRAM(unsigned addr)
|
UINT32 CTileGen::ReadRAM32(unsigned addr)
|
||||||
{
|
{
|
||||||
return *(UINT32 *) &vram[addr];
|
return *(UINT32 *) &vram[addr];
|
||||||
}
|
}
|
||||||
|
|
||||||
void CTileGen::WriteRAM(unsigned addr, UINT32 data)
|
void CTileGen::WriteRAM32(unsigned addr, UINT32 data)
|
||||||
{
|
{
|
||||||
if (g_Config.gpuMultiThreaded)
|
if (g_Config.gpuMultiThreaded)
|
||||||
MARK_DIRTY(vramDirty, addr);
|
MARK_DIRTY(vramDirty, addr);
|
||||||
|
@ -296,6 +296,38 @@ void CTileGen::WriteRAM(unsigned addr, UINT32 data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: 8- and 16-bit handlers have not been thoroughly tested
|
||||||
|
uint8_t CTileGen::ReadRAM8(unsigned addr)
|
||||||
|
{
|
||||||
|
return vram[addr];
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTileGen::WriteRAM8(unsigned addr, uint8_t data)
|
||||||
|
{
|
||||||
|
uint32_t tmp = ReadRAM32(addr & ~3);
|
||||||
|
size_t shift = (addr & 3) * 8;
|
||||||
|
uint32_t mask = 0xff << shift;
|
||||||
|
tmp &= ~mask;
|
||||||
|
tmp |= uint32_t(data) << shift;
|
||||||
|
WriteRAM32(addr & ~3, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Star Wars Trilogy uses this
|
||||||
|
uint16_t CTileGen::ReadRAM16(unsigned addr)
|
||||||
|
{
|
||||||
|
return *((uint16_t *) &vram[addr]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTileGen::WriteRAM16(unsigned addr, uint16_t data)
|
||||||
|
{
|
||||||
|
uint32_t tmp = ReadRAM32(addr & ~1);
|
||||||
|
size_t shift = (addr & 1) * 16;
|
||||||
|
uint32_t mask = 0xffff << shift;
|
||||||
|
tmp &= ~mask;
|
||||||
|
tmp |= uint32_t(data) << shift;
|
||||||
|
WriteRAM32(addr & ~1, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
void CTileGen::InitPalette(void)
|
void CTileGen::InitPalette(void)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 0x20000/4; i++)
|
for (int i = 0; i < 0x20000/4; i++)
|
||||||
|
|
|
@ -137,11 +137,13 @@ public:
|
||||||
void EndFrame(void);
|
void EndFrame(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ReadRAM(addr):
|
* ReadRAM8(addr):
|
||||||
|
* ReadRAM16(addr):
|
||||||
|
* ReadRAM32(addr):
|
||||||
*
|
*
|
||||||
* Reads the tile generator's little endian RAM (the word is returned with
|
* Reads the tile generator's little endian RAM (the word is returned with
|
||||||
* the MSB read from addr+3). If a big endian device is reading (PowerPC),
|
* the MSB read from addr+3). If a big endian device is reading (PowerPC),
|
||||||
* the result must be manually flipped.
|
* the result must be manually adjusted.
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* addr Address in tile generator RAM. Caller must ensure it is
|
* addr Address in tile generator RAM. Caller must ensure it is
|
||||||
|
@ -149,16 +151,20 @@ public:
|
||||||
* function does not.
|
* function does not.
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* A 32-bit word read as little endian from the RAM address.
|
* Data from the RAM address.
|
||||||
*/
|
*/
|
||||||
UINT32 ReadRAM(unsigned addr);
|
uint8_t ReadRAM8(unsigned addr);
|
||||||
|
uint16_t ReadRAM16(unsigned addr);
|
||||||
|
uint32_t ReadRAM32(unsigned addr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* WriteRAM(addr, data):
|
* WriteRAM8(addr, data):
|
||||||
|
* WriteRAM16(addr, data):
|
||||||
|
* WriteRAM32(addr, data):
|
||||||
*
|
*
|
||||||
* Writes to the tile generator's little endian RAM (the word's MSB is
|
* Writes to the tile generator's little endian RAM (the word's MSB is
|
||||||
* written to addr+3). If a big endian device is writing, the word must be
|
* written to addr+3). If a big endian device is writing, the address and
|
||||||
* flipped manually before passing it to this function.
|
* data must be adjusted manually before passing it to this function.
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* addr Address in tile generator RAM. Caller must ensure it is
|
* addr Address in tile generator RAM. Caller must ensure it is
|
||||||
|
@ -166,7 +172,9 @@ public:
|
||||||
* function does not.
|
* function does not.
|
||||||
* data The data to write.
|
* data The data to write.
|
||||||
*/
|
*/
|
||||||
void WriteRAM(unsigned addr, UINT32 data);
|
void WriteRAM8(unsigned addr, uint8_t data);
|
||||||
|
void WriteRAM16(unsigned addr, uint16_t data);
|
||||||
|
void WriteRAM32(unsigned addr, uint32_t data);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ReadRegister(reg):
|
* ReadRegister(reg):
|
||||||
|
|
Loading…
Reference in a new issue