diff --git a/Source/Core/Common/Debug/CodeTrace.cpp b/Source/Core/Common/Debug/CodeTrace.cpp index 3023923fbb..49ad967382 100644 --- a/Source/Core/Common/Debug/CodeTrace.cpp +++ b/Source/Core/Common/Debug/CodeTrace.cpp @@ -8,6 +8,7 @@ #include #include "Common/Event.h" +#include "Core/Core.h" #include "Core/Debugger/PPCDebugInterface.h" #include "Core/HW/CPU.h" #include "Core/PowerPC/PowerPC.h" @@ -122,14 +123,14 @@ InstructionAttributes CodeTrace::GetInstructionAttributes(const TraceOutput& ins return tmp_attributes; } -TraceOutput CodeTrace::SaveCurrentInstruction(const Core::CPUThreadGuard* guard) const +TraceOutput CodeTrace::SaveCurrentInstruction(const Core::CPUThreadGuard& guard) const { - auto& system = Core::System::GetInstance(); + auto& system = guard.GetSystem(); auto& ppc_state = system.GetPPCState(); // Quickly save instruction and memory target for fast logging. TraceOutput output; - const std::string instr = PowerPC::debug_interface.Disassemble(guard, ppc_state.pc); + const std::string instr = PowerPC::debug_interface.Disassemble(&guard, ppc_state.pc); output.instruction = instr; output.address = ppc_state.pc; @@ -147,7 +148,7 @@ AutoStepResults CodeTrace::AutoStepping(const Core::CPUThreadGuard& guard, bool if (m_recording) return results; - TraceOutput pc_instr = SaveCurrentInstruction(&guard); + TraceOutput pc_instr = SaveCurrentInstruction(guard); const InstructionAttributes instr = GetInstructionAttributes(pc_instr); // Not an instruction we should start autostepping from (ie branches). @@ -199,7 +200,7 @@ AutoStepResults CodeTrace::AutoStepping(const Core::CPUThreadGuard& guard, bool { PowerPC::SingleStep(); - pc_instr = SaveCurrentInstruction(&guard); + pc_instr = SaveCurrentInstruction(guard); hit = TraceLogic(pc_instr); results.count += 1; } while (clock::now() < timeout && hit < stop_condition && diff --git a/Source/Core/Common/Debug/CodeTrace.h b/Source/Core/Common/Debug/CodeTrace.h index c47ae8e961..ae99b6d9a2 100644 --- a/Source/Core/Common/Debug/CodeTrace.h +++ b/Source/Core/Common/Debug/CodeTrace.h @@ -73,7 +73,7 @@ public: private: InstructionAttributes GetInstructionAttributes(const TraceOutput& line) const; - TraceOutput SaveCurrentInstruction(const Core::CPUThreadGuard* guard) const; + TraceOutput SaveCurrentInstruction(const Core::CPUThreadGuard& guard) const; HitType TraceLogic(const TraceOutput& current_instr, bool first_hit = false); bool m_recording = false; diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index b1da318c65..5b1b9e6ebc 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -531,13 +531,14 @@ static void EmuThread(std::unique_ptr boot, WindowSystemInfo wsi AudioCommon::InitSoundStream(system); Common::ScopeGuard audio_guard([&system] { AudioCommon::ShutdownSoundStream(system); }); - HW::Init(NetPlay::IsNetPlayRunning() ? &(boot_session_data.GetNetplaySettings()->sram) : nullptr); + HW::Init(system, + NetPlay::IsNetPlayRunning() ? &(boot_session_data.GetNetplaySettings()->sram) : nullptr); Common::ScopeGuard hw_guard{[&system] { // We must set up this flag before executing HW::Shutdown() s_hardware_initialized = false; INFO_LOG_FMT(CONSOLE, "{}", StopMessage(false, "Shutting down HW")); - HW::Shutdown(); + HW::Shutdown(system); INFO_LOG_FMT(CONSOLE, "{}", StopMessage(false, "HW shutdown")); // Clear on screen messages that haven't expired diff --git a/Source/Core/Core/Core.h b/Source/Core/Core/Core.h index 4dd0f7e32e..e237e25711 100644 --- a/Source/Core/Core/Core.h +++ b/Source/Core/Core/Core.h @@ -116,6 +116,8 @@ public: CPUThreadGuard& operator=(const CPUThreadGuard&) = delete; CPUThreadGuard& operator=(CPUThreadGuard&&) = delete; + Core::System& GetSystem() const { return m_system; } + private: Core::System& m_system; const bool m_was_cpu_thread; diff --git a/Source/Core/Core/HW/AddressSpace.cpp b/Source/Core/Core/HW/AddressSpace.cpp index b620f2ee7e..0bacf52c2d 100644 --- a/Source/Core/Core/HW/AddressSpace.cpp +++ b/Source/Core/Core/HW/AddressSpace.cpp @@ -7,6 +7,7 @@ #include "Common/BitUtils.h" #include "Core/ConfigManager.h" +#include "Core/Core.h" #include "Core/HW/DSP.h" #include "Core/HW/Memmap.h" #include "Core/PowerPC/MMU.h" @@ -125,7 +126,7 @@ struct EffectiveAddressSpaceAccessors : Accessors bool Matches(const Core::CPUThreadGuard& guard, u32 haystack_start, const u8* needle_start, std::size_t needle_size) const { - auto& system = Core::System::GetInstance(); + auto& system = guard.GetSystem(); auto& memory = system.GetMemory(); u32 page_base = haystack_start & 0xfffff000; @@ -212,13 +213,13 @@ struct AuxiliaryAddressSpaceAccessors : Accessors } u8 ReadU8(const Core::CPUThreadGuard& guard, u32 address) const override { - const u8* base = Core::System::GetInstance().GetDSP().GetARAMPtr(); + const u8* base = guard.GetSystem().GetDSP().GetARAMPtr(); return base[address]; } void WriteU8(const Core::CPUThreadGuard& guard, u32 address, u8 value) override { - u8* base = Core::System::GetInstance().GetDSP().GetARAMPtr(); + u8* base = guard.GetSystem().GetDSP().GetARAMPtr(); base[address] = value; } diff --git a/Source/Core/Core/HW/HW.cpp b/Source/Core/Core/HW/HW.cpp index a8e8ae466f..b031d24cad 100644 --- a/Source/Core/Core/HW/HW.cpp +++ b/Source/Core/Core/HW/HW.cpp @@ -31,9 +31,8 @@ namespace HW { -void Init(const Sram* override_sram) +void Init(Core::System& system, const Sram* override_sram) { - auto& system = Core::System::GetInstance(); system.GetCoreTiming().Init(); SystemTimers::PreInit(); @@ -62,10 +61,8 @@ void Init(const Sram* override_sram) } } -void Shutdown() +void Shutdown(Core::System& system) { - auto& system = Core::System::GetInstance(); - // IOS should always be shut down regardless of bWii because it can be running in GC mode (MIOS). IOS::HLE::Shutdown(); // Depends on Memory IOS::Shutdown(); @@ -86,9 +83,8 @@ void Shutdown() system.GetCoreTiming().Shutdown(); } -void DoState(PointerWrap& p) +void DoState(Core::System& system, PointerWrap& p) { - auto& system = Core::System::GetInstance(); system.GetMemory().DoState(p); p.DoMarker("Memory"); system.GetMemoryInterface().DoState(p); diff --git a/Source/Core/Core/HW/HW.h b/Source/Core/Core/HW/HW.h index 1122ca5e2d..d70ad72fa6 100644 --- a/Source/Core/Core/HW/HW.h +++ b/Source/Core/Core/HW/HW.h @@ -5,10 +5,14 @@ class PointerWrap; struct Sram; +namespace Core +{ +class System; +} namespace HW { -void Init(const Sram* override_sram); -void Shutdown(); -void DoState(PointerWrap& p); +void Init(Core::System& system, const Sram* override_sram); +void Shutdown(Core::System& system); +void DoState(Core::System& system, PointerWrap& p); } // namespace HW diff --git a/Source/Core/Core/HW/Memmap.cpp b/Source/Core/Core/HW/Memmap.cpp index 25c102d6a4..5a63405d17 100644 --- a/Source/Core/Core/HW/Memmap.cpp +++ b/Source/Core/Core/HW/Memmap.cpp @@ -41,31 +41,33 @@ namespace Memory { -MemoryManager::MemoryManager() = default; +MemoryManager::MemoryManager(Core::System& system) : m_system(system) +{ +} + MemoryManager::~MemoryManager() = default; void MemoryManager::InitMMIO(bool is_wii) { m_mmio_mapping = std::make_unique(); - auto& system = Core::System::GetInstance(); - system.GetCommandProcessor().RegisterMMIO(system, m_mmio_mapping.get(), 0x0C000000); - system.GetPixelEngine().RegisterMMIO(m_mmio_mapping.get(), 0x0C001000); - system.GetVideoInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0C002000); - system.GetProcessorInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0C003000); - system.GetMemoryInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0C004000); - system.GetDSP().RegisterMMIO(m_mmio_mapping.get(), 0x0C005000); - system.GetDVDInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0C006000, false); - system.GetSerialInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0C006400); - system.GetExpansionInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0C006800); - system.GetAudioInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0C006C00); + m_system.GetCommandProcessor().RegisterMMIO(m_system, m_mmio_mapping.get(), 0x0C000000); + m_system.GetPixelEngine().RegisterMMIO(m_mmio_mapping.get(), 0x0C001000); + m_system.GetVideoInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0C002000); + m_system.GetProcessorInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0C003000); + m_system.GetMemoryInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0C004000); + m_system.GetDSP().RegisterMMIO(m_mmio_mapping.get(), 0x0C005000); + m_system.GetDVDInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0C006000, false); + m_system.GetSerialInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0C006400); + m_system.GetExpansionInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0C006800); + m_system.GetAudioInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0C006C00); if (is_wii) { IOS::RegisterMMIO(m_mmio_mapping.get(), 0x0D000000); - system.GetDVDInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0D006000, true); - system.GetSerialInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0D006400); - system.GetExpansionInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0D006800); - system.GetAudioInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0D006C00); + m_system.GetDVDInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0D006000, true); + m_system.GetSerialInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0D006400); + m_system.GetExpansionInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0D006800); + m_system.GetAudioInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0D006C00); } } @@ -102,7 +104,7 @@ void MemoryManager::Init() &m_exram, 0x10000000, GetExRamSize(), PhysicalMemoryRegion::WII_ONLY, 0, false}; const bool wii = SConfig::GetInstance().bWii; - const bool mmu = Core::System::GetInstance().IsMMUMode(); + const bool mmu = m_system.IsMMUMode(); // If MMU is turned off in GameCube mode, turn on fake VMEM hack. const bool fake_vmem = !wii && !mmu; @@ -490,7 +492,7 @@ u8* MemoryManager::GetPointer(u32 address) const return m_exram + (address & GetExRamMask()); } - auto& ppc_state = Core::System::GetInstance().GetPPCState(); + auto& ppc_state = m_system.GetPPCState(); PanicAlertFmt("Unknown Pointer {:#010x} PC {:#010x} LR {:#010x}", address, ppc_state.pc, LR(ppc_state)); return nullptr; diff --git a/Source/Core/Core/HW/Memmap.h b/Source/Core/Core/HW/Memmap.h index 1873095d25..39c8c438bb 100644 --- a/Source/Core/Core/HW/Memmap.h +++ b/Source/Core/Core/HW/Memmap.h @@ -16,6 +16,10 @@ // Global declarations class PointerWrap; +namespace Core +{ +class System; +} namespace MMIO { class Mapping; @@ -54,7 +58,7 @@ struct LogicalMemoryView class MemoryManager { public: - MemoryManager(); + explicit MemoryManager(Core::System& system); MemoryManager(const MemoryManager& other) = delete; MemoryManager(MemoryManager&& other) = delete; MemoryManager& operator=(const MemoryManager& other) = delete; @@ -239,6 +243,8 @@ private: std::array m_physical_page_mappings{}; std::array m_logical_page_mappings{}; + Core::System& m_system; + void InitMMIO(bool is_wii); }; } // namespace Memory diff --git a/Source/Core/Core/HW/ProcessorInterface.cpp b/Source/Core/Core/HW/ProcessorInterface.cpp index 2c45e56416..70b34ccc81 100644 --- a/Source/Core/Core/HW/ProcessorInterface.cpp +++ b/Source/Core/Core/HW/ProcessorInterface.cpp @@ -18,6 +18,7 @@ #include "Core/IOS/IOS.h" #include "Core/IOS/STM/STM.h" #include "Core/PowerPC/PowerPC.h" +#include "Core/System.h" #include "VideoCommon/AsyncRequests.h" #include "VideoCommon/Fifo.h" @@ -27,6 +28,12 @@ constexpr u32 FLIPPER_REV_A = 0x046500B0; constexpr u32 FLIPPER_REV_B = 0x146500B1; constexpr u32 FLIPPER_REV_C = 0x246500B1; +ProcessorInterfaceManager::ProcessorInterfaceManager(Core::System& system) : m_system(system) +{ +} + +ProcessorInterfaceManager::~ProcessorInterfaceManager() = default; + void ProcessorInterfaceManager::DoState(PointerWrap& p) { p.Do(m_interrupt_mask); @@ -49,8 +56,7 @@ void ProcessorInterfaceManager::Init() m_reset_code = 0; // Cold reset m_interrupt_cause = INT_CAUSE_RST_BUTTON | INT_CAUSE_VI; - auto& system = Core::System::GetInstance(); - auto& core_timing = system.GetCoreTiming(); + auto& core_timing = m_system.GetCoreTiming(); m_event_type_toggle_reset_button = core_timing.RegisterEvent("ToggleResetButton", ToggleResetButtonCallback); m_event_type_ios_notify_reset_button = @@ -65,14 +71,14 @@ void ProcessorInterfaceManager::RegisterMMIO(MMIO::Mapping* mmio, u32 base) MMIO::ComplexWrite([](Core::System& system, u32, u32 val) { auto& processor_interface = system.GetProcessorInterface(); processor_interface.m_interrupt_cause &= ~val; - processor_interface.UpdateException(system); + processor_interface.UpdateException(); })); mmio->Register(base | PI_INTERRUPT_MASK, MMIO::DirectRead(&m_interrupt_mask), MMIO::ComplexWrite([](Core::System& system, u32, u32 val) { auto& processor_interface = system.GetProcessorInterface(); processor_interface.m_interrupt_mask = val; - processor_interface.UpdateException(system); + processor_interface.UpdateException(); })); mmio->Register(base | PI_FIFO_BASE, MMIO::DirectRead(&m_fifo_cpu_base), @@ -137,9 +143,9 @@ void ProcessorInterfaceManager::RegisterMMIO(MMIO::Mapping* mmio, u32 base) } } -void ProcessorInterfaceManager::UpdateException(Core::System& system) +void ProcessorInterfaceManager::UpdateException() { - auto& ppc_state = system.GetPPCState(); + auto& ppc_state = m_system.GetPPCState(); if ((m_interrupt_cause & m_interrupt_mask) != 0) ppc_state.Exceptions |= EXCEPTION_EXTERNAL_INT; else @@ -209,7 +215,7 @@ void ProcessorInterfaceManager::SetInterrupt(u32 cause_mask, bool set) m_interrupt_cause &= ~cause_mask; // is there any reason to have this possibility? // F|RES: i think the hw devices reset the interrupt in the PI to 0 // if the interrupt cause is eliminated. that isn't done by software (afaik) - UpdateException(Core::System::GetInstance()); + UpdateException(); } void ProcessorInterfaceManager::SetResetButton(bool set) @@ -252,8 +258,7 @@ void ProcessorInterfaceManager::ResetButton_Tap() if (!Core::IsRunning()) return; - auto& system = Core::System::GetInstance(); - auto& core_timing = system.GetCoreTiming(); + auto& core_timing = m_system.GetCoreTiming(); core_timing.ScheduleEvent(0, m_event_type_toggle_reset_button, true, CoreTiming::FromThread::ANY); core_timing.ScheduleEvent(0, m_event_type_ios_notify_reset_button, 0, CoreTiming::FromThread::ANY); @@ -266,8 +271,7 @@ void ProcessorInterfaceManager::PowerButton_Tap() if (!Core::IsRunning()) return; - auto& system = Core::System::GetInstance(); - auto& core_timing = system.GetCoreTiming(); + auto& core_timing = m_system.GetCoreTiming(); core_timing.ScheduleEvent(0, m_event_type_ios_notify_power_button, 0, CoreTiming::FromThread::ANY); } diff --git a/Source/Core/Core/HW/ProcessorInterface.h b/Source/Core/Core/HW/ProcessorInterface.h index 5247c03b2f..6387634843 100644 --- a/Source/Core/Core/HW/ProcessorInterface.h +++ b/Source/Core/Core/HW/ProcessorInterface.h @@ -63,6 +63,13 @@ enum class ProcessorInterfaceManager { public: + explicit ProcessorInterfaceManager(Core::System& system); + ProcessorInterfaceManager(const ProcessorInterfaceManager& other) = delete; + ProcessorInterfaceManager(ProcessorInterfaceManager&& other) = delete; + ProcessorInterfaceManager& operator=(const ProcessorInterfaceManager& other) = delete; + ProcessorInterfaceManager& operator=(ProcessorInterfaceManager&& other) = delete; + ~ProcessorInterfaceManager(); + void Init(); void DoState(PointerWrap& p); @@ -87,7 +94,7 @@ public: private: // Let the PPC know that an external exception is set/cleared - void UpdateException(Core::System& system); + void UpdateException(); void SetResetButton(bool set); @@ -101,5 +108,7 @@ private: CoreTiming::EventType* m_event_type_ios_notify_power_button = nullptr; u32 m_reset_code = 0; + + Core::System& m_system; }; } // namespace ProcessorInterface diff --git a/Source/Core/Core/PowerPC/MMU.cpp b/Source/Core/Core/PowerPC/MMU.cpp index 0a03195138..2b3706ae27 100644 --- a/Source/Core/Core/PowerPC/MMU.cpp +++ b/Source/Core/Core/PowerPC/MMU.cpp @@ -15,6 +15,7 @@ #include "Common/Logging/Log.h" #include "Core/ConfigManager.h" +#include "Core/Core.h" #include "Core/HW/CPU.h" #include "Core/HW/GPFifo.h" #include "Core/HW/MMIO.h" @@ -524,7 +525,7 @@ TryReadInstResult TryReadInstruction(u32 address) u32 HostRead_Instruction(const Core::CPUThreadGuard& guard, const u32 address) { - auto& system = Core::System::GetInstance(); + auto& system = guard.GetSystem(); auto& memory = system.GetMemory(); return ReadFromHardware(system, memory, address); } @@ -536,7 +537,7 @@ std::optional> HostTryReadInstruction(const Core::CPUThreadGuard if (!HostIsInstructionRAMAddress(guard, address, space)) return std::nullopt; - auto& system = Core::System::GetInstance(); + auto& system = guard.GetSystem(); auto& memory = system.GetMemory(); switch (space) @@ -660,7 +661,7 @@ static std::optional> HostTryReadUX(const Core::CPUThreadGuard& gu if (!HostIsRAMAddress(guard, address, space)) return std::nullopt; - auto& system = Core::System::GetInstance(); + auto& system = guard.GetSystem(); auto& memory = system.GetMemory(); switch (space) @@ -795,28 +796,28 @@ void Write_F64(const double var, const u32 address) u8 HostRead_U8(const Core::CPUThreadGuard& guard, const u32 address) { - auto& system = Core::System::GetInstance(); + auto& system = guard.GetSystem(); auto& memory = system.GetMemory(); return ReadFromHardware(system, memory, address); } u16 HostRead_U16(const Core::CPUThreadGuard& guard, const u32 address) { - auto& system = Core::System::GetInstance(); + auto& system = guard.GetSystem(); auto& memory = system.GetMemory(); return ReadFromHardware(system, memory, address); } u32 HostRead_U32(const Core::CPUThreadGuard& guard, const u32 address) { - auto& system = Core::System::GetInstance(); + auto& system = guard.GetSystem(); auto& memory = system.GetMemory(); return ReadFromHardware(system, memory, address); } u64 HostRead_U64(const Core::CPUThreadGuard& guard, const u32 address) { - auto& system = Core::System::GetInstance(); + auto& system = guard.GetSystem(); auto& memory = system.GetMemory(); return ReadFromHardware(system, memory, address); } @@ -837,28 +838,28 @@ double HostRead_F64(const Core::CPUThreadGuard& guard, const u32 address) void HostWrite_U8(const Core::CPUThreadGuard& guard, const u32 var, const u32 address) { - auto& system = Core::System::GetInstance(); + auto& system = guard.GetSystem(); auto& memory = system.GetMemory(); WriteToHardware(system, memory, address, var, 1); } void HostWrite_U16(const Core::CPUThreadGuard& guard, const u32 var, const u32 address) { - auto& system = Core::System::GetInstance(); + auto& system = guard.GetSystem(); auto& memory = system.GetMemory(); WriteToHardware(system, memory, address, var, 2); } void HostWrite_U32(const Core::CPUThreadGuard& guard, const u32 var, const u32 address) { - auto& system = Core::System::GetInstance(); + auto& system = guard.GetSystem(); auto& memory = system.GetMemory(); WriteToHardware(system, memory, address, var, 4); } void HostWrite_U64(const Core::CPUThreadGuard& guard, const u64 var, const u32 address) { - auto& system = Core::System::GetInstance(); + auto& system = guard.GetSystem(); auto& memory = system.GetMemory(); WriteToHardware(system, memory, address, static_cast(var >> 32), 4); @@ -887,7 +888,7 @@ static std::optional HostTryWriteUX(const Core::CPUThreadGuard& gua if (!HostIsRAMAddress(guard, address, space)) return std::nullopt; - auto& system = Core::System::GetInstance(); + auto& system = guard.GetSystem(); auto& memory = system.GetMemory(); switch (space) @@ -1041,7 +1042,7 @@ static bool IsRAMAddress(Memory::MemoryManager& memory, u32 address, bool transl bool HostIsRAMAddress(const Core::CPUThreadGuard& guard, u32 address, RequestedAddressSpace space) { - auto& system = Core::System::GetInstance(); + auto& system = guard.GetSystem(); auto& memory = system.GetMemory(); switch (space) @@ -1067,7 +1068,7 @@ bool HostIsInstructionRAMAddress(const Core::CPUThreadGuard& guard, u32 address, if (address & 3) return false; - auto& system = Core::System::GetInstance(); + auto& system = guard.GetSystem(); auto& memory = system.GetMemory(); switch (space) diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp index 8eb59fe938..fa26b3339a 100644 --- a/Source/Core/Core/State.cpp +++ b/Source/Core/Core/State.cpp @@ -230,7 +230,7 @@ static void DoState(PointerWrap& p) p.DoMarker("CoreTiming"); // HW needs to be restored before PowerPC because the data cache might need to be flushed. - HW::DoState(p); + HW::DoState(system, p); p.DoMarker("HW"); PowerPC::DoState(p); diff --git a/Source/Core/Core/System.cpp b/Source/Core/Core/System.cpp index 047c73793d..788a4834b9 100644 --- a/Source/Core/Core/System.cpp +++ b/Source/Core/Core/System.cpp @@ -37,8 +37,9 @@ struct System::Impl { explicit Impl(System& system) : m_audio_interface(system), m_core_timing(system), m_dsp(system), m_dvd_interface(system), - m_dvd_thread(system), m_expansion_interface(system), m_gp_fifo(system), - m_ppc_state(PowerPC::ppcState), m_serial_interface(system), m_video_interface(system) + m_dvd_thread(system), m_expansion_interface(system), m_gp_fifo(system), m_memory(system), + m_ppc_state(PowerPC::ppcState), m_processor_interface(system), m_serial_interface(system), + m_video_interface(system) { }