0
0
mirror of https://notabug.org/litucks/torzu.git synced 2025-04-24 09:05:13 +00:00

Update some Android dependencies and fix build by making boost-process optional (#120)

Based on #119

Co-authored-by: Ramiro <ramiro.depaoli@gmail.com>
Co-authored-by: spectranator <spectranator@y2nlvhmmk5jnsvechppxnbyzmmv3vbl7dvzn6ltwcdbpgxixp3clkgqd.onion>
Reviewed-on: http://vub63vv26q6v27xzv2dtcd25xumubshogm67yrpaz2rculqxs7jlfqad.onion/torzu-emu/torzu/pulls/120
This commit is contained in:
spectranator 2025-04-16 19:47:40 +00:00
parent 8561b75518
commit 634acab40b
20 changed files with 203 additions and 100 deletions

View File

@ -63,6 +63,8 @@ option(ENABLE_CUBEB "Enables the cubeb audio backend" ON)
option(USE_DISCORD_PRESENCE "Enables Discord Rich Presence" OFF) option(USE_DISCORD_PRESENCE "Enables Discord Rich Presence" OFF)
option(YUZU_NO_CPU_DEBUGGER "Do not build debugging code" OFF)
option(YUZU_TESTS "Compile tests" "${BUILD_TESTING}") option(YUZU_TESTS "Compile tests" "${BUILD_TESTING}")
option(YUZU_USE_PRECOMPILED_HEADERS "Use precompiled headers" ON) option(YUZU_USE_PRECOMPILED_HEADERS "Use precompiled headers" ON)
@ -170,7 +172,7 @@ endif()
option(ENABLE_OPENSSL "Enable OpenSSL backend for ISslConnection" ${DEFAULT_ENABLE_OPENSSL}) option(ENABLE_OPENSSL "Enable OpenSSL backend for ISslConnection" ${DEFAULT_ENABLE_OPENSSL})
if (ANDROID AND YUZU_DOWNLOAD_ANDROID_VVL) if (ANDROID AND YUZU_DOWNLOAD_ANDROID_VVL)
set(vvl_version "sdk-1.3.261.1") set(vvl_version "1.4.304.1")
set(vvl_zip_file "${CMAKE_BINARY_DIR}/externals/vvl-android.zip") set(vvl_zip_file "${CMAKE_BINARY_DIR}/externals/vvl-android.zip")
set(vvl_lib_path "${CMAKE_CURRENT_SOURCE_DIR}/src/android/app/src/main/jniLibs/arm64-v8a/") set(vvl_lib_path "${CMAKE_CURRENT_SOURCE_DIR}/src/android/app/src/main/jniLibs/arm64-v8a/")

View File

@ -44,9 +44,9 @@ https://developer.android.com/studio/intro
### Dependencies ### Dependencies
``` ```
sudo apt-get update sudo apt-get update
sudo apt-get install -y sdkmanager openjdk-17-jdk build-essential curl git pkg-config glslang-tools zip sudo apt-get install -y sdkmanager openjdk-21-jdk build-essential curl git pkg-config glslang-tools zip
sudo sdkmanager "ndk;26.3.11579264" "platforms;android-34" "build-tools;34.0.0" "cmake;3.22.1" "platform-tools;34.0.5" sudo sdkmanager "ndk;26.3.11579264" "platforms;android-35" "build-tools;35.0.0" "cmake;3.22.1" "platform-tools;35.0.5"
sudo update-alternatives --config java # Select Java 17 here if possible sudo update-alternatives --config java # Select Java 21 here if possible
``` ```
### Cloning Yuzu with Git ### Cloning Yuzu with Git

View File

@ -27,7 +27,7 @@ val autoVersion = (((System.currentTimeMillis() / 1000) - 1451606400) / 10).toIn
android { android {
namespace = "org.yuzu.yuzu_emu" namespace = "org.yuzu.yuzu_emu"
compileSdkVersion = "android-34" compileSdkVersion = "android-35"
ndkVersion = "26.3.11579264" ndkVersion = "26.3.11579264"
buildFeatures { buildFeatures {
@ -35,12 +35,12 @@ android {
} }
compileOptions { compileOptions {
sourceCompatibility = JavaVersion.VERSION_17 sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_21
} }
kotlinOptions { kotlinOptions {
jvmTarget = "17" jvmTarget = "21"
} }
packaging { packaging {
@ -118,7 +118,6 @@ android {
isDefault = true isDefault = true
resValue("string", "app_name_suffixed", "yuzu Debug Release") resValue("string", "app_name_suffixed", "yuzu Debug Release")
signingConfig = signingConfigs.getByName("default") signingConfig = signingConfigs.getByName("default")
isMinifyEnabled = true
isDebuggable = true isDebuggable = true
proguardFiles( proguardFiles(
getDefaultProguardFile("proguard-android.txt"), getDefaultProguardFile("proguard-android.txt"),
@ -165,9 +164,10 @@ android {
"-DENABLE_WEB_SERVICE=0", // Don't use telemetry "-DENABLE_WEB_SERVICE=0", // Don't use telemetry
"-DBUNDLE_SPEEX=ON", "-DBUNDLE_SPEEX=ON",
"-DANDROID_ARM_NEON=true", // cryptopp requires Neon to work "-DANDROID_ARM_NEON=true", // cryptopp requires Neon to work
"-DYUZU_NO_CPU_DEBUGGER=ON",
"-DYUZU_ENABLE_LTO=ON",
"-DYUZU_USE_BUNDLED_VCPKG=ON", "-DYUZU_USE_BUNDLED_VCPKG=ON",
"-DYUZU_USE_BUNDLED_FFMPEG=ON", "-DYUZU_USE_BUNDLED_FFMPEG=ON",
"-DYUZU_ENABLE_LTO=ON",
"-DCMAKE_EXPORT_COMPILE_COMMANDS=ON" "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
) )

View File

@ -297,7 +297,9 @@ void EmulationSession::ShutdownEmulation() {
// Shutdown the main emulated process // Shutdown the main emulated process
if (m_load_result == Core::SystemResultStatus::Success) { if (m_load_result == Core::SystemResultStatus::Success) {
#ifndef YUZU_NO_CPU_DEBUGGER
m_system.DetachDebugger(); m_system.DetachDebugger();
#endif
m_system.ShutdownMainProcess(); m_system.ShutdownMainProcess();
m_detached_tasks.WaitForAllTasks(); m_detached_tasks.WaitForAllTasks();
m_load_result = Core::SystemResultStatus::ErrorNotInitialized; m_load_result = Core::SystemResultStatus::ErrorNotInitialized;
@ -344,9 +346,11 @@ void EmulationSession::RunEmulation() {
void(m_system.Run()); void(m_system.Run());
#ifndef YUZU_NO_CPU_DEBUGGER
if (m_system.DebuggerEnabled()) { if (m_system.DebuggerEnabled()) {
m_system.InitializeDebugger(); m_system.InitializeDebugger();
} }
#endif
while (true) { while (true) {
{ {

View File

@ -17,4 +17,4 @@ kotlin.parallel.tasks.in.project=true
android.defaults.buildfeatures.buildconfig=true android.defaults.buildfeatures.buildconfig=true
# Android Gradle plugin 8.0.2 # Android Gradle plugin 8.0.2
android.suppressUnsupportedCompileSdk=34 android.suppressUnsupportedCompileSdk=35

View File

@ -30,13 +30,6 @@ add_library(core STATIC
crypto/partition_data_manager.h crypto/partition_data_manager.h
crypto/xts_encryption_layer.cpp crypto/xts_encryption_layer.cpp
crypto/xts_encryption_layer.h crypto/xts_encryption_layer.h
debugger/debugger.cpp
debugger/debugger.h
debugger/debugger_interface.h
debugger/gdbstub.cpp
debugger/gdbstub.h
debugger/gdbstub_arch.cpp
debugger/gdbstub_arch.h
device_memory.cpp device_memory.cpp
device_memory.h device_memory.h
device_memory_manager.h device_memory_manager.h
@ -1142,6 +1135,20 @@ add_library(core STATIC
tools/renderdoc.h tools/renderdoc.h
) )
if (YUZU_NO_CPU_DEBUGGER)
target_compile_definitions(core PUBLIC YUZU_NO_CPU_DEBUGGER)
else()
target_sources(core PRIVATE
debugger/debugger.cpp
debugger/debugger.h
debugger/debugger_interface.h
debugger/gdbstub.cpp
debugger/gdbstub.h
debugger/gdbstub_arch.cpp
debugger/gdbstub_arch.h
)
endif()
if (MSVC) if (MSVC)
target_compile_options(core PRIVATE target_compile_options(core PRIVATE
/we4245 # 'conversion': conversion from 'type1' to 'type2', signed/unsigned mismatch /we4245 # 'conversion': conversion from 'type1' to 'type2', signed/unsigned mismatch

View File

@ -16,10 +16,15 @@ using namespace Common::Literals;
class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks { class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks {
public: public:
explicit DynarmicCallbacks32(ArmDynarmic32& parent, Kernel::KProcess* process) explicit DynarmicCallbacks32(ArmDynarmic32& parent, Kernel::KProcess* process)
: m_parent{parent}, m_memory(process->GetMemory()), : m_parent{parent}
m_process(process), m_debugger_enabled{parent.m_system.DebuggerEnabled()}, , m_memory(process->GetMemory())
m_check_memory_access{m_debugger_enabled || , m_process(process)
!Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {} #ifndef YUZU_NO_CPU_DEBUGGER
, m_debugger_enabled{parent.m_system.DebuggerEnabled()}
#endif
, m_check_memory_access{m_debugger_enabled
|| !Settings::values.cpuopt_ignore_memory_aborts.GetValue()}
{}
u8 MemoryRead8(u32 vaddr) override { u8 MemoryRead8(u32 vaddr) override {
CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read); CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read);
@ -213,10 +218,12 @@ std::shared_ptr<Dynarmic::A32::Jit> ArmDynarmic32::MakeJit(Common::PageTable* pa
config.code_cache_size = 512_MiB; config.code_cache_size = 512_MiB;
#endif #endif
#ifndef YUZU_NO_CPU_DEBUGGER
// Allow memory fault handling to work // Allow memory fault handling to work
if (m_system.DebuggerEnabled()) { if (m_system.DebuggerEnabled()) {
config.check_halt_on_memory_access = true; config.check_halt_on_memory_access = true;
} }
#endif
// null_jit // null_jit
if (!page_table) { if (!page_table) {

View File

@ -16,10 +16,18 @@ using namespace Common::Literals;
class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks { class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks {
public: public:
explicit DynarmicCallbacks64(ArmDynarmic64& parent, Kernel::KProcess* process) explicit DynarmicCallbacks64(ArmDynarmic64& parent, Kernel::KProcess* process)
: m_parent{parent}, m_memory(process->GetMemory()), : m_parent{parent}
m_process(process), m_debugger_enabled{parent.m_system.DebuggerEnabled()}, , m_memory(process->GetMemory())
m_check_memory_access{m_debugger_enabled || , m_process(process)
!Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {} #ifndef YUZU_NO_CPU_DEBUGGER
, m_debugger_enabled{parent.m_system.DebuggerEnabled()}
#endif
, m_check_memory_access{
#ifndef YUZU_NO_CPU_DEBUGGER
m_debugger_enabled ||
#endif
!Settings::values.cpuopt_ignore_memory_aborts.GetValue()}
{}
u8 MemoryRead8(u64 vaddr) override { u8 MemoryRead8(u64 vaddr) override {
CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read); CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read);
@ -139,10 +147,12 @@ public:
ReturnException(pc, PrefetchAbort); ReturnException(pc, PrefetchAbort);
return; return;
default: default:
#ifndef YUZU_NO_CPU_DEBUGGER
if (m_debugger_enabled) { if (m_debugger_enabled) {
ReturnException(pc, InstructionBreakpoint); ReturnException(pc, InstructionBreakpoint);
return; return;
} }
#endif
m_parent.LogBacktrace(m_process); m_parent.LogBacktrace(m_process);
LOG_CRITICAL(Core_ARM, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})", LOG_CRITICAL(Core_ARM, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})",
@ -192,6 +202,7 @@ public:
return false; return false;
} }
#ifndef YUZU_NO_CPU_DEBUGGER
if (!m_debugger_enabled) { if (!m_debugger_enabled) {
return true; return true;
} }
@ -202,6 +213,7 @@ public:
m_parent.m_jit->HaltExecution(DataAbort); m_parent.m_jit->HaltExecution(DataAbort);
return false; return false;
} }
#endif
return true; return true;
} }
@ -217,7 +229,9 @@ public:
u64 m_tpidrro_el0{}; u64 m_tpidrro_el0{};
u64 m_tpidr_el0{}; u64 m_tpidr_el0{};
Kernel::KProcess* m_process{}; Kernel::KProcess* m_process{};
#ifndef YUZU_NO_CPU_DEBUGGER
const bool m_debugger_enabled{}; const bool m_debugger_enabled{};
#endif
const bool m_check_memory_access{}; const bool m_check_memory_access{};
static constexpr u64 MinimumRunCycles = 10000U; static constexpr u64 MinimumRunCycles = 10000U;
}; };
@ -272,10 +286,12 @@ std::shared_ptr<Dynarmic::A64::Jit> ArmDynarmic64::MakeJit(Common::PageTable* pa
config.code_cache_size = 512_MiB; config.code_cache_size = 512_MiB;
#endif #endif
#ifndef YUZU_NO_CPU_DEBUGGER
// Allow memory fault handling to work // Allow memory fault handling to work
if (m_system.DebuggerEnabled()) { if (m_system.DebuggerEnabled()) {
config.check_halt_on_memory_access = true; config.check_halt_on_memory_access = true;
} }
#endif
// null_jit // null_jit
if (!page_table) { if (!page_table) {

View File

@ -256,9 +256,11 @@ struct System::Impl {
return nvdec_active; return nvdec_active;
} }
#ifndef YUZU_NO_CPU_DEBUGGER
void InitializeDebugger(System& system, u16 port) { void InitializeDebugger(System& system, u16 port) {
debugger = std::make_unique<Debugger>(system, port); debugger = std::make_unique<Debugger>(system, port);
} }
#endif
void InitializeKernel(System& system) { void InitializeKernel(System& system) {
LOG_DEBUG(Core, "initialized OK"); LOG_DEBUG(Core, "initialized OK");
@ -421,7 +423,9 @@ struct System::Impl {
host1x_core.reset(); host1x_core.reset();
perf_stats.reset(); perf_stats.reset();
cpu_manager.Shutdown(); cpu_manager.Shutdown();
#ifndef YUZU_NO_CPU_DEBUGGER
debugger.reset(); debugger.reset();
#endif
kernel.Shutdown(); kernel.Shutdown();
stop_event = {}; stop_event = {};
Network::RestartSocketOperations(); Network::RestartSocketOperations();
@ -516,8 +520,10 @@ struct System::Impl {
/// Network instance /// Network instance
Network::NetworkInstance network_instance; Network::NetworkInstance network_instance;
#ifndef YUZU_NO_CPU_DEBUGGER
/// Debugger /// Debugger
std::unique_ptr<Core::Debugger> debugger; std::unique_ptr<Core::Debugger> debugger;
#endif
SystemResultStatus status = SystemResultStatus::Success; SystemResultStatus status = SystemResultStatus::Success;
std::string status_details = ""; std::string status_details = "";
@ -582,11 +588,13 @@ void System::SetShuttingDown(bool shutting_down) {
impl->SetShuttingDown(shutting_down); impl->SetShuttingDown(shutting_down);
} }
#ifndef YUZU_NO_CPU_DEBUGGER
void System::DetachDebugger() { void System::DetachDebugger() {
if (impl->debugger) { if (impl->debugger) {
impl->debugger->NotifyShutdown(); impl->debugger->NotifyShutdown();
} }
} }
#endif
std::unique_lock<std::mutex> System::StallApplication() { std::unique_lock<std::mutex> System::StallApplication() {
return impl->StallApplication(); return impl->StallApplication();
@ -604,9 +612,11 @@ bool System::GetNVDECActive() {
return impl->GetNVDECActive(); return impl->GetNVDECActive();
} }
#ifndef YUZU_NO_CPU_DEBUGGER
void System::InitializeDebugger() { void System::InitializeDebugger() {
impl->InitializeDebugger(*this, Settings::values.gdbstub_port.GetValue()); impl->InitializeDebugger(*this, Settings::values.gdbstub_port.GetValue());
} }
#endif
SystemResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath, SystemResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath,
Service::AM::FrontendAppletParameters& params) { Service::AM::FrontendAppletParameters& params) {
@ -927,6 +937,7 @@ bool System::IsMulticore() const {
return impl->is_multicore; return impl->is_multicore;
} }
#ifndef YUZU_NO_CPU_DEBUGGER
bool System::DebuggerEnabled() const { bool System::DebuggerEnabled() const {
return Settings::values.use_gdbstub.GetValue(); return Settings::values.use_gdbstub.GetValue();
} }
@ -938,6 +949,7 @@ Core::Debugger& System::GetDebugger() {
const Core::Debugger& System::GetDebugger() const { const Core::Debugger& System::GetDebugger() const {
return *impl->debugger; return *impl->debugger;
} }
#endif
Network::RoomNetwork& System::GetRoomNetwork() { Network::RoomNetwork& System::GetRoomNetwork() {
return impl->room_network; return impl->room_network;

View File

@ -184,8 +184,10 @@ public:
/// Set the shutting down state. /// Set the shutting down state.
void SetShuttingDown(bool shutting_down); void SetShuttingDown(bool shutting_down);
#ifndef YUZU_NO_CPU_DEBUGGER
/// Forcibly detach the debugger if it is running. /// Forcibly detach the debugger if it is running.
void DetachDebugger(); void DetachDebugger();
#endif
std::unique_lock<std::mutex> StallApplication(); std::unique_lock<std::mutex> StallApplication();
void UnstallApplication(); void UnstallApplication();
@ -193,10 +195,12 @@ public:
void SetNVDECActive(bool is_nvdec_active); void SetNVDECActive(bool is_nvdec_active);
[[nodiscard]] bool GetNVDECActive(); [[nodiscard]] bool GetNVDECActive();
#ifndef YUZU_NO_CPU_DEBUGGER
/** /**
* Initialize the debugger. * Initialize the debugger.
*/ */
void InitializeDebugger(); void InitializeDebugger();
#endif
/** /**
* Load an executable application. * Load an executable application.
@ -377,8 +381,10 @@ public:
[[nodiscard]] Service::Account::ProfileManager& GetProfileManager(); [[nodiscard]] Service::Account::ProfileManager& GetProfileManager();
[[nodiscard]] const Service::Account::ProfileManager& GetProfileManager() const; [[nodiscard]] const Service::Account::ProfileManager& GetProfileManager() const;
#ifndef YUZU_NO_CPU_DEBUGGER
[[nodiscard]] Core::Debugger& GetDebugger(); [[nodiscard]] Core::Debugger& GetDebugger();
[[nodiscard]] const Core::Debugger& GetDebugger() const; [[nodiscard]] const Core::Debugger& GetDebugger() const;
#endif
/// Gets a mutable reference to the Room Network. /// Gets a mutable reference to the Room Network.
[[nodiscard]] Network::RoomNetwork& GetRoomNetwork(); [[nodiscard]] Network::RoomNetwork& GetRoomNetwork();
@ -412,8 +418,10 @@ public:
/// Tells if system is running on multicore. /// Tells if system is running on multicore.
[[nodiscard]] bool IsMulticore() const; [[nodiscard]] bool IsMulticore() const;
#ifndef YUZU_NO_CPU_DEBUGGER
/// Tells if the system debugger is enabled. /// Tells if the system debugger is enabled.
[[nodiscard]] bool DebuggerEnabled() const; [[nodiscard]] bool DebuggerEnabled() const;
#endif
/// Runs a server instance until shutdown. /// Runs a server instance until shutdown.
void RunServer(std::unique_ptr<Service::ServerManager>&& server_manager); void RunServer(std::unique_ptr<Service::ServerManager>&& server_manager);

View File

@ -1,6 +1,8 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "core/debugger/debugger.h"
#include <algorithm> #include <algorithm>
#include <mutex> #include <mutex>
#include <thread> #include <thread>
@ -9,33 +11,34 @@
#include <boost/process/v1/async_pipe.hpp> #include <boost/process/v1/async_pipe.hpp>
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/polyfill_thread.h"
#include "common/thread.h" #include "common/thread.h"
#include "core/core.h" #include "core/core.h"
#include "core/debugger/debugger.h"
#include "core/debugger/debugger_interface.h" #include "core/debugger/debugger_interface.h"
#include "core/debugger/gdbstub.h" #include "core/debugger/gdbstub.h"
#include "core/hle/kernel/global_scheduler_context.h" #include "core/hle/kernel/global_scheduler_context.h"
#include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_scheduler.h" #include "core/hle/kernel/k_scheduler.h"
template <typename Readable, typename Buffer, typename Callback> template<typename Readable, typename Buffer, typename Callback>
static void AsyncReceiveInto(Readable& r, Buffer& buffer, Callback&& c) { static void AsyncReceiveInto(Readable& r, Buffer& buffer, Callback&& c)
{
static_assert(std::is_trivial_v<Buffer>); static_assert(std::is_trivial_v<Buffer>);
auto boost_buffer{boost::asio::buffer(&buffer, sizeof(Buffer))}; auto boost_buffer{boost::asio::buffer(&buffer, sizeof(Buffer))};
r.async_read_some( r.async_read_some(boost_buffer,
boost_buffer, [&, c](const boost::system::error_code& error, size_t bytes_read) { [&, c](const boost::system::error_code& error, size_t bytes_read) {
if (!error.failed()) { if (!error.failed()) {
const u8* buffer_start = reinterpret_cast<const u8*>(&buffer); const u8* buffer_start = reinterpret_cast<const u8*>(&buffer);
std::span<const u8> received_data{buffer_start, buffer_start + bytes_read}; std::span<const u8> received_data{buffer_start,
c(received_data); buffer_start + bytes_read};
AsyncReceiveInto(r, buffer, c); c(received_data);
} AsyncReceiveInto(r, buffer, c);
}); }
});
} }
template <typename Callback> template<typename Callback>
static void AsyncAccept(boost::asio::ip::tcp::acceptor& acceptor, Callback&& c) { static void AsyncAccept(boost::asio::ip::tcp::acceptor& acceptor, Callback&& c)
{
acceptor.async_accept([&, c](const boost::system::error_code& error, auto&& peer_socket) { acceptor.async_accept([&, c](const boost::system::error_code& error, auto&& peer_socket) {
if (!error.failed()) { if (!error.failed()) {
c(peer_socket); c(peer_socket);
@ -44,8 +47,9 @@ static void AsyncAccept(boost::asio::ip::tcp::acceptor& acceptor, Callback&& c)
}); });
} }
template <typename Readable, typename Buffer> template<typename Readable, typename Buffer>
static std::span<const u8> ReceiveInto(Readable& r, Buffer& buffer) { static std::span<const u8> ReceiveInto(Readable& r, Buffer& buffer)
{
static_assert(std::is_trivial_v<Buffer>); static_assert(std::is_trivial_v<Buffer>);
auto boost_buffer{boost::asio::buffer(&buffer, sizeof(Buffer))}; auto boost_buffer{boost::asio::buffer(&buffer, sizeof(Buffer))};
size_t bytes_read = r.read_some(boost_buffer); size_t bytes_read = r.read_some(boost_buffer);
@ -60,7 +64,8 @@ enum class SignalType {
ShuttingDown, ShuttingDown,
}; };
struct SignalInfo { struct SignalInfo
{
SignalType type; SignalType type;
Kernel::KThread* thread; Kernel::KThread* thread;
const Kernel::DebugWatchpoint* watchpoint; const Kernel::DebugWatchpoint* watchpoint;
@ -68,17 +73,19 @@ struct SignalInfo {
namespace Core { namespace Core {
class DebuggerImpl : public DebuggerBackend { class DebuggerImpl : public DebuggerBackend
{
public: public:
explicit DebuggerImpl(Core::System& system_, u16 port) : system{system_} { explicit DebuggerImpl(Core::System& system_, u16 port)
: system{system_}
{
InitializeServer(port); InitializeServer(port);
} }
~DebuggerImpl() override { ~DebuggerImpl() override { ShutdownServer(); }
ShutdownServer();
}
bool SignalDebugger(SignalInfo signal_info) { bool SignalDebugger(SignalInfo signal_info)
{
std::scoped_lock lk{connection_lock}; std::scoped_lock lk{connection_lock};
if (stopped || !state) { if (stopped || !state) {
@ -100,25 +107,24 @@ public:
// These functions are callbacks from the frontend, and the lock will be held. // These functions are callbacks from the frontend, and the lock will be held.
// There is no need to relock it. // There is no need to relock it.
std::span<const u8> ReadFromClient() override { std::span<const u8> ReadFromClient() override
{
return ReceiveInto(state->client_socket, state->client_data); return ReceiveInto(state->client_socket, state->client_data);
} }
void WriteToClient(std::span<const u8> data) override { void WriteToClient(std::span<const u8> data) override
{
boost::asio::write(state->client_socket, boost::asio::write(state->client_socket,
boost::asio::buffer(data.data(), data.size_bytes())); boost::asio::buffer(data.data(), data.size_bytes()));
} }
void SetActiveThread(Kernel::KThread* thread) override { void SetActiveThread(Kernel::KThread* thread) override { state->active_thread = thread; }
state->active_thread = thread;
}
Kernel::KThread* GetActiveThread() override { Kernel::KThread* GetActiveThread() override { return state->active_thread.GetPointerUnsafe(); }
return state->active_thread.GetPointerUnsafe();
}
private: private:
void InitializeServer(u16 port) { void InitializeServer(u16 port)
{
using boost::asio::ip::tcp; using boost::asio::ip::tcp;
LOG_INFO(Debug_GDBStub, "Starting server on port {}...", port); LOG_INFO(Debug_GDBStub, "Starting server on port {}...", port);
@ -142,7 +148,8 @@ private:
}); });
} }
void AcceptConnection(boost::asio::ip::tcp::socket&& peer) { void AcceptConnection(boost::asio::ip::tcp::socket&& peer)
{
LOG_INFO(Debug_GDBStub, "Accepting new peer connection"); LOG_INFO(Debug_GDBStub, "Accepting new peer connection");
std::scoped_lock lk{connection_lock}; std::scoped_lock lk{connection_lock};
@ -177,13 +184,15 @@ private:
frontend->Connected(); frontend->Connected();
} }
void ShutdownServer() { void ShutdownServer()
{
connection_thread.request_stop(); connection_thread.request_stop();
io_context.stop(); io_context.stop();
connection_thread.join(); connection_thread.join();
} }
void PipeData(std::span<const u8> data) { void PipeData(std::span<const u8> data)
{
std::scoped_lock lk{connection_lock}; std::scoped_lock lk{connection_lock};
switch (state->info.type) { switch (state->info.type) {
@ -197,8 +206,7 @@ private:
UpdateActiveThread(); UpdateActiveThread();
if (state->info.type == SignalType::Watchpoint) { if (state->info.type == SignalType::Watchpoint) {
frontend->Watchpoint(std::addressof(*state->active_thread), frontend->Watchpoint(std::addressof(*state->active_thread), *state->info.watchpoint);
*state->info.watchpoint);
} else { } else {
frontend->Stopped(std::addressof(*state->active_thread)); frontend->Stopped(std::addressof(*state->active_thread));
} }
@ -220,7 +228,8 @@ private:
} }
} }
void ClientData(std::span<const u8> data) { void ClientData(std::span<const u8> data)
{
std::scoped_lock lk{connection_lock}; std::scoped_lock lk{connection_lock};
const auto actions{frontend->ClientData(data)}; const auto actions{frontend->ClientData(data)};
@ -262,7 +271,8 @@ private:
} }
} }
void PauseEmulation() { void PauseEmulation()
{
Kernel::KScopedLightLock ll{debug_process->GetListLock()}; Kernel::KScopedLightLock ll{debug_process->GetListLock()};
Kernel::KScopedSchedulerLock sl{system.Kernel()}; Kernel::KScopedSchedulerLock sl{system.Kernel()};
@ -272,7 +282,8 @@ private:
} }
} }
void ResumeEmulation(Kernel::KThread* except = nullptr) { void ResumeEmulation(Kernel::KThread* except = nullptr)
{
Kernel::KScopedLightLock ll{debug_process->GetListLock()}; Kernel::KScopedLightLock ll{debug_process->GetListLock()};
Kernel::KScopedSchedulerLock sl{system.Kernel()}; Kernel::KScopedSchedulerLock sl{system.Kernel()};
@ -287,13 +298,15 @@ private:
} }
} }
template <typename Callback> template<typename Callback>
void MarkResumed(Callback&& cb) { void MarkResumed(Callback&& cb)
{
stopped = false; stopped = false;
cb(); cb();
} }
void UpdateActiveThread() { void UpdateActiveThread()
{
Kernel::KScopedLightLock ll{debug_process->GetListLock()}; Kernel::KScopedLightLock ll{debug_process->GetListLock()};
auto& threads{ThreadList()}; auto& threads{ThreadList()};
@ -307,13 +320,9 @@ private:
} }
private: private:
void SetDebugProcess() { void SetDebugProcess() { debug_process = std::move(system.Kernel().GetProcessList().back()); }
debug_process = std::move(system.Kernel().GetProcessList().back());
}
Kernel::KProcess::ThreadList& ThreadList() { Kernel::KProcess::ThreadList& ThreadList() { return debug_process->GetThreadList(); }
return debug_process->GetThreadList();
}
private: private:
System& system; System& system;
@ -324,7 +333,8 @@ private:
std::jthread connection_thread; std::jthread connection_thread;
std::mutex connection_lock; std::mutex connection_lock;
struct ConnectionState { struct ConnectionState
{
boost::asio::ip::tcp::socket client_socket; boost::asio::ip::tcp::socket client_socket;
boost::process::v1::async_pipe signal_pipe; boost::process::v1::async_pipe signal_pipe;
@ -338,7 +348,8 @@ private:
bool stopped{}; bool stopped{};
}; };
Debugger::Debugger(Core::System& system, u16 port) { Debugger::Debugger(Core::System& system, u16 port)
{
try { try {
impl = std::make_unique<DebuggerImpl>(system, port); impl = std::make_unique<DebuggerImpl>(system, port);
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
@ -348,16 +359,18 @@ Debugger::Debugger(Core::System& system, u16 port) {
Debugger::~Debugger() = default; Debugger::~Debugger() = default;
bool Debugger::NotifyThreadStopped(Kernel::KThread* thread) { bool Debugger::NotifyThreadStopped(Kernel::KThread* thread)
{
return impl && impl->SignalDebugger(SignalInfo{SignalType::Stopped, thread, nullptr}); return impl && impl->SignalDebugger(SignalInfo{SignalType::Stopped, thread, nullptr});
} }
bool Debugger::NotifyThreadWatchpoint(Kernel::KThread* thread, bool Debugger::NotifyThreadWatchpoint(Kernel::KThread* thread, const Kernel::DebugWatchpoint& watch)
const Kernel::DebugWatchpoint& watch) { {
return impl && impl->SignalDebugger(SignalInfo{SignalType::Watchpoint, thread, &watch}); return impl && impl->SignalDebugger(SignalInfo{SignalType::Watchpoint, thread, &watch});
} }
void Debugger::NotifyShutdown() { void Debugger::NotifyShutdown()
{
if (impl) { if (impl) {
impl->SignalDebugger(SignalInfo{SignalType::ShuttingDown, nullptr, nullptr}); impl->SignalDebugger(SignalInfo{SignalType::ShuttingDown, nullptr, nullptr});
} }

View File

@ -992,10 +992,12 @@ Result KProcess::Run(s32 priority, size_t stack_size) {
this->ChangeState(state); this->ChangeState(state);
}; };
#ifndef YUZU_NO_CPU_DEBUGGER
// Suspend for debug, if we should. // Suspend for debug, if we should.
if (m_kernel.System().DebuggerEnabled()) { if (m_kernel.System().DebuggerEnabled()) {
main_thread->RequestSuspend(SuspendType::Debug); main_thread->RequestSuspend(SuspendType::Debug);
} }
#endif
// Run our thread. // Run our thread.
R_TRY(main_thread->Run()); R_TRY(main_thread->Run());

View File

@ -71,7 +71,9 @@ void PhysicalCore::RunThread(Kernel::KThread* thread) {
// Notify the debugger and go to sleep if a step was performed // Notify the debugger and go to sleep if a step was performed
// and this thread has been scheduled again. // and this thread has been scheduled again.
if (thread->GetStepState() == StepState::StepPerformed) { if (thread->GetStepState() == StepState::StepPerformed) {
#ifndef YUZU_NO_CPU_DEBUGGER
system.GetDebugger().NotifyThreadStopped(thread); system.GetDebugger().NotifyThreadStopped(thread);
#endif
thread->RequestSuspend(SuspendType::Debug); thread->RequestSuspend(SuspendType::Debug);
return; return;
} }
@ -113,20 +115,23 @@ void PhysicalCore::RunThread(Kernel::KThread* thread) {
if (breakpoint) { if (breakpoint) {
interface->RewindBreakpointInstruction(); interface->RewindBreakpointInstruction();
} }
#ifndef YUZU_NO_CPU_DEBUGGER
if (system.DebuggerEnabled()) { if (system.DebuggerEnabled()) {
system.GetDebugger().NotifyThreadStopped(thread); system.GetDebugger().NotifyThreadStopped(thread);
} else { } else
#endif
interface->LogBacktrace(process); interface->LogBacktrace(process);
}
thread->RequestSuspend(SuspendType::Debug); thread->RequestSuspend(SuspendType::Debug);
return; return;
} }
// Notify the debugger and go to sleep on data abort. // Notify the debugger and go to sleep on data abort.
if (data_abort) { if (data_abort) {
#ifndef YUZU_NO_CPU_DEBUGGER
if (system.DebuggerEnabled()) { if (system.DebuggerEnabled()) {
system.GetDebugger().NotifyThreadWatchpoint(thread, *interface->HaltedWatchpoint()); system.GetDebugger().NotifyThreadWatchpoint(thread, *interface->HaltedWatchpoint());
} }
#endif
thread->RequestSuspend(SuspendType::Debug); thread->RequestSuspend(SuspendType::Debug);
return; return;
} }

View File

@ -2,7 +2,9 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "core/core.h" #include "core/core.h"
#ifndef YUZU_NO_CPU_DEBUGGER
#include "core/debugger/debugger.h" #include "core/debugger/debugger.h"
#endif
#include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/svc.h" #include "core/hle/kernel/svc.h"
@ -106,6 +108,7 @@ void Break(Core::System& system, BreakReason reason, u64 info1, u64 info2) {
system.CurrentPhysicalCore().LogBacktrace(); system.CurrentPhysicalCore().LogBacktrace();
} }
#ifndef YUZU_NO_CPU_DEBUGGER
const bool is_hbl = GetCurrentProcess(system.Kernel()).IsHbl(); const bool is_hbl = GetCurrentProcess(system.Kernel()).IsHbl();
const bool should_break = is_hbl || !notification_only; const bool should_break = is_hbl || !notification_only;
@ -114,6 +117,7 @@ void Break(Core::System& system, BreakReason reason, u64 info1, u64 info2) {
system.GetDebugger().NotifyThreadStopped(thread); system.GetDebugger().NotifyThreadStopped(thread);
thread->RequestSuspend(Kernel::SuspendType::Debug); thread->RequestSuspend(Kernel::SuspendType::Debug);
} }
#endif
} }
void ReturnFromException(Core::System& system, Result result) { void ReturnFromException(Core::System& system, Result result) {

View File

@ -100,9 +100,11 @@ void EmuThread::run() {
m_system.GetCpuManager().OnGpuReady(); m_system.GetCpuManager().OnGpuReady();
#ifndef YUZU_NO_CPU_DEBUGGER
if (m_system.DebuggerEnabled()) { if (m_system.DebuggerEnabled()) {
m_system.InitializeDebugger(); m_system.InitializeDebugger();
} }
#endif
while (!stop_token.stop_requested()) { while (!stop_token.stop_requested()) {
std::unique_lock lk{m_should_run_mutex}; std::unique_lock lk{m_should_run_mutex};
@ -122,7 +124,9 @@ void EmuThread::run() {
} }
// Shutdown the main emulated process // Shutdown the main emulated process
#ifndef YUZU_NO_CPU_DEBUGGER
m_system.DetachDebugger(); m_system.DetachDebugger();
#endif
m_system.ShutdownMainProcess(); m_system.ShutdownMainProcess();
#if MICROPROFILE_ENABLED #if MICROPROFILE_ENABLED

View File

@ -19,9 +19,14 @@ ConfigureDebug::ConfigureDebug(const Core::System& system_, QWidget* parent)
ui->setupUi(this); ui->setupUi(this);
SetConfiguration(); SetConfiguration();
#ifdef YUZU_NO_CPU_DEBUGGER
ui->cpu_debug_box->setEnabled(false);
ui->toggle_gdbstub->setCheckState(Qt::Unchecked);
#endif
connect(ui->open_log_button, &QPushButton::clicked, []() { connect(ui->open_log_button, &QPushButton::clicked, []() {
const auto path = const auto path = QString::fromStdString(
QString::fromStdString(Common::FS::GetYuzuPathString(Common::FS::YuzuPath::LogDir)); Common::FS::GetYuzuPathString(Common::FS::YuzuPath::LogDir));
QDesktopServices::openUrl(QUrl::fromLocalFile(path)); QDesktopServices::openUrl(QUrl::fromLocalFile(path));
}); });

View File

@ -18,8 +18,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>842</width> <width>829</width>
<height>741</height> <height>758</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_1"> <layout class="QVBoxLayout" name="verticalLayout_1">
@ -29,7 +29,7 @@
<number>0</number> <number>0</number>
</property> </property>
<item> <item>
<widget class="QGroupBox" name="groupBox"> <widget class="QGroupBox" name="cpu_debug_box">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch> <horstretch>0</horstretch>
@ -40,7 +40,7 @@
<string>Debugger</string> <string>Debugger</string>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> <set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
</property> </property>
<property name="flat"> <property name="flat">
<bool>false</bool> <bool>false</bool>
@ -59,7 +59,7 @@
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<property name="sizeConstraint"> <property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum> <enum>QLayout::SizeConstraint::SetDefaultConstraint</enum>
</property> </property>
<property name="leftMargin"> <property name="leftMargin">
<number>0</number> <number>0</number>
@ -355,10 +355,10 @@
<item row="10" column="0"> <item row="10" column="0">
<spacer name="verticalSpacer_5"> <spacer name="verticalSpacer_5">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Orientation::Vertical</enum>
</property> </property>
<property name="sizeType"> <property name="sizeType">
<enum>QSizePolicy::Preferred</enum> <enum>QSizePolicy::Policy::Preferred</enum>
</property> </property>
<property name="sizeHint" stdset="0"> <property name="sizeHint" stdset="0">
<size> <size>
@ -452,10 +452,10 @@
<item row="7" column="0"> <item row="7" column="0">
<spacer name="verticalSpacer_4"> <spacer name="verticalSpacer_4">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Orientation::Vertical</enum>
</property> </property>
<property name="sizeType"> <property name="sizeType">
<enum>QSizePolicy::Expanding</enum> <enum>QSizePolicy::Policy::Expanding</enum>
</property> </property>
<property name="sizeHint" stdset="0"> <property name="sizeHint" stdset="0">
<size> <size>
@ -501,10 +501,10 @@
<item row="5" column="0"> <item row="5" column="0">
<spacer name="verticalSpacer_3"> <spacer name="verticalSpacer_3">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Orientation::Vertical</enum>
</property> </property>
<property name="sizeType"> <property name="sizeType">
<enum>QSizePolicy::Expanding</enum> <enum>QSizePolicy::Policy::Expanding</enum>
</property> </property>
<property name="sizeHint" stdset="0"> <property name="sizeHint" stdset="0">
<size> <size>
@ -522,7 +522,7 @@
<item> <item>
<spacer name="verticalSpacer"> <spacer name="verticalSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Orientation::Vertical</enum>
</property> </property>
<property name="sizeHint" stdset="0"> <property name="sizeHint" stdset="0">
<size> <size>

View File

@ -2076,9 +2076,12 @@ bool GMainWindow::OnShutdownBegin() {
int shutdown_time = 1000; int shutdown_time = 1000;
#ifndef YUZU_NO_CPU_DEBUGGER
if (system->DebuggerEnabled()) { if (system->DebuggerEnabled()) {
shutdown_time = 0; shutdown_time = 0;
} else if (system->GetExitLocked()) { } else
#endif
if (system->GetExitLocked()) {
shutdown_time = 5000; shutdown_time = 5000;
} }

View File

@ -436,13 +436,17 @@ int main(int argc, char** argv) {
#endif #endif
void(system.Run()); void(system.Run());
#ifndef YUZU_NO_CPU_DEBUGGER
if (system.DebuggerEnabled()) { if (system.DebuggerEnabled()) {
system.InitializeDebugger(); system.InitializeDebugger();
} }
#endif
while (emu_window->IsOpen()) { while (emu_window->IsOpen()) {
emu_window->WaitEvent(); emu_window->WaitEvent();
} }
#ifndef YUZU_NO_CPU_DEBUGGER
system.DetachDebugger(); system.DetachDebugger();
#endif
void(system.Pause()); void(system.Pause());
system.ShutdownMainProcess(); system.ShutdownMainProcess();

View File

@ -16,7 +16,10 @@
"boost-icl", "boost-icl",
"boost-intrusive", "boost-intrusive",
"boost-mpl", "boost-mpl",
"boost-process", {
"name": "boost-process",
"platform": "!android"
},
"boost-range", "boost-range",
"boost-spirit", "boost-spirit",
"boost-test", "boost-test",
@ -48,6 +51,10 @@
{ {
"name": "oboe", "name": "oboe",
"platform": "android" "platform": "android"
},
{
"name": "boost-fiber",
"platform": "android"
} }
] ]
} }