diff --git a/Source/Core/Core/HW/MemoryInterface.cpp b/Source/Core/Core/HW/MemoryInterface.cpp index 27f0177287..ac9ddd116b 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/HW/Memmap.h" +#include "Core/System.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,27 @@ 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 +128,13 @@ 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..75bc9776ff 100644 --- a/Source/Core/Core/HW/WII_IPC.cpp +++ b/Source/Core/Core/HW/WII_IPC.cpp @@ -10,6 +10,7 @@ #include "Core/CoreTiming.h" #include "Core/HW/DVD/DVDInterface.h" #include "Core/HW/MMIO.h" +#include "Core/HW/Memmap.h" #include "Core/HW/ProcessorInterface.h" #include "Core/IOS/IOS.h" #include "Core/System.h" @@ -56,6 +57,19 @@ enum UNK_180 = 0x180, UNK_1CC = 0x1cc, UNK_1D0 = 0x1d0, + + VERSION = 0x214, + + // Memory controller registers + + MEM2_COLSEL = 0xB4210, + MEM2_ROWSEL = 0xB4212, + MEM2_BANKSEL = 0xB4214, + MEM2_RANKSEL = 0xB4216, + + MEM2_COLMSK = 0xB4218, + MEM2_ROWMSK = 0xB421A, + MEM2_BANKMSK = 0xB421C, }; // Indicates which pins are accessible by broadway. Writable by starlet only. @@ -129,6 +143,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 +271,20 @@ 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_is_128 = memory.GetExRamSizeReal() == Memory::MEM2_SIZE_NDEV; + + mmio->Register(base | MEM2_COLSEL, MMIO::Constant(6), MMIO::Nop()); + mmio->Register(base | MEM2_ROWSEL, MMIO::Constant(4), MMIO::Nop()); + mmio->Register(base | MEM2_BANKSEL, MMIO::Constant(2), MMIO::Nop()); + mmio->Register(base | MEM2_RANKSEL, MMIO::Constant(mem2_is_128 ? 1 : 7), MMIO::Nop()); + + mmio->Register(base | MEM2_COLMSK, MMIO::Constant(0x1FF), MMIO::Nop()); + mmio->Register(base | MEM2_ROWMSK, MMIO::Constant(0xFFF), MMIO::Nop()); + mmio->Register(base | MEM2_BANKMSK, MMIO::Constant(7), 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());