mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-25 23:25:40 +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
|
||||
* 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:
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue