System::ResultStatus System::Init(Frontend::EmuWindow& emu_window, u32 system_mode) { LOG_DEBUG(HW_Memory, "initialized OK"); memory = std::make_unique<Memory::MemorySystem>(); timing = std::make_unique<Timing>(); kernel = std::make_unique<Kernel::KernelSystem>(*memory, *timing, [this] { PrepareReschedule(); }, system_mode); if (Settings::values.use_cpu_jit) { #ifdef ARCHITECTURE_x86_64 cpu_core = std::make_unique<ARM_Dynarmic>(this, *memory, USER32MODE); #else cpu_core = std::make_unique<ARM_DynCom>(this, *memory, USER32MODE); LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available"); #endif } else { cpu_core = std::make_unique<ARM_DynCom>(this, *memory, USER32MODE); } kernel->GetThreadManager().SetCPU(*cpu_core); memory->SetCPU(*cpu_core); if (Settings::values.enable_dsp_lle) { dsp_core = std::make_unique<AudioCore::DspLle>(*memory, Settings::values.enable_dsp_lle_multithread); } else { dsp_core = std::make_unique<AudioCore::DspHle>(*memory); } memory->SetDSP(*dsp_core); dsp_core->SetSink(Settings::values.sink_id, Settings::values.audio_device_id); dsp_core->EnableStretching(Settings::values.enable_audio_stretching); telemetry_session = std::make_unique<Core::TelemetrySession>(); rpc_server = std::make_unique<RPC::RPCServer>(); service_manager = std::make_shared<Service::SM::ServiceManager>(*this); archive_manager = std::make_unique<Service::FS::ArchiveManager>(*this); HW::Init(*memory); Service::Init(*this); GDBStub::Init(); ResultStatus result = VideoCore::Init(emu_window, *memory); if (result != ResultStatus::Success) { return result; } LOG_DEBUG(Core, "Initialized OK"); // Reset counters and set time origin to current frame GetAndResetPerfStats(); perf_stats.BeginSystemFrame(); return ResultStatus::Success; }
System::ResultStatus System::RunLoop(bool tight_loop) { status = ResultStatus::Success; if (!cpu_core) { return ResultStatus::ErrorNotInitialized; } if (GDBStub::IsServerEnabled()) { GDBStub::HandlePacket(); // If the loop is halted and we want to step, use a tiny (1) number of instructions to // execute. Otherwise, get out of the loop function. if (GDBStub::GetCpuHaltFlag()) { if (GDBStub::GetCpuStepFlag()) { tight_loop = false; } else { return ResultStatus::Success; } } } // If we don't have a currently active thread then don't execute instructions, // instead advance to the next event and try to yield to the next thread if (kernel->GetThreadManager().GetCurrentThread() == nullptr) { LOG_TRACE(Core_ARM11, "Idling"); timing->Idle(); timing->Advance(); PrepareReschedule(); } else { timing->Advance(); if (tight_loop) { cpu_core->Run(); } else { cpu_core->Step(); } } if (GDBStub::IsServerEnabled()) { GDBStub::SetCpuStepFlag(false); } HW::Update(); Reschedule(); if (reset_requested.exchange(false)) { Reset(); } else if (shutdown_requested.exchange(false)) { return ResultStatus::ShutdownRequested; } return status; }
System::ResultStatus System::RunLoop(int tight_loop) { status = ResultStatus::Success; if (!cpu_core) { return ResultStatus::ErrorNotInitialized; } if (GDBStub::IsServerEnabled()) { GDBStub::HandlePacket(); // If the loop is halted and we want to step, use a tiny (1) number of instructions to // execute. Otherwise, get out of the loop function. if (GDBStub::GetCpuHaltFlag()) { if (GDBStub::GetCpuStepFlag()) { GDBStub::SetCpuStepFlag(false); tight_loop = 1; } else { return ResultStatus::Success; } } } // If we don't have a currently active thread then don't execute instructions, // instead advance to the next event and try to yield to the next thread if (Kernel::GetCurrentThread() == nullptr) { LOG_TRACE(Core_ARM11, "Idling"); CoreTiming::Idle(); CoreTiming::Advance(); PrepareReschedule(); } else { cpu_core->Run(tight_loop); } HW::Update(); Reschedule(); return status; }