diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index 4a8d37147dab..b1da318c657e 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -783,7 +783,7 @@ static bool PauseAndLock(Core::System& system, bool do_lock, bool unpause_on_unl was_unpaused = system.GetCPU().PauseAndLock(true); } - ExpansionInterface::PauseAndLock(do_lock, false); + system.GetExpansionInterface().PauseAndLock(do_lock, false); // audio has to come after CPU, because CPU thread can wait for audio thread (m_throttle). system.GetDSP().GetDSPEmulator()->PauseAndLock(do_lock, false); diff --git a/Source/Core/Core/HW/EXI/EXI.cpp b/Source/Core/Core/HW/EXI/EXI.cpp index 445e989bfa7a..57d6ff4b7f85 100644 --- a/Source/Core/Core/HW/EXI/EXI.cpp +++ b/Source/Core/Core/HW/EXI/EXI.cpp @@ -27,28 +27,13 @@ namespace ExpansionInterface { -struct ExpansionInterfaceState::Data -{ - CoreTiming::EventType* event_type_change_device = nullptr; - CoreTiming::EventType* event_type_update_interrupts = nullptr; - - std::array, MAX_EXI_CHANNELS> channels{}; - - bool using_overridden_sram = false; -}; - -ExpansionInterfaceState::ExpansionInterfaceState() : m_data(std::make_unique()) +ExpansionInterfaceManager::ExpansionInterfaceManager(Core::System& system) : m_system(system) { } -ExpansionInterfaceState::~ExpansionInterfaceState() = default; +ExpansionInterfaceManager::~ExpansionInterfaceManager() = default; -static void ChangeDeviceCallback(Core::System& system, u64 userdata, s64 cyclesLate); -static void UpdateInterruptsCallback(Core::System& system, u64 userdata, s64 cycles_late); - -namespace -{ -void AddMemoryCard(Slot slot) +void ExpansionInterfaceManager::AddMemoryCard(Slot slot) { EXIDeviceType memorycard_device; if (Movie::IsPlayingInput() && Movie::IsConfigSaved()) @@ -76,10 +61,8 @@ void AddMemoryCard(Slot slot) memorycard_device = Config::Get(Config::GetInfoForEXIDevice(slot)); } - auto& state = Core::System::GetInstance().GetExpansionInterfaceState().GetData(); - state.channels[SlotToEXIChannel(slot)]->AddDevice(memorycard_device, SlotToEXIDevice(slot)); + m_channels[SlotToEXIChannel(slot)]->AddDevice(memorycard_device, SlotToEXIDevice(slot)); } -} // namespace u8 SlotToEXIChannel(Slot slot) { @@ -113,20 +96,18 @@ u8 SlotToEXIDevice(Slot slot) } } -void Init(const Sram* override_sram) +void ExpansionInterfaceManager::Init(const Sram* override_sram) { - auto& system = Core::System::GetInstance(); - auto& state = system.GetExpansionInterfaceState().GetData(); - auto& sram = system.GetSRAM(); + auto& sram = m_system.GetSRAM(); if (override_sram) { sram = *override_sram; - state.using_overridden_sram = true; + m_using_overridden_sram = true; } else { InitSRAM(&sram, SConfig::GetInstance().m_strSRAM); - state.using_overridden_sram = false; + m_using_overridden_sram = false; } CEXIMemoryCard::Init(); @@ -149,141 +130,130 @@ void Init(const Sram* override_sram) Memcard::HeaderData header_data; Memcard::InitializeHeaderData(&header_data, flash_id, size_mbits, shift_jis, rtc_bias, sram_language, format_time + i); - state.channels[i] = std::make_unique(system, i, header_data); + m_channels[i] = std::make_unique(m_system, i, header_data); } } for (Slot slot : MEMCARD_SLOTS) AddMemoryCard(slot); - state.channels[0]->AddDevice(EXIDeviceType::MaskROM, 1); - state.channels[SlotToEXIChannel(Slot::SP1)]->AddDevice(Config::Get(Config::MAIN_SERIAL_PORT_1), - SlotToEXIDevice(Slot::SP1)); - state.channels[2]->AddDevice(EXIDeviceType::AD16, 0); + m_channels[0]->AddDevice(EXIDeviceType::MaskROM, 1); + m_channels[SlotToEXIChannel(Slot::SP1)]->AddDevice(Config::Get(Config::MAIN_SERIAL_PORT_1), + SlotToEXIDevice(Slot::SP1)); + m_channels[2]->AddDevice(EXIDeviceType::AD16, 0); - auto& core_timing = system.GetCoreTiming(); - state.event_type_change_device = - core_timing.RegisterEvent("ChangeEXIDevice", ChangeDeviceCallback); - state.event_type_update_interrupts = + auto& core_timing = m_system.GetCoreTiming(); + m_event_type_change_device = core_timing.RegisterEvent("ChangeEXIDevice", ChangeDeviceCallback); + m_event_type_update_interrupts = core_timing.RegisterEvent("EXIUpdateInterrupts", UpdateInterruptsCallback); } -void Shutdown() +void ExpansionInterfaceManager::Shutdown() { - auto& system = Core::System::GetInstance(); - auto& state = system.GetExpansionInterfaceState().GetData(); - - for (auto& channel : state.channels) + for (auto& channel : m_channels) channel.reset(); CEXIMemoryCard::Shutdown(); - if (!state.using_overridden_sram) + if (!m_using_overridden_sram) { File::IOFile file(SConfig::GetInstance().m_strSRAM, "wb"); - auto& sram = system.GetSRAM(); + auto& sram = m_system.GetSRAM(); file.WriteArray(&sram, 1); } } -void DoState(PointerWrap& p) +void ExpansionInterfaceManager::DoState(PointerWrap& p) { - auto& state = Core::System::GetInstance().GetExpansionInterfaceState().GetData(); - for (auto& channel : state.channels) + for (auto& channel : m_channels) channel->DoState(p); } -void PauseAndLock(bool doLock, bool unpauseOnUnlock) +void ExpansionInterfaceManager::PauseAndLock(bool doLock, bool unpauseOnUnlock) { - auto& state = Core::System::GetInstance().GetExpansionInterfaceState().GetData(); - for (auto& channel : state.channels) + for (auto& channel : m_channels) channel->PauseAndLock(doLock, unpauseOnUnlock); } -void RegisterMMIO(MMIO::Mapping* mmio, u32 base) +void ExpansionInterfaceManager::RegisterMMIO(MMIO::Mapping* mmio, u32 base) { - auto& state = Core::System::GetInstance().GetExpansionInterfaceState().GetData(); for (int i = 0; i < MAX_EXI_CHANNELS; ++i) { - DEBUG_ASSERT(state.channels[i] != nullptr); + DEBUG_ASSERT(m_channels[i] != nullptr); // Each channel has 5 32 bit registers assigned to it. We offset the // base that we give to each channel for registration. // // Be careful: this means the base is no longer aligned on a page // boundary and using "base | FOO" is not valid! - state.channels[i]->RegisterMMIO(mmio, base + 5 * 4 * i); + m_channels[i]->RegisterMMIO(mmio, base + 5 * 4 * i); } } -static void ChangeDeviceCallback(Core::System& system, u64 userdata, s64 cyclesLate) +void ExpansionInterfaceManager::ChangeDeviceCallback(Core::System& system, u64 userdata, + s64 cycles_late) { u8 channel = (u8)(userdata >> 32); u8 type = (u8)(userdata >> 16); u8 num = (u8)userdata; - auto& state = system.GetExpansionInterfaceState().GetData(); - state.channels.at(channel)->AddDevice(static_cast(type), num); + system.GetExpansionInterface().m_channels.at(channel)->AddDevice(static_cast(type), + num); } -void ChangeDevice(Slot slot, EXIDeviceType device_type, CoreTiming::FromThread from_thread) +void ExpansionInterfaceManager::ChangeDevice(Slot slot, EXIDeviceType device_type, + CoreTiming::FromThread from_thread) { ChangeDevice(SlotToEXIChannel(slot), SlotToEXIDevice(slot), device_type, from_thread); } -void ChangeDevice(u8 channel, u8 device_num, EXIDeviceType device_type, - CoreTiming::FromThread from_thread) +void ExpansionInterfaceManager::ChangeDevice(u8 channel, u8 device_num, EXIDeviceType device_type, + CoreTiming::FromThread from_thread) { // Let the hardware see no device for 1 second - auto& system = Core::System::GetInstance(); - auto& core_timing = system.GetCoreTiming(); - auto& state = system.GetExpansionInterfaceState().GetData(); - core_timing.ScheduleEvent(0, state.event_type_change_device, + auto& core_timing = m_system.GetCoreTiming(); + core_timing.ScheduleEvent(0, m_event_type_change_device, ((u64)channel << 32) | ((u64)EXIDeviceType::None << 16) | device_num, from_thread); - core_timing.ScheduleEvent(SystemTimers::GetTicksPerSecond(), state.event_type_change_device, + core_timing.ScheduleEvent(SystemTimers::GetTicksPerSecond(), m_event_type_change_device, ((u64)channel << 32) | ((u64)device_type << 16) | device_num, from_thread); } -CEXIChannel* GetChannel(u32 index) +CEXIChannel* ExpansionInterfaceManager::GetChannel(u32 index) { - auto& state = Core::System::GetInstance().GetExpansionInterfaceState().GetData(); - return state.channels.at(index).get(); + return m_channels.at(index).get(); } -IEXIDevice* GetDevice(Slot slot) +IEXIDevice* ExpansionInterfaceManager::GetDevice(Slot slot) { - auto& state = Core::System::GetInstance().GetExpansionInterfaceState().GetData(); - return state.channels.at(SlotToEXIChannel(slot))->GetDevice(1 << SlotToEXIDevice(slot)); + return m_channels.at(SlotToEXIChannel(slot))->GetDevice(1 << SlotToEXIDevice(slot)); } -void UpdateInterrupts() +void ExpansionInterfaceManager::UpdateInterrupts() { // Interrupts are mapped a bit strangely: // Channel 0 Device 0 generates interrupt on channel 0 // Channel 0 Device 2 generates interrupt on channel 2 // Channel 1 Device 0 generates interrupt on channel 1 - auto& system = Core::System::GetInstance(); - auto& state = system.GetExpansionInterfaceState().GetData(); - state.channels[2]->SetEXIINT(state.channels[0]->GetDevice(4)->IsInterruptSet()); + m_channels[2]->SetEXIINT(m_channels[0]->GetDevice(4)->IsInterruptSet()); bool causeInt = false; - for (auto& channel : state.channels) + for (auto& channel : m_channels) causeInt |= channel->IsCausingInterrupt(); - system.GetProcessorInterface().SetInterrupt(ProcessorInterface::INT_CAUSE_EXI, causeInt); + m_system.GetProcessorInterface().SetInterrupt(ProcessorInterface::INT_CAUSE_EXI, causeInt); } -static void UpdateInterruptsCallback(Core::System& system, u64 userdata, s64 cycles_late) +void ExpansionInterfaceManager::UpdateInterruptsCallback(Core::System& system, u64 userdata, + s64 cycles_late) { - UpdateInterrupts(); + system.GetExpansionInterface().UpdateInterrupts(); } -void ScheduleUpdateInterrupts(CoreTiming::FromThread from, int cycles_late) +void ExpansionInterfaceManager::ScheduleUpdateInterrupts(CoreTiming::FromThread from, + int cycles_late) { - auto& system = Core::System::GetInstance(); - auto& state = Core::System::GetInstance().GetExpansionInterfaceState().GetData(); - system.GetCoreTiming().ScheduleEvent(cycles_late, state.event_type_update_interrupts, 0, from); + m_system.GetCoreTiming().ScheduleEvent(cycles_late, m_event_type_update_interrupts, 0, from); } } // namespace ExpansionInterface diff --git a/Source/Core/Core/HW/EXI/EXI.h b/Source/Core/Core/HW/EXI/EXI.h index 815029d796c4..a82f8f994d0c 100644 --- a/Source/Core/Core/HW/EXI/EXI.h +++ b/Source/Core/Core/HW/EXI/EXI.h @@ -3,6 +3,7 @@ #pragma once +#include #include #include @@ -13,10 +14,15 @@ class PointerWrap; struct Sram; +namespace Core +{ +class System; +} namespace CoreTiming { +struct EventType; enum class FromThread; -} +} // namespace CoreTiming namespace MMIO { class Mapping; @@ -24,23 +30,6 @@ class Mapping; namespace ExpansionInterface { -class ExpansionInterfaceState -{ -public: - ExpansionInterfaceState(); - ExpansionInterfaceState(const ExpansionInterfaceState&) = delete; - ExpansionInterfaceState(ExpansionInterfaceState&&) = delete; - ExpansionInterfaceState& operator=(const ExpansionInterfaceState&) = delete; - ExpansionInterfaceState& operator=(ExpansionInterfaceState&&) = delete; - ~ExpansionInterfaceState(); - - struct Data; - Data& GetData() { return *m_data; } - -private: - std::unique_ptr m_data; -}; - class CEXIChannel; class IEXIDevice; enum class EXIDeviceType : int; @@ -70,24 +59,49 @@ constexpr bool IsMemcardSlot(Slot slot) u8 SlotToEXIChannel(Slot slot); u8 SlotToEXIDevice(Slot slot); -void Init(const Sram* override_sram); -void Shutdown(); -void DoState(PointerWrap& p); -void PauseAndLock(bool doLock, bool unpauseOnUnlock); +class ExpansionInterfaceManager +{ +public: + explicit ExpansionInterfaceManager(Core::System& system); + ExpansionInterfaceManager(const ExpansionInterfaceManager&) = delete; + ExpansionInterfaceManager(ExpansionInterfaceManager&&) = delete; + ExpansionInterfaceManager& operator=(const ExpansionInterfaceManager&) = delete; + ExpansionInterfaceManager& operator=(ExpansionInterfaceManager&&) = delete; + ~ExpansionInterfaceManager(); + + void Init(const Sram* override_sram); + void Shutdown(); + void DoState(PointerWrap& p); + void PauseAndLock(bool doLock, bool unpauseOnUnlock); + + void RegisterMMIO(MMIO::Mapping* mmio, u32 base); + + void UpdateInterrupts(); + void ScheduleUpdateInterrupts(CoreTiming::FromThread from, int cycles_late); -void RegisterMMIO(MMIO::Mapping* mmio, u32 base); + void ChangeDevice(Slot slot, EXIDeviceType device_type, + CoreTiming::FromThread from_thread = CoreTiming::FromThread::NON_CPU); + void ChangeDevice(u8 channel, u8 device_num, EXIDeviceType device_type, + CoreTiming::FromThread from_thread = CoreTiming::FromThread::NON_CPU); -void UpdateInterrupts(); -void ScheduleUpdateInterrupts(CoreTiming::FromThread from, int cycles_late); + CEXIChannel* GetChannel(u32 index); + IEXIDevice* GetDevice(Slot slot); -void ChangeDevice(Slot slot, EXIDeviceType device_type, - CoreTiming::FromThread from_thread = CoreTiming::FromThread::NON_CPU); -void ChangeDevice(u8 channel, u8 device_num, EXIDeviceType device_type, - CoreTiming::FromThread from_thread = CoreTiming::FromThread::NON_CPU); +private: + void AddMemoryCard(Slot slot); + + static void ChangeDeviceCallback(Core::System& system, u64 userdata, s64 cycles_late); + static void UpdateInterruptsCallback(Core::System& system, u64 userdata, s64 cycles_late); + + CoreTiming::EventType* m_event_type_change_device = nullptr; + CoreTiming::EventType* m_event_type_update_interrupts = nullptr; -CEXIChannel* GetChannel(u32 index); -IEXIDevice* GetDevice(Slot slot); + std::array, MAX_EXI_CHANNELS> m_channels; + bool m_using_overridden_sram = false; + + Core::System& m_system; +}; } // namespace ExpansionInterface template <> diff --git a/Source/Core/Core/HW/EXI/EXI_Channel.cpp b/Source/Core/Core/HW/EXI/EXI_Channel.cpp index c9900febc49b..1eb1bbae543e 100644 --- a/Source/Core/Core/HW/EXI/EXI_Channel.cpp +++ b/Source/Core/Core/HW/EXI/EXI_Channel.cpp @@ -62,7 +62,7 @@ void CEXIChannel::RegisterMMIO(MMIO::Mapping* mmio, u32 base) return m_status.Hex; }), - MMIO::ComplexWrite([this](Core::System&, u32, u32 val) { + MMIO::ComplexWrite([this](Core::System& system, u32, u32 val) { UEXI_STATUS new_status(val); m_status.EXIINTMASK = new_status.EXIINTMASK; @@ -91,7 +91,7 @@ void CEXIChannel::RegisterMMIO(MMIO::Mapping* mmio, u32 base) if (device != nullptr) device->SetCS(m_status.CHIP_SELECT); - ExpansionInterface::UpdateInterrupts(); + system.GetExpansionInterface().UpdateInterrupts(); })); mmio->Register(base + EXI_DMA_ADDRESS, MMIO::DirectRead(&m_dma_memory_address), @@ -160,7 +160,7 @@ void CEXIChannel::RegisterMMIO(MMIO::Mapping* mmio, u32 base) void CEXIChannel::SendTransferComplete() { m_status.TCINT = 1; - ExpansionInterface::UpdateInterrupts(); + m_system.GetExpansionInterface().UpdateInterrupts(); } void CEXIChannel::RemoveDevices() @@ -195,7 +195,7 @@ void CEXIChannel::AddDevice(std::unique_ptr device, const int device if (m_channel_id != 2) { m_status.EXTINT = 1; - ExpansionInterface::UpdateInterrupts(); + m_system.GetExpansionInterface().UpdateInterrupts(); } } } @@ -280,8 +280,8 @@ void CEXIChannel::DoState(PointerWrap& p) // the new device type are identical in this case. I assume there is a reason we have this // grace period when switching in the GUI. AddDevice(EXIDeviceType::None, device_index); - ExpansionInterface::ChangeDevice(m_channel_id, device_index, EXIDeviceType::MemoryCardFolder, - CoreTiming::FromThread::CPU); + m_system.GetExpansionInterface().ChangeDevice( + m_channel_id, device_index, EXIDeviceType::MemoryCardFolder, CoreTiming::FromThread::CPU); } } } diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceEthernet.cpp b/Source/Core/Core/HW/EXI/EXI_DeviceEthernet.cpp index 9d991b41e4a9..83134941dc1c 100644 --- a/Source/Core/Core/HW/EXI/EXI_DeviceEthernet.cpp +++ b/Source/Core/Core/HW/EXI/EXI_DeviceEthernet.cpp @@ -178,7 +178,7 @@ void CEXIETHERNET::ImmWrite(u32 data, u32 size) exi_status.interrupt_mask = data; break; } - ExpansionInterface::UpdateInterrupts(); + m_system.GetExpansionInterface().UpdateInterrupts(); } else { @@ -466,7 +466,7 @@ void CEXIETHERNET::SendComplete() mBbaMem[BBA_IR] |= INT_T; exi_status.interrupt |= exi_status.TRANSFER; - ExpansionInterface::ScheduleUpdateInterrupts(CoreTiming::FromThread::CPU, 0); + m_system.GetExpansionInterface().ScheduleUpdateInterrupts(CoreTiming::FromThread::CPU, 0); } mBbaMem[BBA_LTPS] = 0; @@ -637,7 +637,7 @@ bool CEXIETHERNET::RecvHandlePacket() mBbaMem[BBA_IR] |= INT_R; exi_status.interrupt |= exi_status.TRANSFER; - ExpansionInterface::ScheduleUpdateInterrupts(CoreTiming::FromThread::NON_CPU, 0); + m_system.GetExpansionInterface().ScheduleUpdateInterrupts(CoreTiming::FromThread::NON_CPU, 0); } else { diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceMemoryCard.cpp b/Source/Core/Core/HW/EXI/EXI_DeviceMemoryCard.cpp index 043299662f9a..8ddb996778f6 100644 --- a/Source/Core/Core/HW/EXI/EXI_DeviceMemoryCard.cpp +++ b/Source/Core/Core/HW/EXI/EXI_DeviceMemoryCard.cpp @@ -56,11 +56,11 @@ static Common::EnumMap s_card_short_names{'A', 'B'}; // Takes care of the nasty recovery of the 'this' pointer from card_slot, // stored in the userdata parameter of the CoreTiming event. -void CEXIMemoryCard::EventCompleteFindInstance(u64 userdata, +void CEXIMemoryCard::EventCompleteFindInstance(Core::System& system, u64 userdata, std::function callback) { Slot card_slot = static_cast(userdata); - IEXIDevice* self = ExpansionInterface::GetDevice(card_slot); + IEXIDevice* self = system.GetExpansionInterface().GetDevice(card_slot); if (self != nullptr) { if (self->m_device_type == EXIDeviceType::MemoryCard || @@ -73,12 +73,13 @@ void CEXIMemoryCard::EventCompleteFindInstance(u64 userdata, void CEXIMemoryCard::CmdDoneCallback(Core::System& system, u64 userdata, s64) { - EventCompleteFindInstance(userdata, [](CEXIMemoryCard* instance) { instance->CmdDone(); }); + EventCompleteFindInstance(system, userdata, + [](CEXIMemoryCard* instance) { instance->CmdDone(); }); } void CEXIMemoryCard::TransferCompleteCallback(Core::System& system, u64 userdata, s64) { - EventCompleteFindInstance(userdata, + EventCompleteFindInstance(system, userdata, [](CEXIMemoryCard* instance) { instance->TransferComplete(); }); } @@ -256,13 +257,14 @@ void CEXIMemoryCard::CmdDone() m_status &= ~MC_STATUS_BUSY; m_interrupt_set = true; - ExpansionInterface::UpdateInterrupts(); + m_system.GetExpansionInterface().UpdateInterrupts(); } void CEXIMemoryCard::TransferComplete() { // Transfer complete, send interrupt - ExpansionInterface::GetChannel(ExpansionInterface::SlotToEXIChannel(m_card_slot)) + m_system.GetExpansionInterface() + .GetChannel(ExpansionInterface::SlotToEXIChannel(m_card_slot)) ->SendTransferComplete(); } diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceMemoryCard.h b/Source/Core/Core/HW/EXI/EXI_DeviceMemoryCard.h index e793bfa5c004..b7772556e52f 100644 --- a/Source/Core/Core/HW/EXI/EXI_DeviceMemoryCard.h +++ b/Source/Core/Core/HW/EXI/EXI_DeviceMemoryCard.h @@ -59,7 +59,7 @@ class CEXIMemoryCard : public IEXIDevice private: void SetupGciFolder(const Memcard::HeaderData& header_data); void SetupRawMemcard(u16 size_mb); - static void EventCompleteFindInstance(u64 userdata, + static void EventCompleteFindInstance(Core::System& system, u64 userdata, std::function callback); // Scheduled when a command that required delayed end signaling is done. diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceMic.cpp b/Source/Core/Core/HW/EXI/EXI_DeviceMic.cpp index 3e8717593807..1bd3d00b35b6 100644 --- a/Source/Core/Core/HW/EXI/EXI_DeviceMic.cpp +++ b/Source/Core/Core/HW/EXI/EXI_DeviceMic.cpp @@ -266,7 +266,7 @@ void CEXIMic::UpdateNextInterruptTicks() { int diff = (SystemTimers::GetTicksPerSecond() / sample_rate) * buff_size_samples; next_int_ticks = m_system.GetCoreTiming().GetTicks() + diff; - ExpansionInterface::ScheduleUpdateInterrupts(CoreTiming::FromThread::CPU, diff); + m_system.GetExpansionInterface().ScheduleUpdateInterrupts(CoreTiming::FromThread::CPU, diff); } bool CEXIMic::IsInterruptSet() diff --git a/Source/Core/Core/HW/HW.cpp b/Source/Core/Core/HW/HW.cpp index f8eedc7eb1d2..471d48e9f446 100644 --- a/Source/Core/Core/HW/HW.cpp +++ b/Source/Core/Core/HW/HW.cpp @@ -44,11 +44,11 @@ void Init(const Sram* override_sram) VideoInterface::Init(); SerialInterface::Init(); system.GetProcessorInterface().Init(); - ExpansionInterface::Init(override_sram); // Needs to be initialized before Memory + system.GetExpansionInterface().Init(override_sram); // Needs to be initialized before Memory system.GetHSP().Init(); system.GetMemory().Init(); // Needs to be initialized before AddressSpace AddressSpace::Init(); - MemoryInterface::Init(); + system.GetMemoryInterface().Init(); system.GetDSP().Init(Config::Get(Config::MAIN_DSP_HLE)); system.GetDVDInterface().Init(); system.GetGPFifo().Init(); @@ -74,11 +74,11 @@ void Shutdown() system.GetCPU().Shutdown(); system.GetDVDInterface().Shutdown(); system.GetDSP().Shutdown(); - MemoryInterface::Shutdown(); + system.GetMemoryInterface().Shutdown(); AddressSpace::Shutdown(); system.GetMemory().Shutdown(); system.GetHSP().Shutdown(); - ExpansionInterface::Shutdown(); + system.GetExpansionInterface().Shutdown(); SerialInterface::Shutdown(); system.GetAudioInterface().Shutdown(); @@ -91,7 +91,7 @@ void DoState(PointerWrap& p) auto& system = Core::System::GetInstance(); system.GetMemory().DoState(p); p.DoMarker("Memory"); - MemoryInterface::DoState(p); + system.GetMemoryInterface().DoState(p); p.DoMarker("MemoryInterface"); VideoInterface::DoState(p); p.DoMarker("VideoInterface"); @@ -105,7 +105,7 @@ void DoState(PointerWrap& p) p.DoMarker("DVDInterface"); system.GetGPFifo().DoState(p); p.DoMarker("GPFifo"); - ExpansionInterface::DoState(p); + system.GetExpansionInterface().DoState(p); p.DoMarker("ExpansionInterface"); system.GetAudioInterface().DoState(p); p.DoMarker("AudioInterface"); diff --git a/Source/Core/Core/HW/Memmap.cpp b/Source/Core/Core/HW/Memmap.cpp index 50133c76cdc7..051822afab8f 100644 --- a/Source/Core/Core/HW/Memmap.cpp +++ b/Source/Core/Core/HW/Memmap.cpp @@ -53,18 +53,18 @@ void MemoryManager::InitMMIO(bool is_wii) system.GetPixelEngine().RegisterMMIO(m_mmio_mapping.get(), 0x0C001000); VideoInterface::RegisterMMIO(m_mmio_mapping.get(), 0x0C002000); system.GetProcessorInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0C003000); - MemoryInterface::RegisterMMIO(m_mmio_mapping.get(), 0x0C004000); + 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); SerialInterface::RegisterMMIO(m_mmio_mapping.get(), 0x0C006400); - ExpansionInterface::RegisterMMIO(m_mmio_mapping.get(), 0x0C006800); + system.GetExpansionInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0C006800); 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); SerialInterface::RegisterMMIO(m_mmio_mapping.get(), 0x0D006400); - ExpansionInterface::RegisterMMIO(m_mmio_mapping.get(), 0x0D006800); + system.GetExpansionInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0D006800); system.GetAudioInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0D006C00); } } diff --git a/Source/Core/Core/HW/MemoryInterface.cpp b/Source/Core/Core/HW/MemoryInterface.cpp index 62452bcde925..7bba5450feaa 100644 --- a/Source/Core/Core/HW/MemoryInterface.cpp +++ b/Source/Core/Core/HW/MemoryInterface.cpp @@ -11,7 +11,6 @@ #include "Common/ChunkFile.h" #include "Common/CommonTypes.h" #include "Core/HW/MMIO.h" -#include "Core/System.h" namespace MemoryInterface { @@ -55,166 +54,75 @@ enum MI_UNKNOWN2 = 0x05A, }; -union MIRegion -{ - u32 hex = 0; - struct - { - u16 first_page; - u16 last_page; - }; -}; - -union MIProtType -{ - u16 hex = 0; - - BitField<0, 2, u16> reg0; - BitField<2, 2, u16> reg1; - BitField<4, 2, u16> reg2; - BitField<6, 2, u16> reg3; - BitField<8, 8, u16> reserved; -}; - -union MIIRQMask -{ - u16 hex = 0; - - BitField<0, 1, u16> reg0; - BitField<1, 1, u16> reg1; - BitField<2, 1, u16> reg2; - BitField<3, 1, u16> reg3; - BitField<4, 1, u16> all_regs; - BitField<5, 11, u16> reserved; -}; - -union MIIRQFlag -{ - u16 hex = 0; - - BitField<0, 1, u16> reg0; - BitField<1, 1, u16> reg1; - BitField<2, 1, u16> reg2; - BitField<3, 1, u16> reg3; - BitField<4, 1, u16> all_regs; - BitField<5, 11, u16> reserved; -}; +MemoryInterfaceManager::MemoryInterfaceManager() = default; -union MIProtAddr -{ - u32 hex = 0; - struct - { - u16 lo; - u16 hi; - }; - BitField<0, 5, u32> reserved_1; - BitField<5, 25, u32> addr; - BitField<30, 2, u32> reserved_2; -}; +MemoryInterfaceManager::~MemoryInterfaceManager() = default; -union MITimer +void MemoryInterfaceManager::Init() { - u32 hex = 0; - struct - { - u16 lo; - u16 hi; - }; -}; - -struct MIMemStruct -{ - std::array regions; - MIProtType prot_type; - MIIRQMask irq_mask; - MIIRQFlag irq_flag; - u16 unknown1 = 0; - MIProtAddr prot_addr; - std::array timers; - u16 unknown2 = 0; -}; - -struct MemoryInterfaceState::Data -{ - MIMemStruct mi_mem; -}; - -MemoryInterfaceState::MemoryInterfaceState() : m_data(std::make_unique()) -{ -} - -MemoryInterfaceState::~MemoryInterfaceState() = default; - -void Init() -{ - auto& state = Core::System::GetInstance().GetMemoryInterfaceState().GetData(); static_assert(std::is_trivially_copyable_v); #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wclass-memaccess" #endif - std::memset(&state.mi_mem, 0, sizeof(MIMemStruct)); + std::memset(&m_mi_mem, 0, sizeof(MIMemStruct)); #ifdef __GNUC__ #pragma GCC diagnostic pop #endif } -void Shutdown() +void MemoryInterfaceManager::Shutdown() { Init(); } -void DoState(PointerWrap& p) +void MemoryInterfaceManager::DoState(PointerWrap& p) { - auto& state = Core::System::GetInstance().GetMemoryInterfaceState().GetData(); - p.Do(state.mi_mem); + p.Do(m_mi_mem); } -void RegisterMMIO(MMIO::Mapping* mmio, u32 base) +void MemoryInterfaceManager::RegisterMMIO(MMIO::Mapping* mmio, u32 base) { - auto& state = Core::System::GetInstance().GetMemoryInterfaceState().GetData(); - for (u32 i = MI_REGION0_FIRST; i <= MI_REGION3_LAST; i += 4) { - auto& region = state.mi_mem.regions[i / 4]; + auto& region = m_mi_mem.regions[i / 4]; mmio->Register(base | i, MMIO::DirectRead(®ion.first_page), MMIO::DirectWrite(®ion.first_page)); mmio->Register(base | (i + 2), MMIO::DirectRead(®ion.last_page), MMIO::DirectWrite(®ion.last_page)); } - mmio->Register(base | MI_PROT_TYPE, MMIO::DirectRead(&state.mi_mem.prot_type.hex), - MMIO::DirectWrite(&state.mi_mem.prot_type.hex)); + mmio->Register(base | MI_PROT_TYPE, MMIO::DirectRead(&m_mi_mem.prot_type.hex), + MMIO::DirectWrite(&m_mi_mem.prot_type.hex)); - mmio->Register(base | MI_IRQMASK, MMIO::DirectRead(&state.mi_mem.irq_mask.hex), - MMIO::DirectWrite(&state.mi_mem.irq_mask.hex)); + mmio->Register(base | MI_IRQMASK, MMIO::DirectRead(&m_mi_mem.irq_mask.hex), + MMIO::DirectWrite(&m_mi_mem.irq_mask.hex)); - mmio->Register(base | MI_IRQFLAG, MMIO::DirectRead(&state.mi_mem.irq_flag.hex), - MMIO::DirectWrite(&state.mi_mem.irq_flag.hex)); + mmio->Register(base | MI_IRQFLAG, MMIO::DirectRead(&m_mi_mem.irq_flag.hex), + MMIO::DirectWrite(&m_mi_mem.irq_flag.hex)); - mmio->Register(base | MI_UNKNOWN1, MMIO::DirectRead(&state.mi_mem.unknown1), - MMIO::DirectWrite(&state.mi_mem.unknown1)); + mmio->Register(base | MI_UNKNOWN1, MMIO::DirectRead(&m_mi_mem.unknown1), + MMIO::DirectWrite(&m_mi_mem.unknown1)); // The naming is confusing here: the register contains the lower part of // the address (hence MI_..._LO but this is still the high part of the // overall register. - mmio->Register(base | MI_PROT_ADDR_LO, MMIO::DirectRead(&state.mi_mem.prot_addr.hi), - MMIO::DirectWrite(&state.mi_mem.prot_addr.hi)); - mmio->Register(base | MI_PROT_ADDR_HI, MMIO::DirectRead(&state.mi_mem.prot_addr.lo), - MMIO::DirectWrite(&state.mi_mem.prot_addr.lo)); + mmio->Register(base | MI_PROT_ADDR_LO, MMIO::DirectRead(&m_mi_mem.prot_addr.hi), + MMIO::DirectWrite(&m_mi_mem.prot_addr.hi)); + mmio->Register(base | MI_PROT_ADDR_HI, MMIO::DirectRead(&m_mi_mem.prot_addr.lo), + MMIO::DirectWrite(&m_mi_mem.prot_addr.lo)); - for (u32 i = 0; i < state.mi_mem.timers.size(); ++i) + for (u32 i = 0; i < m_mi_mem.timers.size(); ++i) { - auto& timer = state.mi_mem.timers[i]; + auto& timer = m_mi_mem.timers[i]; mmio->Register(base | (MI_TIMER0_HI + 4 * i), MMIO::DirectRead(&timer.hi), MMIO::DirectWrite(&timer.hi)); mmio->Register(base | (MI_TIMER0_LO + 4 * i), MMIO::DirectRead(&timer.lo), MMIO::DirectWrite(&timer.lo)); } - mmio->Register(base | MI_UNKNOWN2, MMIO::DirectRead(&state.mi_mem.unknown2), - MMIO::DirectWrite(&state.mi_mem.unknown2)); + mmio->Register(base | MI_UNKNOWN2, MMIO::DirectRead(&m_mi_mem.unknown2), + MMIO::DirectWrite(&m_mi_mem.unknown2)); for (u32 i = 0; i < 0x1000; i += 4) { diff --git a/Source/Core/Core/HW/MemoryInterface.h b/Source/Core/Core/HW/MemoryInterface.h index e66b8a3f00f1..b96bc5120ce2 100644 --- a/Source/Core/Core/HW/MemoryInterface.h +++ b/Source/Core/Core/HW/MemoryInterface.h @@ -3,10 +3,16 @@ #pragma once +#include #include +#include "Common/BitField.h" #include "Common/CommonTypes.h" +namespace Core +{ +class System; +} namespace MMIO { class Mapping; @@ -15,26 +21,103 @@ class PointerWrap; namespace MemoryInterface { -class MemoryInterfaceState +class MemoryInterfaceManager { public: - MemoryInterfaceState(); - MemoryInterfaceState(const MemoryInterfaceState&) = delete; - MemoryInterfaceState(MemoryInterfaceState&&) = delete; - MemoryInterfaceState& operator=(const MemoryInterfaceState&) = delete; - MemoryInterfaceState& operator=(MemoryInterfaceState&&) = delete; - ~MemoryInterfaceState(); + MemoryInterfaceManager(); + MemoryInterfaceManager(const MemoryInterfaceManager&) = delete; + MemoryInterfaceManager(MemoryInterfaceManager&&) = delete; + MemoryInterfaceManager& operator=(const MemoryInterfaceManager&) = delete; + MemoryInterfaceManager& operator=(MemoryInterfaceManager&&) = delete; + ~MemoryInterfaceManager(); - struct Data; - Data& GetData() { return *m_data; } + void Init(); + void Shutdown(); + + void DoState(PointerWrap& p); + void RegisterMMIO(MMIO::Mapping* mmio, u32 base); private: - std::unique_ptr m_data; -}; + union MIRegion + { + u32 hex = 0; + struct + { + u16 first_page; + u16 last_page; + }; + }; + + union MIProtType + { + u16 hex = 0; + + BitField<0, 2, u16> reg0; + BitField<2, 2, u16> reg1; + BitField<4, 2, u16> reg2; + BitField<6, 2, u16> reg3; + BitField<8, 8, u16> reserved; + }; + + union MIIRQMask + { + u16 hex = 0; -void Init(); -void Shutdown(); + BitField<0, 1, u16> reg0; + BitField<1, 1, u16> reg1; + BitField<2, 1, u16> reg2; + BitField<3, 1, u16> reg3; + BitField<4, 1, u16> all_regs; + BitField<5, 11, u16> reserved; + }; -void DoState(PointerWrap& p); -void RegisterMMIO(MMIO::Mapping* mmio, u32 base); + union MIIRQFlag + { + u16 hex = 0; + + BitField<0, 1, u16> reg0; + BitField<1, 1, u16> reg1; + BitField<2, 1, u16> reg2; + BitField<3, 1, u16> reg3; + BitField<4, 1, u16> all_regs; + BitField<5, 11, u16> reserved; + }; + + union MIProtAddr + { + u32 hex = 0; + struct + { + u16 lo; + u16 hi; + }; + BitField<0, 5, u32> reserved_1; + BitField<5, 25, u32> addr; + BitField<30, 2, u32> reserved_2; + }; + + union MITimer + { + u32 hex = 0; + struct + { + u16 lo; + u16 hi; + }; + }; + + struct MIMemStruct + { + std::array regions; + MIProtType prot_type; + MIIRQMask irq_mask; + MIIRQFlag irq_flag; + u16 unknown1 = 0; + MIProtAddr prot_addr; + std::array timers; + u16 unknown2 = 0; + }; + + MIMemStruct m_mi_mem; +}; } // namespace MemoryInterface diff --git a/Source/Core/Core/System.cpp b/Source/Core/Core/System.cpp index 40260b8b9d40..3abe0fb1ea00 100644 --- a/Source/Core/Core/System.cpp +++ b/Source/Core/Core/System.cpp @@ -37,7 +37,8 @@ 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_gp_fifo(system), m_ppc_state(PowerPC::ppcState) + m_dvd_thread(system), m_expansion_interface(system), m_gp_fifo(system), + m_ppc_state(PowerPC::ppcState) { } @@ -52,14 +53,14 @@ struct System::Impl DSP::DSPManager m_dsp; DVD::DVDInterface m_dvd_interface; DVD::DVDThread m_dvd_thread; - ExpansionInterface::ExpansionInterfaceState m_expansion_interface_state; + ExpansionInterface::ExpansionInterfaceManager m_expansion_interface; Fifo::FifoManager m_fifo; GeometryShaderManager m_geometry_shader_manager; GPFifo::GPFifoManager m_gp_fifo; HSP::HSPManager m_hsp; IOS::HLE::USB::SkylanderPortal m_skylander_portal; Memory::MemoryManager m_memory; - MemoryInterface::MemoryInterfaceState m_memory_interface_state; + MemoryInterface::MemoryInterfaceManager m_memory_interface; PixelEngine::PixelEngineManager m_pixel_engine; PixelShaderManager m_pixel_shader_manager; PowerPC::PowerPCState& m_ppc_state; @@ -148,9 +149,9 @@ DVD::DVDThread& System::GetDVDThread() const return m_impl->m_dvd_thread; } -ExpansionInterface::ExpansionInterfaceState& System::GetExpansionInterfaceState() const +ExpansionInterface::ExpansionInterfaceManager& System::GetExpansionInterface() const { - return m_impl->m_expansion_interface_state; + return m_impl->m_expansion_interface; } Fifo::FifoManager& System::GetFifo() const @@ -183,9 +184,9 @@ Memory::MemoryManager& System::GetMemory() const return m_impl->m_memory; } -MemoryInterface::MemoryInterfaceState& System::GetMemoryInterfaceState() const +MemoryInterface::MemoryInterfaceManager& System::GetMemoryInterface() const { - return m_impl->m_memory_interface_state; + return m_impl->m_memory_interface; } PixelEngine::PixelEngineManager& System::GetPixelEngine() const diff --git a/Source/Core/Core/System.h b/Source/Core/Core/System.h index 847d108124c4..ae1ab518b802 100644 --- a/Source/Core/Core/System.h +++ b/Source/Core/Core/System.h @@ -38,7 +38,7 @@ class DVDThread; } // namespace DVD namespace ExpansionInterface { -class ExpansionInterfaceState; +class ExpansionInterfaceManager; }; namespace Fifo { @@ -62,7 +62,7 @@ class MemoryManager; }; namespace MemoryInterface { -class MemoryInterfaceState; +class MemoryInterfaceManager; }; namespace PixelEngine { @@ -126,14 +126,14 @@ class System DSP::DSPManager& GetDSP() const; DVD::DVDInterface& GetDVDInterface() const; DVD::DVDThread& GetDVDThread() const; - ExpansionInterface::ExpansionInterfaceState& GetExpansionInterfaceState() const; + ExpansionInterface::ExpansionInterfaceManager& GetExpansionInterface() const; Fifo::FifoManager& GetFifo() const; GeometryShaderManager& GetGeometryShaderManager() const; GPFifo::GPFifoManager& GetGPFifo() const; HSP::HSPManager& GetHSP() const; IOS::HLE::USB::SkylanderPortal& GetSkylanderPortal() const; Memory::MemoryManager& GetMemory() const; - MemoryInterface::MemoryInterfaceState& GetMemoryInterfaceState() const; + MemoryInterface::MemoryInterfaceManager& GetMemoryInterface() const; PixelEngine::PixelEngineManager& GetPixelEngine() const; PixelShaderManager& GetPixelShaderManager() const; PowerPC::PowerPCState& GetPPCState() const; diff --git a/Source/Core/DolphinQt/Settings/GameCubePane.cpp b/Source/Core/DolphinQt/Settings/GameCubePane.cpp index 7b7bac989d49..55510fd9f94f 100644 --- a/Source/Core/DolphinQt/Settings/GameCubePane.cpp +++ b/Source/Core/DolphinQt/Settings/GameCubePane.cpp @@ -32,6 +32,7 @@ #include "Core/HW/EXI/EXI.h" #include "Core/HW/GCMemcard/GCMemcard.h" #include "Core/NetPlayServer.h" +#include "Core/System.h" #include "DolphinQt/Config/Mapping/MappingWindow.h" #include "DolphinQt/GCMemcardManager.h" @@ -496,7 +497,8 @@ bool GameCubePane::SetMemcard(ExpansionInterface::Slot slot, const QString& file { // ChangeDevice unplugs the device for 1 second, which means that games should notice that // the path has changed and thus the memory card contents have changed - ExpansionInterface::ChangeDevice(slot, ExpansionInterface::EXIDeviceType::MemoryCard); + Core::System::GetInstance().GetExpansionInterface().ChangeDevice( + slot, ExpansionInterface::EXIDeviceType::MemoryCard); } } @@ -601,7 +603,8 @@ bool GameCubePane::SetGCIFolder(ExpansionInterface::Slot slot, const QString& pa { // ChangeDevice unplugs the device for 1 second, which means that games should notice that // the path has changed and thus the memory card contents have changed - ExpansionInterface::ChangeDevice(slot, ExpansionInterface::EXIDeviceType::MemoryCardFolder); + Core::System::GetInstance().GetExpansionInterface().ChangeDevice( + slot, ExpansionInterface::EXIDeviceType::MemoryCardFolder); } } @@ -637,7 +640,8 @@ void GameCubePane::SetAGPRom(ExpansionInterface::Slot slot, const QString& filen // cartridge without unplugging it, and it's not clear if the AGP software actually notices // that it's been unplugged or the cartridge has changed, but this was done for memcards so // we might as well do it for the AGP too. - ExpansionInterface::ChangeDevice(slot, ExpansionInterface::EXIDeviceType::AGP); + Core::System::GetInstance().GetExpansionInterface().ChangeDevice( + slot, ExpansionInterface::EXIDeviceType::AGP); } LoadSettings(); @@ -761,7 +765,7 @@ void GameCubePane::SaveSettings() if (Core::IsRunning() && current_exi_device != dev) { - ExpansionInterface::ChangeDevice(slot, dev); + Core::System::GetInstance().GetExpansionInterface().ChangeDevice(slot, dev); } Config::SetBaseOrCurrent(Config::GetInfoForEXIDevice(slot), dev);