summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorLink Mauve <linkmauve@linkmauve.fr>2026-05-06 22:24:49 +0200
committerLink Mauve <linkmauve@linkmauve.fr>2026-06-26 01:32:15 +0200
commit82a317124ade2392ad04dd47582c14e839a4c998 (patch)
treef62feac0380890486515721ac10dbca35fa548f7 /Source/Core
parentbaf91d4436449ef9b7e5afe2988cbba0fcc60eb8 (diff)
HW/ProcessorInterface: Add support for all known registers
These changes originate from testing the behaviour of the PI registers in Linux on my Wii. I started by testing the masks, writing 0xFFFF_FFFF to the registers on the Wii, and then got told about their value on a GameCube, and then figured out most of the registers through a discussion with Extrems.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/HW/ProcessorInterface.cpp42
-rw-r--r--Source/Core/Core/HW/ProcessorInterface.h25
-rw-r--r--Source/Core/Core/State.cpp2
3 files changed, 62 insertions, 7 deletions
diff --git a/Source/Core/Core/HW/ProcessorInterface.cpp b/Source/Core/Core/HW/ProcessorInterface.cpp
index 7b999ac0de..10cca6c1c5 100644
--- a/Source/Core/Core/HW/ProcessorInterface.cpp
+++ b/Source/Core/Core/HW/ProcessorInterface.cpp
@@ -41,20 +41,27 @@ void ProcessorInterfaceManager::DoState(PointerWrap& p)
p.Do(m_fifo_cpu_base);
p.Do(m_fifo_cpu_end);
p.Do(m_fifo_cpu_write_pointer);
+ p.Do(m_error_cause);
+ p.Do(m_error_address);
p.Do(m_reset_code);
+ p.Do(m_unknown);
+ p.Do(m_flipper_bus_strength);
}
void ProcessorInterfaceManager::Init()
{
m_interrupt_mask = 0;
- m_interrupt_cause = 0;
+ m_interrupt_cause = INT_CAUSE_RST_BUTTON | INT_CAUSE_VI;
m_fifo_cpu_base = 0;
m_fifo_cpu_end = 0;
m_fifo_cpu_write_pointer = 0;
+ m_error_cause = 0;
+ m_error_address = 0;
m_reset_code = 0; // Cold reset
- m_interrupt_cause = INT_CAUSE_RST_BUTTON | INT_CAUSE_VI;
+ m_unknown = 0x000001FF;
+ m_flipper_bus_strength = 0x02492492;
auto& core_timing = m_system.GetCoreTiming();
m_event_type_toggle_reset_button =
@@ -82,13 +89,25 @@ void ProcessorInterfaceManager::RegisterMMIO(MMIO::Mapping* mmio, u32 base)
}));
mmio->Register(base | PI_FIFO_BASE, MMIO::DirectRead<u32>(&m_fifo_cpu_base),
- MMIO::DirectWrite<u32>(&m_fifo_cpu_base, 0xFFFFFFE0));
+ MMIO::ComplexWrite<u32>([](Core::System& system, u32, u32 val) {
+ u32 mask = CommandProcessor::GetPhysicalAddressMask(system.IsWii()) & 0xFFFFFFE0;
+ auto& processor_interface = system.GetProcessorInterface();
+ processor_interface.m_fifo_cpu_base = val & mask;
+ }));
mmio->Register(base | PI_FIFO_END, MMIO::DirectRead<u32>(&m_fifo_cpu_end),
- MMIO::DirectWrite<u32>(&m_fifo_cpu_end, 0xFFFFFFE0));
+ MMIO::ComplexWrite<u32>([](Core::System& system, u32, u32 val) {
+ u32 mask = CommandProcessor::GetPhysicalAddressMask(system.IsWii()) & 0xFFFFFFE0;
+ auto& processor_interface = system.GetProcessorInterface();
+ processor_interface.m_fifo_cpu_end = val & mask;
+ }));
mmio->Register(base | PI_FIFO_WPTR, MMIO::DirectRead<u32>(&m_fifo_cpu_write_pointer),
- MMIO::DirectWrite<u32>(&m_fifo_cpu_write_pointer, 0xFFFFFFE0));
+ MMIO::ComplexWrite<u32>([](Core::System& system, u32, u32 val) {
+ u32 mask = CommandProcessor::GetPhysicalAddressMask(system.IsWii()) & 0xFFFFFFE0;
+ auto& processor_interface = system.GetProcessorInterface();
+ processor_interface.m_fifo_cpu_write_pointer = val & mask;
+ }));
mmio->Register(base | PI_FIFO_RESET, MMIO::InvalidRead<u32>(),
MMIO::ComplexWrite<u32>([](Core::System& system, u32, u32 val) {
@@ -116,6 +135,13 @@ void ProcessorInterfaceManager::RegisterMMIO(MMIO::Mapping* mmio, u32 base)
}
}));
+ // TODO: Use the ErrorCause enum instead.
+ mmio->Register(base | PI_ERROR_CAUSE, MMIO::DirectRead<u32>(&m_error_cause),
+ MMIO::DirectWrite<u32>(&m_error_cause, 0x00000007));
+
+ mmio->Register(base | PI_ERROR_ADDRESS, MMIO::DirectRead<u32>(&m_error_address),
+ MMIO::InvalidWrite<u32>());
+
mmio->Register(base | PI_RESET_CODE, MMIO::ComplexRead<u32>([](Core::System& system, u32) {
auto& processor_interface = system.GetProcessorInterface();
DEBUG_LOG_FMT(PROCESSORINTERFACE, "Read PI_RESET_CODE: {:08x}",
@@ -133,9 +159,15 @@ void ProcessorInterfaceManager::RegisterMMIO(MMIO::Mapping* mmio, u32 base)
}
}));
+ mmio->Register(base | PI_UNKNOWN, MMIO::DirectRead<u32>(&m_unknown),
+ MMIO::DirectWrite<u32>(&m_unknown, 0x000003FF));
+
mmio->Register(base | PI_FLIPPER_REV, MMIO::Constant<u32>(FLIPPER_REV_C),
MMIO::InvalidWrite<u32>());
+ mmio->Register(base | PI_FLIPPER_BUS_STRENGTH, MMIO::DirectRead<u32>(&m_flipper_bus_strength),
+ MMIO::DirectWrite<u32>(&m_flipper_bus_strength, 0x07FFFFFF));
+
// 16 bit reads are based on 32 bit reads.
for (u32 i = 0; i < 0x1000; i += 4)
{
diff --git a/Source/Core/Core/HW/ProcessorInterface.h b/Source/Core/Core/HW/ProcessorInterface.h
index 6387634843..4934147609 100644
--- a/Source/Core/Core/HW/ProcessorInterface.h
+++ b/Source/Core/Core/HW/ProcessorInterface.h
@@ -55,9 +55,27 @@ enum
PI_FIFO_END = 0x10,
PI_FIFO_WPTR = 0x14,
PI_FIFO_RESET = 0x18, // Used by GXAbortFrame
+ PI_ERROR_CAUSE = 0x1C,
+ PI_ERROR_ADDRESS = 0x20,
PI_RESET_CODE = 0x24,
+ PI_UNKNOWN = 0x28,
PI_FLIPPER_REV = 0x2C,
- PI_FLIPPER_UNK = 0x30 // BS1 writes 0x0245248A to it - prolly some bootstrap thing
+ PI_FLIPPER_BUS_STRENGTH = 0x30 // BS1 writes 0x0245248A to it - controls the strength of the
+ // signal on the bus. 0 means the bus is dead and Flipper will
+ // not respond any longer, increasing it from the default value
+ // can reduce the noise in the Game Boy Player.
+};
+
+enum ErrorCause : u32
+{
+ NoError = 0,
+ MisalignedAddress = 1,
+ IncorrectTransferType = 2,
+ UnsupportedTransferSize = 3,
+ AddressOutOfRange = 4,
+ WriteToROM = 5,
+ ReadFromGXFIFO = 6,
+ Reserved = 7,
};
class ProcessorInterfaceManager
@@ -92,6 +110,11 @@ public:
u32 m_fifo_cpu_end = 0;
u32 m_fifo_cpu_write_pointer = 0;
+ u32 m_error_cause = 0;
+ u32 m_error_address = 0;
+ u32 m_unknown = 0x000001FF;
+ u32 m_flipper_bus_strength = 0x02492492;
+
private:
// Let the PPC know that an external exception is set/cleared
void UpdateException();
diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp
index 040c60f6ab..345e1537e5 100644
--- a/Source/Core/Core/State.cpp
+++ b/Source/Core/Core/State.cpp
@@ -96,7 +96,7 @@ struct CompressAndDumpStateArgs
static Common::WorkQueueThreadSP<CompressAndDumpStateArgs> s_compress_and_dump_thread;
// Don't forget to increase this after doing changes on the savestate system
-constexpr u32 STATE_VERSION = 191; // Last changed in PR 14668
+constexpr u32 STATE_VERSION = 192; // Last changed in PR 14646
// Increase this if the StateExtendedHeader definition changes
constexpr u32 EXTENDED_HEADER_VERSION = 1; // Last changed in PR 12217