mirror of
https://github.com/stenzek/duckstation.git
synced 2026-11-07 09:36:00 -10:00
GPU: Decode GP1 command bits 29-31, only GP1(10h) ignores bits 30-31
Hardware shows GP1(40h..FFh) are not mirrors, fixes GameShark Sampler Disc resetting the GPU per glyph. Unfortunately it also relies on I_STAT going active before the exception triggers, which I'm not going to fix (at least not at the moment) due to the performance impact.
This commit is contained in:
2 files changed
+48
-22
No files matched your search
@@ -264,6 +264,46 @@ TEST_F(GPUFrontend, V2InternalRegisterQueries)
|
||||
EXPECT_EQ(GPU::ReadRegister(0), 0u);
|
||||
}
|
||||
|
||||
TEST_F(GPUFrontend, GP1HighCommandBitsAreDecoded)
|
||||
{
|
||||
constexpr u32 DISPLAY_DISABLE = 1u << 23;
|
||||
|
||||
GPU::WriteRegister(4, 0x03000000); // display on
|
||||
for (const u32 v : {0x23000001u, 0x43000001u, 0x83000001u, 0xC3000001u})
|
||||
{
|
||||
GPU::WriteRegister(4, v);
|
||||
EXPECT_EQ(GPU::ReadRegister(4) & DISPLAY_DISABLE, 0u) << std::hex << v;
|
||||
}
|
||||
|
||||
// GameShark Sampler Disc writes this before every glyph, it must not reset.
|
||||
GPU::WriteRegister(0, 0xE10006A5);
|
||||
for (const u32 v : {0x40000000u, 0x80000000u, 0xC0000000u})
|
||||
{
|
||||
GPU::WriteRegister(4, v);
|
||||
EXPECT_EQ(GPU::ReadRegister(4) & DISPLAY_DISABLE, 0u) << std::hex << v;
|
||||
EXPECT_EQ(GPU::ReadRegister(4) & 0x7FFu, 0x6A5u) << std::hex << v;
|
||||
}
|
||||
|
||||
GPU::WriteRegister(4, 0x03000001);
|
||||
EXPECT_NE(GPU::ReadRegister(4) & DISPLAY_DISABLE, 0u);
|
||||
}
|
||||
|
||||
TEST_F(GPUFrontend, GP1InfoIgnoresBits30And31)
|
||||
{
|
||||
GPU::WriteRegister(0, 0xE3001234);
|
||||
GPU::WriteRegister(0, 0xE4005678);
|
||||
for (const u32 v : {0x50000004u, 0x90000004u, 0xD0000004u})
|
||||
{
|
||||
GPU::WriteRegister(4, 0x10000003);
|
||||
ASSERT_EQ(GPU::ReadRegister(0), 0x1234u);
|
||||
GPU::WriteRegister(4, v);
|
||||
EXPECT_EQ(GPU::ReadRegister(0), 0x5678u) << std::hex << v;
|
||||
}
|
||||
GPU::WriteRegister(4, 0x10000003);
|
||||
GPU::WriteRegister(4, 0x30000004); // bit 29 is decoded: no read
|
||||
EXPECT_EQ(GPU::ReadRegister(0), 0x1234u);
|
||||
}
|
||||
|
||||
TEST_F(GPUFrontend, V2StatusReportsFieldAndUpperTextureAddress)
|
||||
{
|
||||
EXPECT_NE(GPU::ReadRegister(4) & (1u << 13), 0u);
|
||||
|
||||
+8
-22
@@ -2007,7 +2007,7 @@ u32 GPU::ReadGPUREAD()
|
||||
|
||||
void GPU::WriteGP1(u32 value)
|
||||
{
|
||||
const u32 command = (value >> 24) & 0x3Fu;
|
||||
const u32 command = value >> 24;
|
||||
const u32 param = value & UINT32_C(0x00FFFFFF);
|
||||
switch (command)
|
||||
{
|
||||
@@ -2163,30 +2163,16 @@ void GPU::WriteGP1(u32 value)
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x10:
|
||||
case 0x11:
|
||||
case 0x12:
|
||||
case 0x13:
|
||||
case 0x14:
|
||||
case 0x15:
|
||||
case 0x16:
|
||||
case 0x17:
|
||||
case 0x18:
|
||||
case 0x19:
|
||||
case 0x1A:
|
||||
case 0x1B:
|
||||
case 0x1C:
|
||||
case 0x1D:
|
||||
case 0x1E:
|
||||
case 0x1F:
|
||||
default:
|
||||
{
|
||||
HandleGetGPUInfoCommand(value);
|
||||
// GP1(10h) ignores command bits 24-27 and 30-31, every other command decodes the full byte,
|
||||
// so 40h..FFh are not mirrors of 00h..3Fh (measured on v0 and v2 GPUs).
|
||||
if ((command & 0x30u) == 0x10u) [[likely]]
|
||||
HandleGetGPUInfoCommand(value);
|
||||
else
|
||||
DEV_LOG("Unimplemented GP1 command 0x{:02X}", command);
|
||||
}
|
||||
break;
|
||||
|
||||
[[unlikely]] default:
|
||||
ERROR_LOG("Unimplemented GP1 command 0x{:02X}", command);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user