GPU byte swapping.

A lot of other packets likely do this.
This commit is contained in:
Ben Vanik 2013-10-19 16:29:00 -07:00
parent f15b5dae9d
commit 68d5f33cfa
4 changed files with 29 additions and 8 deletions

View File

@ -97,6 +97,14 @@ XEFORCEINLINE double XESWAPF64BE(double value) {
#define XESETUINT32BE(p, v) (*((uint32_t*)(p)) = XESWAP32BE((uint32_t)v)) #define XESETUINT32BE(p, v) (*((uint32_t*)(p)) = XESWAP32BE((uint32_t)v))
#define XESETINT64BE(p, v) (*( (int64_t*)(p)) = XESWAP64BE( (int64_t)v)) #define XESETINT64BE(p, v) (*( (int64_t*)(p)) = XESWAP64BE( (int64_t)v))
#define XESETUINT64BE(p, v) (*((uint64_t*)(p)) = XESWAP64BE((uint64_t)v)) #define XESETUINT64BE(p, v) (*((uint64_t*)(p)) = XESWAP64BE((uint64_t)v))
#define XESETINT8LE(p, v) (*( (int8_t*)(p)) = (int8_t)v)
#define XESETUINT8LE(p, v) (*( (uint8_t*)(p)) = (uint8_t)v)
#define XESETINT16LE(p, v) (*( (int16_t*)(p)) = (int16_t)v)
#define XESETUINT16LE(p, v) (*((uint16_t*)(p)) = (uint16_t)v)
#define XESETINT32LE(p, v) (*( (int32_t*)(p)) = (int32_t)v)
#define XESETUINT32LE(p, v) (*((uint32_t*)(p)) = (uint32_t)v)
#define XESETINT64LE(p, v) (*( (int64_t*)(p)) = (int64_t)v)
#define XESETUINT64LE(p, v) (*((uint64_t*)(p)) = (uint64_t)v)
#endif // XENIA_BYTE_ORDER_H_ #endif // XENIA_BYTE_ORDER_H_

View File

@ -161,7 +161,7 @@ void GraphicsSystem::WriteRegister(uint32_t r, uint64_t value) {
} }
void GraphicsSystem::DispatchInterruptCallback( void GraphicsSystem::DispatchInterruptCallback(
uint32_t source, uint32_t cpu) { uint32_t source, uint32_t cpu) {
// Pick a CPU, if needed. We're going to guess 2. Because. // Pick a CPU, if needed. We're going to guess 2. Because.
if (cpu == 0xFFFFFFFF) { if (cpu == 0xFFFFFFFF) {
cpu = 2; cpu = 2;

View File

@ -483,13 +483,10 @@ uint32_t RingBufferWorker::ExecutePacket(PacketArgs& args) {
// Write value. // Write value.
data_value = value; data_value = value;
} }
if (!(address & 0xC0000000)) { uint32_t endianness = address >> 29;
XESETUINT32BE(p + TRANSLATE_ADDR(address), data_value); address &= ~0xC0000000;
} else { data_value = GpuSwap(data_value, endianness);
// TODO(benvanik): read up on PM4_EVENT_WRITE_SHD. XESETUINT32BE(p + TRANSLATE_ADDR(address), data_value);
// No clue. Maybe relative write based on a register base?
XELOGE("UNKNOWN FORM OF PM4_EVENT_WRITE_SHD");
}
} }
break; break;

View File

@ -42,6 +42,22 @@ typedef enum {
XE_GPU_PRIMITIVE_TYPE_LINE_LOOP = 0x0C, XE_GPU_PRIMITIVE_TYPE_LINE_LOOP = 0x0C,
} XE_GPU_PRIMITIVE_TYPE; } XE_GPU_PRIMITIVE_TYPE;
XEFORCEINLINE uint32_t GpuSwap(uint32_t value, uint32_t endianness) {
switch (endianness) {
default:
case 0x0: // No swap.
return value;
case 0x1: // Swap bytes in half words.
return ((value << 8) & 0xFF00FF00) |
((value >> 8) & 0x00FF00FF);
case 0x2: // Swap bytes.
// NOTE: we are likely doing two swaps here. Wasteful. Oh well.
return XESWAP32(value);
case 0x3: // Swap half words.
return ((value >> 16) & 0xFFFF) | (value << 16);
}
}
// XE_GPU_REG_SQ_PROGRAM_CNTL // XE_GPU_REG_SQ_PROGRAM_CNTL
typedef union { typedef union {
XEPACKEDSTRUCTANONYMOUS({ XEPACKEDSTRUCTANONYMOUS({