mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2025-02-18 10:15:38 +00:00
DMA and register space access for Real3D have been unified and CReal3D::ReadRegister() returns little endian data now that the PowerPC handler byte-swaps back, to be consistent with how DMA registers work.
This commit is contained in:
parent
50d1f95648
commit
f04a285727
|
@ -30,6 +30,8 @@
|
||||||
* in Real3D.cpp and security board-related variable was added to Model 3
|
* in Real3D.cpp and security board-related variable was added to Model 3
|
||||||
* state. PowerPC timing variables have changed. Before 0.3a release,
|
* state. PowerPC timing variables have changed. Before 0.3a release,
|
||||||
* important to change format version #.
|
* important to change format version #.
|
||||||
|
* - Remove FLIPENDIAN32() macros and have little endian devices flip data
|
||||||
|
* around themselves. Bus standard should be big endian.
|
||||||
* - ROM sets should probably be handled with a class that manages ROM
|
* - ROM sets should probably be handled with a class that manages ROM
|
||||||
* loading, the game list, as well as ROM patching
|
* loading, the game list, as well as ROM patching
|
||||||
* - Wrap up CPU emulation inside a class.
|
* - Wrap up CPU emulation inside a class.
|
||||||
|
@ -833,18 +835,9 @@ void CModel3::WriteSystemRegister(unsigned reg, UINT8 data)
|
||||||
DebugLog("IRQ ENABLE=%02X\n", data);
|
DebugLog("IRQ ENABLE=%02X\n", data);
|
||||||
break;
|
break;
|
||||||
case 0x18: // IRQ acknowledge
|
case 0x18: // IRQ acknowledge
|
||||||
{
|
IRQ.Deassert(data);
|
||||||
// MAME: Clear bits are ack. Reverse order from other IRQ regs.
|
|
||||||
//uint8_t ack = 0;
|
|
||||||
//for (int bit = 0; bit < 8; bit++)
|
|
||||||
//{
|
|
||||||
// if (!(data & (1 << bit)))
|
|
||||||
// ack |= (1 << (7-bit));
|
|
||||||
//}
|
|
||||||
//IRQ.Deassert(ack);
|
|
||||||
DebugLog("IRQ ACK? %02X=%02X\n", reg, data);
|
DebugLog("IRQ ACK? %02X=%02X\n", reg, data);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case 0x0C: // JTAG Test Access Port
|
case 0x0C: // JTAG Test Access Port
|
||||||
GPU.WriteTAP((data>>6)&1,(data>>2)&1,(data>>5)&1,(data>>7)&1); // TCK, TMS, TDI, TRST
|
GPU.WriteTAP((data>>6)&1,(data>>2)&1,(data>>5)&1,(data>>7)&1); // TCK, TMS, TDI, TRST
|
||||||
break;
|
break;
|
||||||
|
@ -1075,7 +1068,8 @@ UINT32 CModel3::Read32(UINT32 addr)
|
||||||
|
|
||||||
// Real3D registers
|
// Real3D registers
|
||||||
case 0x84:
|
case 0x84:
|
||||||
return GPU.ReadRegister(addr&0x3F);
|
data = GPU.ReadRegister(addr&0x3F);
|
||||||
|
return FLIPENDIAN32(data);
|
||||||
|
|
||||||
// Real3D DMA
|
// Real3D DMA
|
||||||
case 0xC2:
|
case 0xC2:
|
||||||
|
|
|
@ -145,7 +145,7 @@ void CReal3D::BeginVBlank(int statusCycles)
|
||||||
// Calculate point at which status bit should change value. Currently the same timing is used for both the status bit in ReadRegister
|
// Calculate point at which status bit should change value. Currently the same timing is used for both the status bit in ReadRegister
|
||||||
// and in WriteDMARegister32/ReadDMARegister32, however it may be that they are completely unrelated. It appears that step 1.x games
|
// and in WriteDMARegister32/ReadDMARegister32, however it may be that they are completely unrelated. It appears that step 1.x games
|
||||||
// access just the former while step 2.x access the latter. It is not known yet what this bit/these bits actually represent.
|
// access just the former while step 2.x access the latter. It is not known yet what this bit/these bits actually represent.
|
||||||
statusChange = ppc_total_cycles() + statusCycles;
|
statusChange = ppc_total_cycles() + statusCycles;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CReal3D::EndVBlank(void)
|
void CReal3D::EndVBlank(void)
|
||||||
|
@ -254,134 +254,6 @@ void CReal3D::EndFrame(void)
|
||||||
Render3D->EndFrame();
|
Render3D->EndFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
DMA Device
|
|
||||||
|
|
||||||
Register 0xC:
|
|
||||||
-------------
|
|
||||||
+---+---+---+---+---+---+---+---+
|
|
||||||
|BUS|???|???|???|???|???|???|IRQ|
|
|
||||||
+---+---+---+---+---+---+---+---+
|
|
||||||
BUS: Busy (see von2 0x18A104) if 1.
|
|
||||||
IRQ: IRQ pending.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
void CReal3D::DMACopy(void)
|
|
||||||
{
|
|
||||||
DebugLog("Real3D DMA copy (PC=%08X, LR=%08X): %08X -> %08X, %X %s\n", ppc_get_pc(), ppc_get_lr(), dmaSrc, dmaDest, dmaLength*4, (dmaConfig&0x80)?"(byte reversed)":"");
|
|
||||||
//printf("Real3D DMA copy (PC=%08X, LR=%08X): %08X -> %08X, %X %s\n", ppc_get_pc(), ppc_get_lr(), dmaSrc, dmaDest, dmaLength*4, (dmaConfig&0x80)?"(byte reversed)":"");
|
|
||||||
if ((dmaConfig&0x80)) // reverse bytes
|
|
||||||
{
|
|
||||||
while (dmaLength != 0)
|
|
||||||
{
|
|
||||||
uint32_t data = Bus->Read32(dmaSrc);
|
|
||||||
Bus->Write32(dmaDest, FLIPENDIAN32(data));
|
|
||||||
dmaSrc += 4;
|
|
||||||
dmaDest += 4;
|
|
||||||
--dmaLength;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
while (dmaLength != 0)
|
|
||||||
{
|
|
||||||
Bus->Write32(dmaDest, Bus->Read32(dmaSrc));
|
|
||||||
dmaSrc += 4;
|
|
||||||
dmaDest += 4;
|
|
||||||
--dmaLength;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t CReal3D::ReadDMARegister8(unsigned reg)
|
|
||||||
{
|
|
||||||
switch (reg)
|
|
||||||
{
|
|
||||||
case 0xC: // status
|
|
||||||
return dmaStatus;
|
|
||||||
case 0xE: // configuration
|
|
||||||
return dmaConfig;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
DebugLog("Real3D: ReadDMARegister8: reg=%X\n", reg);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CReal3D::WriteDMARegister8(unsigned reg, uint8_t data)
|
|
||||||
{
|
|
||||||
switch (reg)
|
|
||||||
{
|
|
||||||
case 0xD: // IRQ acknowledge
|
|
||||||
if ((data&1))
|
|
||||||
{
|
|
||||||
dmaStatus &= ~1;
|
|
||||||
IRQ->Deassert(dmaIRQ);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0xE: // configuration
|
|
||||||
dmaConfig = data;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
DebugLog("Real3D: WriteDMARegister8: reg=%X, data=%02X\n", reg, data);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
//DebugLog("Real3D: WriteDMARegister8: reg=%X, data=%02X\n", reg, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t CReal3D::ReadDMARegister32(unsigned reg)
|
|
||||||
{
|
|
||||||
switch (reg)
|
|
||||||
{
|
|
||||||
case 0x14: // command result
|
|
||||||
return dmaData;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
DebugLog("Real3D: ReadDMARegister32: reg=%X\n", reg);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CReal3D::WriteDMARegister32(unsigned reg, uint32_t data)
|
|
||||||
{
|
|
||||||
switch (reg)
|
|
||||||
{
|
|
||||||
case 0x00: // DMA source address
|
|
||||||
dmaSrc = data;
|
|
||||||
break;
|
|
||||||
case 0x04: // DMA destination address
|
|
||||||
dmaDest = data;
|
|
||||||
break;
|
|
||||||
case 0x08: // DMA length
|
|
||||||
dmaLength = data;
|
|
||||||
DMACopy();
|
|
||||||
dmaStatus |= 1;
|
|
||||||
IRQ->Assert(dmaIRQ);
|
|
||||||
break;
|
|
||||||
case 0x10: // command register
|
|
||||||
if ((data&0x20000000))
|
|
||||||
{
|
|
||||||
dmaData = 0x16C311DB; // Virtual On 2 expects this from DMA
|
|
||||||
DebugLog("Real3D: DMA ID command issued (ATTENTION: make sure we're returning the correct value), PC=%08X, LR=%08X\n", ppc_get_pc(), ppc_get_lr());
|
|
||||||
}
|
|
||||||
else if ((data&0x80000000))
|
|
||||||
{
|
|
||||||
//dmaUnknownReg ^= 0xFFFFFFFF;
|
|
||||||
//dmaData = dmaUnknownReg;
|
|
||||||
dmaData = (ppc_total_cycles() >= statusChange ? 0x0 : 0xFFFFFFFF); // Not sure yet if it is just bit 2 as per ReadRegister above
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x14: // ?
|
|
||||||
dmaData = 0xFFFFFFFF;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
DebugLog("Real3D: WriteDMARegister32: reg=%X, data=%08X\n", reg, data);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
//DebugLog("Real3D: WriteDMARegister32: reg=%X, data=%08X\n", reg, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
JTAG Test Access Port Simulation
|
JTAG Test Access Port Simulation
|
||||||
|
@ -789,6 +661,133 @@ void CReal3D::UploadTexture(uint32_t header, const uint16_t *texData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
DMA Device
|
||||||
|
|
||||||
|
Register 0xC:
|
||||||
|
-------------
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
|BUS|???|???|???|???|???|???|IRQ|
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
BUS: Busy (see von2 0x18A104) if 1.
|
||||||
|
IRQ: IRQ pending.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
void CReal3D::DMACopy(void)
|
||||||
|
{
|
||||||
|
DebugLog("Real3D DMA copy (PC=%08X, LR=%08X): %08X -> %08X, %X %s\n", ppc_get_pc(), ppc_get_lr(), dmaSrc, dmaDest, dmaLength*4, (dmaConfig&0x80)?"(byte reversed)":"");
|
||||||
|
//printf("Real3D DMA copy (PC=%08X, LR=%08X): %08X -> %08X, %X %s\n", ppc_get_pc(), ppc_get_lr(), dmaSrc, dmaDest, dmaLength*4, (dmaConfig&0x80)?"(byte reversed)":"");
|
||||||
|
if ((dmaConfig&0x80)) // reverse bytes
|
||||||
|
{
|
||||||
|
while (dmaLength != 0)
|
||||||
|
{
|
||||||
|
uint32_t data = Bus->Read32(dmaSrc);
|
||||||
|
Bus->Write32(dmaDest, FLIPENDIAN32(data));
|
||||||
|
dmaSrc += 4;
|
||||||
|
dmaDest += 4;
|
||||||
|
--dmaLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (dmaLength != 0)
|
||||||
|
{
|
||||||
|
Bus->Write32(dmaDest, Bus->Read32(dmaSrc));
|
||||||
|
dmaSrc += 4;
|
||||||
|
dmaDest += 4;
|
||||||
|
--dmaLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CReal3D::ReadDMARegister8(unsigned reg)
|
||||||
|
{
|
||||||
|
switch (reg)
|
||||||
|
{
|
||||||
|
case 0xC: // status
|
||||||
|
return dmaStatus;
|
||||||
|
case 0xE: // configuration
|
||||||
|
return dmaConfig;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugLog("Real3D: ReadDMARegister8: reg=%X\n", reg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CReal3D::WriteDMARegister8(unsigned reg, uint8_t data)
|
||||||
|
{
|
||||||
|
switch (reg)
|
||||||
|
{
|
||||||
|
case 0xD: // IRQ acknowledge
|
||||||
|
if ((data&1))
|
||||||
|
{
|
||||||
|
dmaStatus &= ~1;
|
||||||
|
IRQ->Deassert(dmaIRQ);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0xE: // configuration
|
||||||
|
dmaConfig = data;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DebugLog("Real3D: WriteDMARegister8: reg=%X, data=%02X\n", reg, data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//DebugLog("Real3D: WriteDMARegister8: reg=%X, data=%02X\n", reg, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t CReal3D::ReadDMARegister32(unsigned reg)
|
||||||
|
{
|
||||||
|
switch (reg)
|
||||||
|
{
|
||||||
|
case 0x14: // command result
|
||||||
|
return dmaData;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugLog("Real3D: ReadDMARegister32: reg=%X\n", reg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CReal3D::WriteDMARegister32(unsigned reg, uint32_t data)
|
||||||
|
{
|
||||||
|
switch (reg)
|
||||||
|
{
|
||||||
|
case 0x00: // DMA source address
|
||||||
|
dmaSrc = data;
|
||||||
|
break;
|
||||||
|
case 0x04: // DMA destination address
|
||||||
|
dmaDest = data;
|
||||||
|
break;
|
||||||
|
case 0x08: // DMA length
|
||||||
|
dmaLength = data;
|
||||||
|
DMACopy();
|
||||||
|
dmaStatus |= 1;
|
||||||
|
IRQ->Assert(dmaIRQ);
|
||||||
|
break;
|
||||||
|
case 0x10: // command register
|
||||||
|
if ((data&0x20000000))
|
||||||
|
{
|
||||||
|
dmaData = 0x16C311DB; // Virtual On 2 expects this from DMA
|
||||||
|
DebugLog("Real3D: DMA ID command issued (ATTENTION: make sure we're returning the correct value), PC=%08X, LR=%08X\n", ppc_get_pc(), ppc_get_lr());
|
||||||
|
}
|
||||||
|
else if ((data&0x80000000))
|
||||||
|
{
|
||||||
|
dmaData = ReadRegister(data & 0x3F);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x14: // ?
|
||||||
|
dmaData = 0xFFFFFFFF;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DebugLog("Real3D: WriteDMARegister32: reg=%X, data=%08X\n", reg, data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//DebugLog("Real3D: WriteDMARegister32: reg=%X, data=%08X\n", reg, data);
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
Basic Emulation Functions, Registers, Memory, and Texture FIFO
|
Basic Emulation Functions, Registers, Memory, and Texture FIFO
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
@ -891,13 +890,15 @@ uint32_t CReal3D::ReadRegister(unsigned reg)
|
||||||
DebugLog("Real3D: Read reg %X\n", reg);
|
DebugLog("Real3D: Read reg %X\n", reg);
|
||||||
if (reg == 0)
|
if (reg == 0)
|
||||||
{
|
{
|
||||||
uint32_t status = (ppc_total_cycles() >= statusChange ? 0x0 : 0x2);
|
uint32_t status = (ppc_total_cycles() >= statusChange ? 0x0 : 0x02000000);
|
||||||
return 0xFFFFFFFD|status;
|
return 0xFDFFFFFF|status;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return 0xFFFFFFFF;
|
return 0xFFFFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: This returns data in the way that the PowerPC bus expects. Other functions in CReal3D should
|
||||||
|
// return data this way.
|
||||||
uint32_t CReal3D::ReadPCIConfigSpace(unsigned device, unsigned reg, unsigned bits, unsigned offset)
|
uint32_t CReal3D::ReadPCIConfigSpace(unsigned device, unsigned reg, unsigned bits, unsigned offset)
|
||||||
{
|
{
|
||||||
uint32_t d;
|
uint32_t d;
|
||||||
|
|
Loading…
Reference in a new issue