diff --git a/Source/Core/Core/HW/MemoryInterface.cpp b/Source/Core/Core/HW/MemoryInterface.cpp index 27f0177287..ba0015214f 100644 --- a/Source/Core/Core/HW/MemoryInterface.cpp +++ b/Source/Core/Core/HW/MemoryInterface.cpp @@ -10,6 +10,8 @@ #include "Common/ChunkFile.h" #include "Common/CommonTypes.h" #include "Core/HW/MMIO.h" +#include "Core/System.h" +#include "Core/HW/Memmap.h" namespace MemoryInterface { @@ -30,6 +32,7 @@ enum MI_UNKNOWN1 = 0x020, MI_PROT_ADDR_LO = 0x022, MI_PROT_ADDR_HI = 0x024, + MI_MEM_CONFIG = 0x028, MI_TIMER0_HI = 0x032, MI_TIMER0_LO = 0x034, MI_TIMER1_HI = 0x036, @@ -73,6 +76,26 @@ void MemoryInterfaceManager::DoState(PointerWrap& p) p.Do(m_mi_mem); } +static u16 EncodeMemConfig(u32 ram_size) +{ + switch (ram_size) + { + case 0x1000000: // 16MiB + return 0; + case 0x1800000: // 24MiB + return 2; + case 0x2000000: // 32MiB + return 1; + case 0x3000000: // 48MiB + return 3; + case 0x4000000: // 64MiB + return 5; + default: + return 2; // Bespoke configs can't be represented in this bitfield + // Fallback to 24. Potentially dangerous, but when not emulating this register at all it is seen as 16 + } +} + void MemoryInterfaceManager::RegisterMMIO(MMIO::Mapping* mmio, u32 base) { for (u32 i = MI_REGION0_FIRST; i <= MI_REGION3_LAST; i += 4) @@ -104,6 +127,14 @@ void MemoryInterfaceManager::RegisterMMIO(MMIO::Mapping* mmio, u32 base) mmio->Register(base | MI_PROT_ADDR_HI, MMIO::DirectRead(&m_mi_mem.prot_addr.lo), MMIO::DirectWrite(&m_mi_mem.prot_addr.lo)); + // MI RAM configuration strap. The low 3 bits encode the installed MEM1 + // size; the SDK uses this to populate OS global 0x80000028. + mmio->Register(base | MI_MEM_CONFIG, + MMIO::ComplexRead([](Core::System& system, u32) { + return EncodeMemConfig(system.GetMemory().GetRamSizeReal()); + }), + MMIO::Nop()); + for (u32 i = 0; i < m_mi_mem.timers.size(); ++i) { auto& timer = m_mi_mem.timers[i]; diff --git a/Source/Core/Core/HW/WII_IPC.cpp b/Source/Core/Core/HW/WII_IPC.cpp index c99c8afbf0..1de27068e5 100644 --- a/Source/Core/Core/HW/WII_IPC.cpp +++ b/Source/Core/Core/HW/WII_IPC.cpp @@ -13,6 +13,7 @@ #include "Core/HW/ProcessorInterface.h" #include "Core/IOS/IOS.h" #include "Core/System.h" +#include "Core/HW/Memmap.h" // This is the intercommunication between ARM and PPC. Currently only PPC actually uses it, because // of the IOS HLE @@ -56,6 +57,10 @@ enum UNK_180 = 0x180, UNK_1CC = 0x1cc, UNK_1D0 = 0x1d0, + + VERSION = 0x214, + + IS_128 = 0xB4216, }; // Indicates which pins are accessible by broadway. Writable by starlet only. @@ -129,6 +134,7 @@ void WiiIPC::Shutdown() void WiiIPC::RegisterMMIO(MMIO::Mapping* mmio, u32 base) { + auto& memory = m_system.GetMemory(); mmio->Register(base | IPC_PPCMSG, MMIO::InvalidRead(), MMIO::DirectWrite(&m_ppc_msg)); mmio->Register(base | IPC_PPCCTRL, MMIO::ComplexRead([](Core::System& system, u32) { @@ -256,6 +262,14 @@ void WiiIPC::RegisterMMIO(MMIO::Mapping* mmio, u32 base) // Register some stubbed/unknown MMIOs required to make Wii games work. mmio->Register(base | PPCSPEED, MMIO::InvalidRead(), MMIO::Nop()); mmio->Register(base | VISOLID, MMIO::InvalidRead(), MMIO::Nop()); + // Sets the Hollywood version register to 0x11 (same as placed in lomem) + mmio->Register(base | VERSION, MMIO::Constant(0x00000011), MMIO::Nop()); + + const bool mem2_128 = memory.GetExRamSizeReal() == Memory::MEM2_SIZE_NDEV; + mmio->Register(base | IS_128, + MMIO::Constant(mem2_128 ? 1 : 0), + MMIO::Nop()); + mmio->Register(base | UNK_180, MMIO::Constant(0), MMIO::Nop()); mmio->Register(base | UNK_1CC, MMIO::Constant(0), MMIO::Nop()); mmio->Register(base | UNK_1D0, MMIO::Constant(0), MMIO::Nop());