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:
Bart Trzynadlowski 2017-08-29 01:28:21 +00:00
parent 50d1f95648
commit f04a285727
2 changed files with 137 additions and 142 deletions

View file

@ -30,6 +30,8 @@
* in Real3D.cpp and security board-related variable was added to Model 3
* state. PowerPC timing variables have changed. Before 0.3a release,
* 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
* loading, the game list, as well as ROM patching
* - Wrap up CPU emulation inside a class.
@ -833,18 +835,9 @@ void CModel3::WriteSystemRegister(unsigned reg, UINT8 data)
DebugLog("IRQ ENABLE=%02X\n", data);
break;
case 0x18: // IRQ acknowledge
{
// 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);
IRQ.Deassert(data);
DebugLog("IRQ ACK? %02X=%02X\n", reg, data);
break;
}
case 0x0C: // JTAG Test Access Port
GPU.WriteTAP((data>>6)&1,(data>>2)&1,(data>>5)&1,(data>>7)&1); // TCK, TMS, TDI, TRST
break;
@ -1075,7 +1068,8 @@ UINT32 CModel3::Read32(UINT32 addr)
// Real3D registers
case 0x84:
return GPU.ReadRegister(addr&0x3F);
data = GPU.ReadRegister(addr&0x3F);
return FLIPENDIAN32(data);
// Real3D DMA
case 0xC2:

View file

@ -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
// 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.
statusChange = ppc_total_cycles() + statusCycles;
statusChange = ppc_total_cycles() + statusCycles;
}
void CReal3D::EndVBlank(void)
@ -254,134 +254,6 @@ void CReal3D::EndFrame(void)
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
@ -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
******************************************************************************/
@ -891,13 +890,15 @@ uint32_t CReal3D::ReadRegister(unsigned reg)
DebugLog("Real3D: Read reg %X\n", reg);
if (reg == 0)
{
uint32_t status = (ppc_total_cycles() >= statusChange ? 0x0 : 0x2);
return 0xFFFFFFFD|status;
uint32_t status = (ppc_total_cycles() >= statusChange ? 0x0 : 0x02000000);
return 0xFDFFFFFF|status;
}
else
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 d;