diff options
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/hle/kernel/memory.cpp | 5 | ||||
| -rw-r--r-- | src/core/hle/service/dsp_dsp.cpp | 135 | ||||
| -rw-r--r-- | src/core/hle/service/dsp_dsp.h | 12 | ||||
| -rw-r--r-- | src/core/hw/gpu.cpp | 6 | ||||
| -rw-r--r-- | src/core/system.cpp | 7 |
5 files changed, 99 insertions, 66 deletions
diff --git a/src/core/hle/kernel/memory.cpp b/src/core/hle/kernel/memory.cpp index 0cfb43fc7..862643448 100644 --- a/src/core/hle/kernel/memory.cpp +++ b/src/core/hle/kernel/memory.cpp | |||
| @@ -7,6 +7,8 @@ | |||
| 7 | #include <utility> | 7 | #include <utility> |
| 8 | #include <vector> | 8 | #include <vector> |
| 9 | 9 | ||
| 10 | #include "audio_core/audio_core.h" | ||
| 11 | |||
| 10 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 11 | #include "common/logging/log.h" | 13 | #include "common/logging/log.h" |
| 12 | 14 | ||
| @@ -107,7 +109,6 @@ struct MemoryArea { | |||
| 107 | static MemoryArea memory_areas[] = { | 109 | static MemoryArea memory_areas[] = { |
| 108 | {SHARED_MEMORY_VADDR, SHARED_MEMORY_SIZE, "Shared Memory"}, // Shared memory | 110 | {SHARED_MEMORY_VADDR, SHARED_MEMORY_SIZE, "Shared Memory"}, // Shared memory |
| 109 | {VRAM_VADDR, VRAM_SIZE, "VRAM"}, // Video memory (VRAM) | 111 | {VRAM_VADDR, VRAM_SIZE, "VRAM"}, // Video memory (VRAM) |
| 110 | {DSP_RAM_VADDR, DSP_RAM_SIZE, "DSP RAM"}, // DSP memory | ||
| 111 | {TLS_AREA_VADDR, TLS_AREA_SIZE, "TLS Area"}, // TLS memory | 112 | {TLS_AREA_VADDR, TLS_AREA_SIZE, "TLS Area"}, // TLS memory |
| 112 | }; | 113 | }; |
| 113 | 114 | ||
| @@ -133,6 +134,8 @@ void InitLegacyAddressSpace(Kernel::VMManager& address_space) { | |||
| 133 | auto shared_page_vma = address_space.MapBackingMemory(SHARED_PAGE_VADDR, | 134 | auto shared_page_vma = address_space.MapBackingMemory(SHARED_PAGE_VADDR, |
| 134 | (u8*)&SharedPage::shared_page, SHARED_PAGE_SIZE, MemoryState::Shared).MoveFrom(); | 135 | (u8*)&SharedPage::shared_page, SHARED_PAGE_SIZE, MemoryState::Shared).MoveFrom(); |
| 135 | address_space.Reprotect(shared_page_vma, VMAPermission::Read); | 136 | address_space.Reprotect(shared_page_vma, VMAPermission::Read); |
| 137 | |||
| 138 | AudioCore::AddAddressSpace(address_space); | ||
| 136 | } | 139 | } |
| 137 | 140 | ||
| 138 | } // namespace | 141 | } // namespace |
diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp index f9f931f6d..15d3274ec 100644 --- a/src/core/hle/service/dsp_dsp.cpp +++ b/src/core/hle/service/dsp_dsp.cpp | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "audio_core/hle/pipe.h" | ||
| 6 | |||
| 5 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 6 | 8 | ||
| 7 | #include "core/hle/kernel/event.h" | 9 | #include "core/hle/kernel/event.h" |
| @@ -14,17 +16,30 @@ namespace DSP_DSP { | |||
| 14 | 16 | ||
| 15 | static u32 read_pipe_count; | 17 | static u32 read_pipe_count; |
| 16 | static Kernel::SharedPtr<Kernel::Event> semaphore_event; | 18 | static Kernel::SharedPtr<Kernel::Event> semaphore_event; |
| 17 | static Kernel::SharedPtr<Kernel::Event> interrupt_event; | ||
| 18 | 19 | ||
| 19 | void SignalInterrupt() { | 20 | struct PairHash { |
| 20 | // TODO(bunnei): This is just a stub, it does not do anything other than signal to the emulated | 21 | template <typename T, typename U> |
| 21 | // application that a DSP interrupt occurred, without specifying which one. Since we do not | 22 | std::size_t operator()(const std::pair<T, U> &x) const { |
| 22 | // emulate the DSP yet (and how it works is largely unknown), this is a work around to get games | 23 | // TODO(yuriks): Replace with better hash combining function. |
| 23 | // that check the DSP interrupt signal event to run. We should figure out the different types of | 24 | return std::hash<T>()(x.first) ^ std::hash<U>()(x.second); |
| 24 | // DSP interrupts, and trigger them at the appropriate times. | 25 | } |
| 26 | }; | ||
| 27 | |||
| 28 | /// Map of (audio interrupt number, channel number) to Kernel::Events. See: RegisterInterruptEvents | ||
| 29 | static std::unordered_map<std::pair<u32, u32>, Kernel::SharedPtr<Kernel::Event>, PairHash> interrupt_events; | ||
| 30 | |||
| 31 | // DSP Interrupts: | ||
| 32 | // Interrupt #2 occurs every frame tick. Userland programs normally have a thread that's waiting | ||
| 33 | // for an interrupt event. Immediately after this interrupt event, userland normally updates the | ||
| 34 | // state in the next region and increments the relevant frame counter by two. | ||
| 35 | void SignalAllInterrupts() { | ||
| 36 | // HACK: The other interrupts have currently unknown purpose, we trigger them each tick in any case. | ||
| 37 | for (auto& interrupt_event : interrupt_events) | ||
| 38 | interrupt_event.second->Signal(); | ||
| 39 | } | ||
| 25 | 40 | ||
| 26 | if (interrupt_event != 0) | 41 | void SignalInterrupt(u32 interrupt, u32 channel) { |
| 27 | interrupt_event->Signal(); | 42 | interrupt_events[std::make_pair(interrupt, channel)]->Signal(); |
| 28 | } | 43 | } |
| 29 | 44 | ||
| 30 | /** | 45 | /** |
| @@ -43,7 +58,7 @@ static void ConvertProcessAddressFromDspDram(Service::Interface* self) { | |||
| 43 | cmd_buff[1] = 0; // No error | 58 | cmd_buff[1] = 0; // No error |
| 44 | cmd_buff[2] = (addr << 1) + (Memory::DSP_RAM_VADDR + 0x40000); | 59 | cmd_buff[2] = (addr << 1) + (Memory::DSP_RAM_VADDR + 0x40000); |
| 45 | 60 | ||
| 46 | LOG_WARNING(Service_DSP, "(STUBBED) called with address 0x%08X", addr); | 61 | LOG_TRACE(Service_DSP, "addr=0x%08X", addr); |
| 47 | } | 62 | } |
| 48 | 63 | ||
| 49 | /** | 64 | /** |
| @@ -121,8 +136,8 @@ static void FlushDataCache(Service::Interface* self) { | |||
| 121 | /** | 136 | /** |
| 122 | * DSP_DSP::RegisterInterruptEvents service function | 137 | * DSP_DSP::RegisterInterruptEvents service function |
| 123 | * Inputs: | 138 | * Inputs: |
| 124 | * 1 : Parameter 0 (purpose unknown) | 139 | * 1 : Interrupt Number |
| 125 | * 2 : Parameter 1 (purpose unknown) | 140 | * 2 : Channel Number |
| 126 | * 4 : Interrupt event handle | 141 | * 4 : Interrupt event handle |
| 127 | * Outputs: | 142 | * Outputs: |
| 128 | * 1 : Result of function, 0 on success, otherwise error code | 143 | * 1 : Result of function, 0 on success, otherwise error code |
| @@ -130,22 +145,24 @@ static void FlushDataCache(Service::Interface* self) { | |||
| 130 | static void RegisterInterruptEvents(Service::Interface* self) { | 145 | static void RegisterInterruptEvents(Service::Interface* self) { |
| 131 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 146 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 132 | 147 | ||
| 133 | u32 param0 = cmd_buff[1]; | 148 | u32 interrupt = cmd_buff[1]; |
| 134 | u32 param1 = cmd_buff[2]; | 149 | u32 channel = cmd_buff[2]; |
| 135 | u32 event_handle = cmd_buff[4]; | 150 | u32 event_handle = cmd_buff[4]; |
| 136 | 151 | ||
| 137 | auto evt = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[4]); | 152 | if (event_handle) { |
| 138 | if (evt != nullptr) { | 153 | auto evt = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[4]); |
| 139 | interrupt_event = evt; | 154 | if (evt) { |
| 140 | cmd_buff[1] = 0; // No error | 155 | interrupt_events[std::make_pair(interrupt, channel)] = evt; |
| 156 | cmd_buff[1] = RESULT_SUCCESS.raw; | ||
| 157 | LOG_WARNING(Service_DSP, "Registered interrupt=%u, channel=%u, event_handle=0x%08X", interrupt, channel, event_handle); | ||
| 158 | } else { | ||
| 159 | cmd_buff[1] = -1; | ||
| 160 | LOG_ERROR(Service_DSP, "Invalid event handle! interrupt=%u, channel=%u, event_handle=0x%08X", interrupt, channel, event_handle); | ||
| 161 | } | ||
| 141 | } else { | 162 | } else { |
| 142 | LOG_ERROR(Service_DSP, "called with invalid handle=%08X", cmd_buff[4]); | 163 | interrupt_events.erase(std::make_pair(interrupt, channel)); |
| 143 | 164 | LOG_WARNING(Service_DSP, "Unregistered interrupt=%u, channel=%u, event_handle=0x%08X", interrupt, channel, event_handle); | |
| 144 | // TODO(yuriks): An error should be returned from SendSyncRequest, not in the cmdbuf | ||
| 145 | cmd_buff[1] = -1; | ||
| 146 | } | 165 | } |
| 147 | |||
| 148 | LOG_WARNING(Service_DSP, "(STUBBED) called param0=%u, param1=%u, event_handle=0x%08X", param0, param1, event_handle); | ||
| 149 | } | 166 | } |
| 150 | 167 | ||
| 151 | /** | 168 | /** |
| @@ -158,8 +175,6 @@ static void RegisterInterruptEvents(Service::Interface* self) { | |||
| 158 | static void SetSemaphore(Service::Interface* self) { | 175 | static void SetSemaphore(Service::Interface* self) { |
| 159 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 176 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 160 | 177 | ||
| 161 | SignalInterrupt(); | ||
| 162 | |||
| 163 | cmd_buff[1] = 0; // No error | 178 | cmd_buff[1] = 0; // No error |
| 164 | 179 | ||
| 165 | LOG_WARNING(Service_DSP, "(STUBBED) called"); | 180 | LOG_WARNING(Service_DSP, "(STUBBED) called"); |
| @@ -168,9 +183,9 @@ static void SetSemaphore(Service::Interface* self) { | |||
| 168 | /** | 183 | /** |
| 169 | * DSP_DSP::WriteProcessPipe service function | 184 | * DSP_DSP::WriteProcessPipe service function |
| 170 | * Inputs: | 185 | * Inputs: |
| 171 | * 1 : Number | 186 | * 1 : Channel |
| 172 | * 2 : Size | 187 | * 2 : Size |
| 173 | * 3 : (size <<14) | 0x402 | 188 | * 3 : (size << 14) | 0x402 |
| 174 | * 4 : Buffer | 189 | * 4 : Buffer |
| 175 | * Outputs: | 190 | * Outputs: |
| 176 | * 0 : Return header | 191 | * 0 : Return header |
| @@ -179,21 +194,42 @@ static void SetSemaphore(Service::Interface* self) { | |||
| 179 | static void WriteProcessPipe(Service::Interface* self) { | 194 | static void WriteProcessPipe(Service::Interface* self) { |
| 180 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 195 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 181 | 196 | ||
| 182 | u32 number = cmd_buff[1]; | 197 | u32 channel = cmd_buff[1]; |
| 183 | u32 size = cmd_buff[2]; | 198 | u32 size = cmd_buff[2]; |
| 184 | u32 new_size = cmd_buff[3]; | ||
| 185 | u32 buffer = cmd_buff[4]; | 199 | u32 buffer = cmd_buff[4]; |
| 186 | 200 | ||
| 201 | if (IPC::StaticBufferDesc(size, 1) != cmd_buff[3]) { | ||
| 202 | LOG_ERROR(Service_DSP, "IPC static buffer descriptor failed validation (0x%X). channel=%u, size=0x%X, buffer=0x%08X", cmd_buff[3], channel, size, buffer); | ||
| 203 | cmd_buff[1] = -1; // TODO | ||
| 204 | return; | ||
| 205 | } | ||
| 206 | |||
| 207 | if (!Memory::GetPointer(buffer)) { | ||
| 208 | LOG_ERROR(Service_DSP, "Invalid Buffer: channel=%u, size=0x%X, buffer=0x%08X", channel, size, buffer); | ||
| 209 | cmd_buff[1] = -1; // TODO | ||
| 210 | return; | ||
| 211 | } | ||
| 212 | |||
| 213 | std::vector<u8> message(size); | ||
| 214 | |||
| 215 | for (size_t i = 0; i < size; i++) { | ||
| 216 | message[i] = Memory::Read8(buffer + i); | ||
| 217 | } | ||
| 218 | |||
| 219 | DSP::HLE::PipeWrite(channel, message); | ||
| 220 | |||
| 187 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 221 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 188 | 222 | ||
| 189 | LOG_WARNING(Service_DSP, "(STUBBED) called number=%u, size=0x%X, new_size=0x%X, buffer=0x%08X", | 223 | LOG_TRACE(Service_DSP, "channel=%u, size=0x%X, buffer=0x%08X", channel, size, buffer); |
| 190 | number, size, new_size, buffer); | ||
| 191 | } | 224 | } |
| 192 | 225 | ||
| 193 | /** | 226 | /** |
| 194 | * DSP_DSP::ReadPipeIfPossible service function | 227 | * DSP_DSP::ReadPipeIfPossible service function |
| 228 | * A pipe is a means of communication between the ARM11 and DSP that occurs on | ||
| 229 | * hardware by writing to/reading from the DSP registers at 0x10203000. | ||
| 230 | * Pipes are used for initialisation. See also DSP::HLE::PipeRead. | ||
| 195 | * Inputs: | 231 | * Inputs: |
| 196 | * 1 : Unknown | 232 | * 1 : Pipe Number |
| 197 | * 2 : Unknown | 233 | * 2 : Unknown |
| 198 | * 3 : Size in bytes of read (observed only lower half word used) | 234 | * 3 : Size in bytes of read (observed only lower half word used) |
| 199 | * 0x41 : Virtual address to read from DSP pipe to in memory | 235 | * 0x41 : Virtual address to read from DSP pipe to in memory |
| @@ -204,35 +240,25 @@ static void WriteProcessPipe(Service::Interface* self) { | |||
| 204 | static void ReadPipeIfPossible(Service::Interface* self) { | 240 | static void ReadPipeIfPossible(Service::Interface* self) { |
| 205 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 241 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 206 | 242 | ||
| 207 | u32 unk1 = cmd_buff[1]; | 243 | u32 pipe = cmd_buff[1]; |
| 208 | u32 unk2 = cmd_buff[2]; | 244 | u32 unk2 = cmd_buff[2]; |
| 209 | u32 size = cmd_buff[3] & 0xFFFF;// Lower 16 bits are size | 245 | u32 size = cmd_buff[3] & 0xFFFF;// Lower 16 bits are size |
| 210 | VAddr addr = cmd_buff[0x41]; | 246 | VAddr addr = cmd_buff[0x41]; |
| 211 | 247 | ||
| 212 | // Canned DSP responses that games expect. These were taken from HW by 3dmoo team. | 248 | if (!Memory::GetPointer(addr)) { |
| 213 | // TODO: Remove this hack :) | 249 | LOG_ERROR(Service_DSP, "Invalid addr: pipe=0x%08X, unk2=0x%08X, size=0x%X, buffer=0x%08X", pipe, unk2, size, addr); |
| 214 | static const std::array<u16, 16> canned_read_pipe = {{ | 250 | cmd_buff[1] = -1; // TODO |
| 215 | 0x000F, 0xBFFF, 0x9E8E, 0x8680, 0xA78E, 0x9430, 0x8400, 0x8540, | 251 | return; |
| 216 | 0x948E, 0x8710, 0x8410, 0xA90E, 0xAA0E, 0xAACE, 0xAC4E, 0xAC58 | 252 | } |
| 217 | }}; | ||
| 218 | 253 | ||
| 219 | u32 initial_size = read_pipe_count; | 254 | std::vector<u8> response = DSP::HLE::PipeRead(pipe, size); |
| 220 | 255 | ||
| 221 | for (unsigned offset = 0; offset < size; offset += sizeof(u16)) { | 256 | Memory::WriteBlock(addr, response.data(), response.size()); |
| 222 | if (read_pipe_count < canned_read_pipe.size()) { | ||
| 223 | Memory::Write16(addr + offset, canned_read_pipe[read_pipe_count]); | ||
| 224 | read_pipe_count++; | ||
| 225 | } else { | ||
| 226 | LOG_ERROR(Service_DSP, "canned read pipe log exceeded!"); | ||
| 227 | break; | ||
| 228 | } | ||
| 229 | } | ||
| 230 | 257 | ||
| 231 | cmd_buff[1] = 0; // No error | 258 | cmd_buff[1] = 0; // No error |
| 232 | cmd_buff[2] = (read_pipe_count - initial_size) * sizeof(u16); | 259 | cmd_buff[2] = (u32)response.size(); |
| 233 | 260 | ||
| 234 | LOG_WARNING(Service_DSP, "(STUBBED) called unk1=0x%08X, unk2=0x%08X, size=0x%X, buffer=0x%08X", | 261 | LOG_TRACE(Service_DSP, "pipe=0x%08X, unk2=0x%08X, size=0x%X, buffer=0x%08X", pipe, unk2, size, addr); |
| 235 | unk1, unk2, size, addr); | ||
| 236 | } | 262 | } |
| 237 | 263 | ||
| 238 | /** | 264 | /** |
| @@ -311,7 +337,6 @@ const Interface::FunctionInfo FunctionTable[] = { | |||
| 311 | 337 | ||
| 312 | Interface::Interface() { | 338 | Interface::Interface() { |
| 313 | semaphore_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "DSP_DSP::semaphore_event"); | 339 | semaphore_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "DSP_DSP::semaphore_event"); |
| 314 | interrupt_event = nullptr; | ||
| 315 | read_pipe_count = 0; | 340 | read_pipe_count = 0; |
| 316 | 341 | ||
| 317 | Register(FunctionTable); | 342 | Register(FunctionTable); |
| @@ -319,7 +344,7 @@ Interface::Interface() { | |||
| 319 | 344 | ||
| 320 | Interface::~Interface() { | 345 | Interface::~Interface() { |
| 321 | semaphore_event = nullptr; | 346 | semaphore_event = nullptr; |
| 322 | interrupt_event = nullptr; | 347 | interrupt_events.clear(); |
| 323 | } | 348 | } |
| 324 | 349 | ||
| 325 | } // namespace | 350 | } // namespace |
diff --git a/src/core/hle/service/dsp_dsp.h b/src/core/hle/service/dsp_dsp.h index b6f611db5..32b89e9bb 100644 --- a/src/core/hle/service/dsp_dsp.h +++ b/src/core/hle/service/dsp_dsp.h | |||
| @@ -23,7 +23,15 @@ public: | |||
| 23 | } | 23 | } |
| 24 | }; | 24 | }; |
| 25 | 25 | ||
| 26 | /// Signals that a DSP interrupt has occurred to userland code | 26 | /// Signal all audio related interrupts. |
| 27 | void SignalInterrupt(); | 27 | void SignalAllInterrupts(); |
| 28 | |||
| 29 | /** | ||
| 30 | * Signal a specific audio related interrupt based on interrupt id and channel id. | ||
| 31 | * @param interrupt_id The interrupt id | ||
| 32 | * @param channel_id The channel id | ||
| 33 | * The significance of various values of interrupt_id and channel_id is not yet known. | ||
| 34 | */ | ||
| 35 | void SignalInterrupt(u32 interrupt_id, u32 channel_id); | ||
| 28 | 36 | ||
| 29 | } // namespace | 37 | } // namespace |
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp index c60310586..5312baa83 100644 --- a/src/core/hw/gpu.cpp +++ b/src/core/hw/gpu.cpp | |||
| @@ -17,7 +17,6 @@ | |||
| 17 | #include "core/core_timing.h" | 17 | #include "core/core_timing.h" |
| 18 | 18 | ||
| 19 | #include "core/hle/service/gsp_gpu.h" | 19 | #include "core/hle/service/gsp_gpu.h" |
| 20 | #include "core/hle/service/dsp_dsp.h" | ||
| 21 | #include "core/hle/service/hid/hid.h" | 20 | #include "core/hle/service/hid/hid.h" |
| 22 | 21 | ||
| 23 | #include "core/hw/hw.h" | 22 | #include "core/hw/hw.h" |
| @@ -414,11 +413,6 @@ static void VBlankCallback(u64 userdata, int cycles_late) { | |||
| 414 | GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC0); | 413 | GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC0); |
| 415 | GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC1); | 414 | GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC1); |
| 416 | 415 | ||
| 417 | // TODO(bunnei): Fake a DSP interrupt on each frame. This does not belong here, but | ||
| 418 | // until we can emulate DSP interrupts, this is probably the only reasonable place to do | ||
| 419 | // this. Certain games expect this to be periodically signaled. | ||
| 420 | DSP_DSP::SignalInterrupt(); | ||
| 421 | |||
| 422 | // Check for user input updates | 416 | // Check for user input updates |
| 423 | Service::HID::Update(); | 417 | Service::HID::Update(); |
| 424 | 418 | ||
diff --git a/src/core/system.cpp b/src/core/system.cpp index 7e9c56538..b62ebf69e 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp | |||
| @@ -2,9 +2,12 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "audio_core/audio_core.h" | ||
| 6 | |||
| 5 | #include "core/core.h" | 7 | #include "core/core.h" |
| 6 | #include "core/core_timing.h" | 8 | #include "core/core_timing.h" |
| 7 | #include "core/system.h" | 9 | #include "core/system.h" |
| 10 | #include "core/gdbstub/gdbstub.h" | ||
| 8 | #include "core/hw/hw.h" | 11 | #include "core/hw/hw.h" |
| 9 | #include "core/hle/hle.h" | 12 | #include "core/hle/hle.h" |
| 10 | #include "core/hle/kernel/kernel.h" | 13 | #include "core/hle/kernel/kernel.h" |
| @@ -12,8 +15,6 @@ | |||
| 12 | 15 | ||
| 13 | #include "video_core/video_core.h" | 16 | #include "video_core/video_core.h" |
| 14 | 17 | ||
| 15 | #include "core/gdbstub/gdbstub.h" | ||
| 16 | |||
| 17 | namespace System { | 18 | namespace System { |
| 18 | 19 | ||
| 19 | void Init(EmuWindow* emu_window) { | 20 | void Init(EmuWindow* emu_window) { |
| @@ -24,11 +25,13 @@ void Init(EmuWindow* emu_window) { | |||
| 24 | Kernel::Init(); | 25 | Kernel::Init(); |
| 25 | HLE::Init(); | 26 | HLE::Init(); |
| 26 | VideoCore::Init(emu_window); | 27 | VideoCore::Init(emu_window); |
| 28 | AudioCore::Init(); | ||
| 27 | GDBStub::Init(); | 29 | GDBStub::Init(); |
| 28 | } | 30 | } |
| 29 | 31 | ||
| 30 | void Shutdown() { | 32 | void Shutdown() { |
| 31 | GDBStub::Shutdown(); | 33 | GDBStub::Shutdown(); |
| 34 | AudioCore::Shutdown(); | ||
| 32 | VideoCore::Shutdown(); | 35 | VideoCore::Shutdown(); |
| 33 | HLE::Shutdown(); | 36 | HLE::Shutdown(); |
| 34 | Kernel::Shutdown(); | 37 | Kernel::Shutdown(); |