Compare commits
8 Commits
lanobu
...
rem-dup-ap
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
72bcc4c43a | ||
|
|
e22756160c | ||
|
|
a33956f738 | ||
|
|
4642e82ca7 | ||
|
|
97054357d2 | ||
|
|
941caf31ce | ||
|
|
c72144abad | ||
|
|
d656e347c8 |
2
externals/CMakeLists.txt
vendored
2
externals/CMakeLists.txt
vendored
@@ -27,7 +27,7 @@ set_directory_properties(PROPERTIES EXCLUDE_FROM_ALL ON)
|
||||
|
||||
# Xbyak (also used by Dynarmic, so needs to be added first)
|
||||
if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64)
|
||||
if (PLATFORM_SUN OR PLATFORM_OPENBSD)
|
||||
if (PLATFORM_SUN OR PLATFORM_OPENBSD OR PLATFORM_NETBSD OR PLATFORM_DRAGONFLY)
|
||||
AddJsonPackage(xbyak_sun)
|
||||
else()
|
||||
AddJsonPackage(xbyak)
|
||||
|
||||
@@ -22,33 +22,21 @@ void AssertFailSoftImpl();
|
||||
#define YUZU_NO_INLINE __attribute__((noinline))
|
||||
#endif
|
||||
|
||||
#define ASSERT(_a_) \
|
||||
([&]() YUZU_NO_INLINE { \
|
||||
if (!(_a_)) [[unlikely]] { \
|
||||
LOG_CRITICAL(Debug, "Assert"); \
|
||||
AssertFailSoftImpl(); \
|
||||
} \
|
||||
}())
|
||||
|
||||
#define ASSERT_MSG(_a_, ...) \
|
||||
([&]() YUZU_NO_INLINE { \
|
||||
if (!(_a_)) [[unlikely]] { \
|
||||
LOG_CRITICAL(Debug, "Assert\n" __VA_ARGS__); \
|
||||
AssertFailSoftImpl(); \
|
||||
LOG_CRITICAL(Debug, __FILE__ ": assert\n" __VA_ARGS__); \
|
||||
AssertFailSoftImpl(); \
|
||||
} \
|
||||
}())
|
||||
|
||||
#define UNREACHABLE() \
|
||||
do { \
|
||||
LOG_CRITICAL(Debug, "Unreachable"); \
|
||||
AssertFatalImpl(); \
|
||||
} while (0)
|
||||
#define ASSERT(_a_) ASSERT_MSG(_a_, "{}", #_a_)
|
||||
|
||||
#define UNREACHABLE_MSG(...) \
|
||||
do { \
|
||||
LOG_CRITICAL(Debug, "Unreachable\n" __VA_ARGS__); \
|
||||
AssertFatalImpl(); \
|
||||
LOG_CRITICAL(Debug, __FILE__ ": unreachable\n" __VA_ARGS__); \
|
||||
AssertFatalImpl(); \
|
||||
} while (0)
|
||||
#define UNREACHABLE() UNREACHABLE_MSG("")
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define DEBUG_ASSERT(_a_) ASSERT(_a_)
|
||||
@@ -68,20 +56,12 @@ void AssertFailSoftImpl();
|
||||
#define UNIMPLEMENTED_IF(cond) ASSERT_MSG(!(cond), "Unimplemented code!")
|
||||
#define UNIMPLEMENTED_IF_MSG(cond, ...) ASSERT_MSG(!(cond), __VA_ARGS__)
|
||||
|
||||
// If the assert is ignored, execute _b_
|
||||
#define ASSERT_OR_EXECUTE(_a_, _b_) \
|
||||
do { \
|
||||
ASSERT(_a_); \
|
||||
if (!(_a_)) [[unlikely]] { \
|
||||
_b_ \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// If the assert is ignored, execute _b_
|
||||
#define ASSERT_OR_EXECUTE_MSG(_a_, _b_, ...) \
|
||||
do { \
|
||||
ASSERT_MSG(_a_, __VA_ARGS__); \
|
||||
if (!(_a_)) [[unlikely]] { \
|
||||
_b_ \
|
||||
} \
|
||||
if (!(_a_)) { _b_ } \
|
||||
} while (0)
|
||||
|
||||
// If the assert is ignored, execute _b_
|
||||
#define ASSERT_OR_EXECUTE(_a_, _b_) ASSERT_OR_EXECUTE_MSG(_a_, _b_, "{}", #_a_)
|
||||
|
||||
@@ -50,8 +50,7 @@ constexpr const char* TrimSourcePath(std::string_view source) {
|
||||
}
|
||||
|
||||
/// @brief Interface for logging backends.
|
||||
class Backend {
|
||||
public:
|
||||
struct Backend {
|
||||
virtual ~Backend() = default;
|
||||
virtual void Write(const Entry& entry) = 0;
|
||||
virtual void EnableForStacktrace() = 0;
|
||||
@@ -59,8 +58,7 @@ public:
|
||||
};
|
||||
|
||||
/// @brief Backend that writes to stderr and with color
|
||||
class ColorConsoleBackend final : public Backend {
|
||||
public:
|
||||
struct ColorConsoleBackend final : public Backend {
|
||||
explicit ColorConsoleBackend() = default;
|
||||
~ColorConsoleBackend() override = default;
|
||||
|
||||
@@ -86,16 +84,15 @@ private:
|
||||
};
|
||||
|
||||
/// @brief Backend that writes to a file passed into the constructor
|
||||
class FileBackend final : public Backend {
|
||||
public:
|
||||
struct FileBackend final : public Backend {
|
||||
explicit FileBackend(const std::filesystem::path& filename) {
|
||||
auto old_filename = filename;
|
||||
old_filename += ".old.txt";
|
||||
|
||||
// Existence checks are done within the functions themselves.
|
||||
// We don't particularly care if these succeed or not.
|
||||
static_cast<void>(FS::RemoveFile(old_filename));
|
||||
static_cast<void>(FS::RenameFile(filename, old_filename));
|
||||
void(FS::RemoveFile(old_filename));
|
||||
void(FS::RenameFile(filename, old_filename));
|
||||
|
||||
file = std::make_unique<FS::IOFile>(filename, FS::FileAccessMode::Write, FS::FileType::TextFile);
|
||||
}
|
||||
@@ -165,51 +162,34 @@ private:
|
||||
bool enabled = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Backend that writes to Visual Studio's output window
|
||||
*/
|
||||
class DebuggerBackend final : public Backend {
|
||||
public:
|
||||
explicit DebuggerBackend() = default;
|
||||
|
||||
~DebuggerBackend() override = default;
|
||||
|
||||
void Write(const Entry& entry) override {
|
||||
#ifdef _WIN32
|
||||
/// @brief Backend that writes to Visual Studio's output window
|
||||
struct DebuggerBackend final : public Backend {
|
||||
explicit DebuggerBackend() = default;
|
||||
~DebuggerBackend() override = default;
|
||||
void Write(const Entry& entry) override {
|
||||
::OutputDebugStringW(UTF8ToUTF16W(FormatLogMessage(entry).append(1, '\n')).c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
void Flush() override {}
|
||||
|
||||
void EnableForStacktrace() override {}
|
||||
};
|
||||
|
||||
#endif
|
||||
#ifdef ANDROID
|
||||
/**
|
||||
* Backend that writes to the Android logcat
|
||||
*/
|
||||
class LogcatBackend : public Backend {
|
||||
public:
|
||||
/// @brief Backend that writes to the Android logcat
|
||||
struct LogcatBackend : public Backend {
|
||||
explicit LogcatBackend() = default;
|
||||
|
||||
~LogcatBackend() override = default;
|
||||
|
||||
void Write(const Entry& entry) override {
|
||||
PrintMessageToLogcat(entry);
|
||||
}
|
||||
|
||||
void Flush() override {}
|
||||
|
||||
void EnableForStacktrace() override {}
|
||||
};
|
||||
#endif
|
||||
|
||||
bool initialization_in_progress_suppress_logging = true;
|
||||
|
||||
/**
|
||||
* Static state as a singleton.
|
||||
*/
|
||||
/// @brief Static state as a singleton.
|
||||
class Impl {
|
||||
public:
|
||||
static Impl& Instance() {
|
||||
@@ -228,8 +208,7 @@ public:
|
||||
void(CreateDir(log_dir));
|
||||
Filter filter;
|
||||
filter.ParseFilterString(Settings::values.log_filter.GetValue());
|
||||
instance = std::unique_ptr<Impl, decltype(&Deleter)>(new Impl(log_dir / LOG_FILE, filter),
|
||||
Deleter);
|
||||
instance = std::unique_ptr<Impl, decltype(&Deleter)>(new Impl(log_dir / LOG_FILE, filter), Deleter);
|
||||
initialization_in_progress_suppress_logging = false;
|
||||
}
|
||||
|
||||
@@ -276,13 +255,14 @@ private:
|
||||
Common::SetCurrentThreadName("Logger");
|
||||
Entry entry;
|
||||
const auto write_logs = [this, &entry]() {
|
||||
ForEachBackend([&entry](Backend& backend) { backend.Write(entry); });
|
||||
ForEachBackend([&entry](Backend& backend) {
|
||||
backend.Write(entry);
|
||||
});
|
||||
};
|
||||
while (!stop_token.stop_requested()) {
|
||||
do {
|
||||
message_queue.PopWait(entry, stop_token);
|
||||
if (entry.filename != nullptr)
|
||||
write_logs();
|
||||
}
|
||||
write_logs();
|
||||
} while (!stop_token.stop_requested());
|
||||
// Drain the logging queue. Only writes out up to MAX_LOGS_TO_WRITE to prevent a
|
||||
// case where a system is repeatedly spamming logs even on close.
|
||||
int max_logs_to_write = filter.IsDebug() ? INT_MAX : 100;
|
||||
@@ -315,9 +295,11 @@ private:
|
||||
}
|
||||
|
||||
void ForEachBackend(auto lambda) {
|
||||
lambda(static_cast<Backend&>(debugger_backend));
|
||||
lambda(static_cast<Backend&>(color_console_backend));
|
||||
lambda(static_cast<Backend&>(file_backend));
|
||||
#ifdef _WIN32
|
||||
lambda(static_cast<Backend&>(debugger_backend));
|
||||
#endif
|
||||
#ifdef ANDROID
|
||||
lambda(static_cast<Backend&>(lc_backend));
|
||||
#endif
|
||||
@@ -330,9 +312,11 @@ private:
|
||||
static inline std::unique_ptr<Impl, decltype(&Deleter)> instance{nullptr, Deleter};
|
||||
|
||||
Filter filter;
|
||||
DebuggerBackend debugger_backend{};
|
||||
ColorConsoleBackend color_console_backend{};
|
||||
FileBackend file_backend;
|
||||
#ifdef _WIN32
|
||||
DebuggerBackend debugger_backend{};
|
||||
#endif
|
||||
#ifdef ANDROID
|
||||
LogcatBackend lc_backend{};
|
||||
#endif
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -25,15 +28,21 @@ static s64 WindowsQueryPerformanceCounter() {
|
||||
}
|
||||
|
||||
static s64 GetSystemTimeNS() {
|
||||
// GetSystemTimePreciseAsFileTime returns the file time in 100ns units.
|
||||
static constexpr s64 Multiplier = 100;
|
||||
// Convert Windows epoch to Unix epoch.
|
||||
static constexpr s64 WindowsEpochToUnixEpoch = 0x19DB1DED53E8000LL;
|
||||
|
||||
FILETIME filetime;
|
||||
GetSystemTimePreciseAsFileTime(&filetime);
|
||||
return Multiplier * ((static_cast<s64>(filetime.dwHighDateTime) << 32) +
|
||||
static_cast<s64>(filetime.dwLowDateTime) - WindowsEpochToUnixEpoch);
|
||||
static auto pf = (decltype(&GetSystemTimePreciseAsFileTime))(void*)GetProcAddress(GetModuleHandle(TEXT("Kernel32.dll")), "GetSystemTimePreciseAsFileTime"); // Windows 8+
|
||||
if (pf) {
|
||||
// GetSystemTimePreciseAsFileTime returns the file time in 100ns units.
|
||||
constexpr s64 Multiplier = 100;
|
||||
// Convert Windows epoch to Unix epoch.
|
||||
constexpr s64 WindowsEpochToUnixEpoch = 0x19DB1DED53E8000LL;
|
||||
FILETIME filetime;
|
||||
pf(&filetime);
|
||||
return Multiplier * ((s64(filetime.dwHighDateTime) << 32) + s64(filetime.dwLowDateTime) - WindowsEpochToUnixEpoch);
|
||||
} else {
|
||||
// Only Windows XP and below error out here
|
||||
LARGE_INTEGER ticks;
|
||||
QueryPerformanceCounter(&ticks);
|
||||
return ticks.QuadPart;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -81,10 +81,9 @@ void SetCurrentThreadPriority(ThreadPriority new_priority) {
|
||||
|
||||
// Sets the debugger-visible name of the current thread.
|
||||
void SetCurrentThreadName(const char* name) {
|
||||
if (auto pf = (decltype(&SetThreadDescription))(void*)GetProcAddress(GetModuleHandle(TEXT("KernelBase.dll")), "SetThreadDescription"); pf)
|
||||
static auto pf = (decltype(&SetThreadDescription))(void*)GetProcAddress(GetModuleHandle(TEXT("KernelBase.dll")), "SetThreadDescription");
|
||||
if (pf)
|
||||
pf(GetCurrentThread(), UTF8ToUTF16W(name).data()); // Windows 10+
|
||||
else
|
||||
; // No-op
|
||||
}
|
||||
|
||||
#else // !MSVC_VER, so must be POSIX threads
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -62,14 +65,15 @@ TimerResolution GetTimerResolution() {
|
||||
|
||||
void SetHighQoS() {
|
||||
// https://learn.microsoft.com/en-us/windows/win32/procthread/quality-of-service
|
||||
PROCESS_POWER_THROTTLING_STATE PowerThrottling{
|
||||
.Version{PROCESS_POWER_THROTTLING_CURRENT_VERSION},
|
||||
.ControlMask{PROCESS_POWER_THROTTLING_EXECUTION_SPEED |
|
||||
PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION},
|
||||
.StateMask{},
|
||||
};
|
||||
SetProcessInformation(GetCurrentProcess(), ProcessPowerThrottling, &PowerThrottling,
|
||||
sizeof(PROCESS_POWER_THROTTLING_STATE));
|
||||
static auto pf = (decltype(&SetProcessInformation))(void*)GetProcAddress(GetModuleHandle(TEXT("Kernel32.dll")), "SetProcessInformation");
|
||||
if (pf) {
|
||||
PROCESS_POWER_THROTTLING_STATE PowerThrottling{
|
||||
.Version = PROCESS_POWER_THROTTLING_CURRENT_VERSION,
|
||||
.ControlMask = PROCESS_POWER_THROTTLING_EXECUTION_SPEED | PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION,
|
||||
.StateMask = 0,
|
||||
};
|
||||
pf(GetCurrentProcess(), ProcessPowerThrottling, &PowerThrottling, sizeof(PROCESS_POWER_THROTTLING_STATE)); // Windows 7+
|
||||
}
|
||||
}
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
@@ -211,7 +211,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ArmDynarmic32::MakeJit(Common::PageTable* pa
|
||||
config.enable_cycle_counting = !m_uses_wall_clock;
|
||||
|
||||
// Code cache size
|
||||
#if defined(ARCHITECTURE_arm64) || defined(__sun__)
|
||||
#if defined(ARCHITECTURE_arm64) || defined(__sun__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
|
||||
config.code_cache_size = std::uint32_t(128_MiB);
|
||||
#else
|
||||
config.code_cache_size = std::uint32_t(512_MiB);
|
||||
@@ -295,7 +295,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ArmDynarmic32::MakeJit(Common::PageTable* pa
|
||||
// Curated optimizations
|
||||
case Settings::CpuAccuracy::Auto:
|
||||
config.unsafe_optimizations = true;
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__) || defined(__HAIKU__) || defined(__DragonFly__)
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__) || defined(__HAIKU__) || defined(__DragonFly__) || defined(__NetBSD__)
|
||||
config.fastmem_pointer = std::nullopt;
|
||||
config.fastmem_exclusive_access = false;
|
||||
#endif
|
||||
|
||||
@@ -270,7 +270,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ArmDynarmic64::MakeJit(Common::PageTable* pa
|
||||
config.enable_cycle_counting = !m_uses_wall_clock;
|
||||
|
||||
// Code cache size
|
||||
#if defined(ARCHITECTURE_arm64) || defined(__sun__)
|
||||
#if defined(ARCHITECTURE_arm64) || defined(__sun__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
|
||||
config.code_cache_size = std::uint32_t(128_MiB);
|
||||
#else
|
||||
config.code_cache_size = std::uint32_t(512_MiB);
|
||||
|
||||
@@ -339,14 +339,10 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
|
||||
};
|
||||
m_system_settings.eula_versions[0] = eula_version;
|
||||
m_system_settings.eula_version_count = 1;
|
||||
|
||||
m_save_thread =
|
||||
std::jthread([this](std::stop_token stop_token) { StoreSettingsThreadFunc(stop_token); });
|
||||
}
|
||||
|
||||
ISystemSettingsServer::~ISystemSettingsServer() {
|
||||
SetSaveNeeded();
|
||||
m_save_thread.request_stop();
|
||||
}
|
||||
|
||||
bool ISystemSettingsServer::LoadSettingsFile(std::filesystem::path& path, auto&& default_func) {
|
||||
@@ -1393,20 +1389,9 @@ void ISystemSettingsServer::StoreSettings() {
|
||||
}
|
||||
}
|
||||
|
||||
void ISystemSettingsServer::StoreSettingsThreadFunc(std::stop_token stop_token) {
|
||||
Common::SetCurrentThreadName("SettingsStore");
|
||||
|
||||
while (Common::StoppableTimedWait(stop_token, std::chrono::minutes(1))) {
|
||||
std::scoped_lock l{m_save_needed_mutex};
|
||||
if (!std::exchange(m_save_needed, false))
|
||||
continue;
|
||||
StoreSettings();
|
||||
}
|
||||
}
|
||||
|
||||
void ISystemSettingsServer::SetSaveNeeded() {
|
||||
std::scoped_lock l{m_save_needed_mutex};
|
||||
m_save_needed = true;
|
||||
StoreSettings();
|
||||
}
|
||||
|
||||
Result ISystemSettingsServer::GetSettingsItemValueImpl(std::span<u8> out_value, u64& out_size,
|
||||
|
||||
@@ -167,7 +167,6 @@ private:
|
||||
bool StoreSettingsFile(std::filesystem::path& path, auto& settings);
|
||||
void SetupSettings();
|
||||
void StoreSettings();
|
||||
void StoreSettingsThreadFunc(std::stop_token stop_token);
|
||||
void SetSaveNeeded();
|
||||
|
||||
Core::System& m_system;
|
||||
@@ -176,7 +175,6 @@ private:
|
||||
DeviceSettings m_device_settings{};
|
||||
ApplnSettings m_appln_settings{};
|
||||
std::mutex m_save_needed_mutex;
|
||||
std::jthread m_save_thread;
|
||||
bool m_save_needed{false};
|
||||
};
|
||||
|
||||
|
||||
@@ -18,7 +18,12 @@ endif()
|
||||
# Dynarmic project options
|
||||
option(DYNARMIC_ENABLE_CPU_FEATURE_DETECTION "Turning this off causes dynarmic to assume the host CPU doesn't support anything later than SSE3" ON)
|
||||
|
||||
option(DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT "Enables support for systems that require W^X" ${PLATFORM_OPENBSD})
|
||||
if (PLATFORM_OPENBSD OR PLATFORM_DRAGONFLY OR PLATFORM_NETBSD)
|
||||
set(REQUIRE_WX ON)
|
||||
else()
|
||||
set(REQUIRE_WX OFF)
|
||||
endif()
|
||||
option(DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT "Enables support for systems that require W^X" ${REQUIRE_WX})
|
||||
|
||||
option(DYNARMIC_IGNORE_ASSERTS "Ignore asserts" OFF)
|
||||
option(DYNARMIC_TESTS_USE_UNICORN "Enable fuzzing tests against unicorn" OFF)
|
||||
|
||||
@@ -87,9 +87,11 @@ A32EmitX64::A32EmitX64(BlockOfCode& code, A32::UserConfig conf, A32::Jit* jit_in
|
||||
code.PreludeComplete();
|
||||
ClearFastDispatchTable();
|
||||
|
||||
exception_handler.SetFastmemCallback([this](u64 rip_) {
|
||||
return FastmemCallback(rip_);
|
||||
});
|
||||
if (conf.fastmem_pointer.has_value()) {
|
||||
exception_handler.SetFastmemCallback([this](u64 rip_) {
|
||||
return FastmemCallback(rip_);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
A32EmitX64::~A32EmitX64() = default;
|
||||
|
||||
@@ -61,9 +61,11 @@ A64EmitX64::A64EmitX64(BlockOfCode& code, A64::UserConfig conf, A64::Jit* jit_in
|
||||
code.PreludeComplete();
|
||||
ClearFastDispatchTable();
|
||||
|
||||
exception_handler.SetFastmemCallback([this](u64 rip_) {
|
||||
return FastmemCallback(rip_);
|
||||
});
|
||||
if (conf.fastmem_pointer.has_value()) {
|
||||
exception_handler.SetFastmemCallback([this](u64 rip_) {
|
||||
return FastmemCallback(rip_);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
A64EmitX64::~A64EmitX64() = default;
|
||||
|
||||
@@ -87,18 +87,24 @@ public:
|
||||
// Waste a page to store the size
|
||||
size += DYNARMIC_PAGE_SIZE;
|
||||
|
||||
# if defined(MAP_ANONYMOUS)
|
||||
int mode = MAP_PRIVATE | MAP_ANONYMOUS;
|
||||
# elif defined(MAP_ANON)
|
||||
int mode = MAP_PRIVATE | MAP_ANON;
|
||||
# else
|
||||
# error "not supported"
|
||||
# endif
|
||||
# ifdef MAP_JIT
|
||||
int mode = MAP_PRIVATE;
|
||||
#if defined(MAP_ANONYMOUS)
|
||||
mode |= MAP_ANONYMOUS;
|
||||
#elif defined(MAP_ANON)
|
||||
mode |= MAP_ANON;
|
||||
#else
|
||||
# error "not supported"
|
||||
#endif
|
||||
#ifdef MAP_JIT
|
||||
mode |= MAP_JIT;
|
||||
# endif
|
||||
|
||||
void* p = mmap(nullptr, size, PROT_READ | PROT_WRITE, mode, -1, 0);
|
||||
#endif
|
||||
int prot = PROT_READ | PROT_WRITE;
|
||||
#ifdef PROT_MPROTECT
|
||||
// https://man.netbsd.org/mprotect.2 specifies that an mprotect() that is LESS
|
||||
// restrictive than the original mapping MUST fail
|
||||
prot |= PROT_MPROTECT(PROT_READ) | PROT_MPROTECT(PROT_WRITE) | PROT_MPROTECT(PROT_EXEC);
|
||||
#endif
|
||||
void* p = mmap(nullptr, size, prot, mode, -1, 0);
|
||||
if (p == MAP_FAILED) {
|
||||
using Xbyak::Error;
|
||||
XBYAK_THROW(Xbyak::ERR_CANT_ALLOC);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <optional>
|
||||
#include <xbyak/xbyak.h>
|
||||
|
||||
#include "dynarmic/backend/x64/abi.h"
|
||||
@@ -42,43 +42,46 @@ void EmitSpinLockUnlock(Xbyak::CodeGenerator& code, Xbyak::Reg64 ptr, Xbyak::Reg
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct SpinLockImpl {
|
||||
void Initialize();
|
||||
|
||||
void Initialize() noexcept;
|
||||
static void GlobalInitialize() noexcept;
|
||||
Xbyak::CodeGenerator code = Xbyak::CodeGenerator(4096, default_cg_mode);
|
||||
|
||||
void (*lock)(volatile int*);
|
||||
void (*unlock)(volatile int*);
|
||||
void (*lock)(volatile int*) = nullptr;
|
||||
void (*unlock)(volatile int*) = nullptr;
|
||||
};
|
||||
|
||||
std::once_flag flag;
|
||||
SpinLockImpl impl;
|
||||
|
||||
void SpinLockImpl::Initialize() {
|
||||
const Xbyak::Reg64 ABI_PARAM1 = Backend::X64::HostLocToReg64(Backend::X64::ABI_PARAM1);
|
||||
/// @brief Bear in mind that initializing the variable as-is on ctor time will trigger bugs
|
||||
/// because some OSes do not prepare mprotect() properly at static ctor time
|
||||
/// We can't really do anything about it, so just live with this fact
|
||||
std::optional<SpinLockImpl> impl;
|
||||
|
||||
void SpinLockImpl::Initialize() noexcept {
|
||||
Xbyak::Reg64 const ABI_PARAM1 = Backend::X64::HostLocToReg64(Backend::X64::ABI_PARAM1);
|
||||
code.align();
|
||||
lock = code.getCurr<void (*)(volatile int*)>();
|
||||
EmitSpinLockLock(code, ABI_PARAM1, code.eax);
|
||||
code.ret();
|
||||
|
||||
code.align();
|
||||
unlock = code.getCurr<void (*)(volatile int*)>();
|
||||
EmitSpinLockUnlock(code, ABI_PARAM1, code.eax);
|
||||
code.ret();
|
||||
}
|
||||
|
||||
void SpinLockImpl::GlobalInitialize() noexcept {
|
||||
impl.emplace();
|
||||
impl->Initialize();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void SpinLock::Lock() noexcept {
|
||||
std::call_once(flag, &SpinLockImpl::Initialize, impl);
|
||||
impl.lock(&storage);
|
||||
std::call_once(flag, &SpinLockImpl::GlobalInitialize);
|
||||
impl->lock(&storage);
|
||||
}
|
||||
|
||||
void SpinLock::Unlock() noexcept {
|
||||
std::call_once(flag, &SpinLockImpl::Initialize, impl);
|
||||
impl.unlock(&storage);
|
||||
std::call_once(flag, &SpinLockImpl::GlobalInitialize);
|
||||
impl->unlock(&storage);
|
||||
}
|
||||
|
||||
} // namespace Dynarmic
|
||||
|
||||
@@ -44,10 +44,20 @@ std::bitset<32> PersistentCallerSavedRegs() {
|
||||
return PERSISTENT_REGISTERS & Common::X64::ABI_ALL_CALLER_SAVED;
|
||||
}
|
||||
|
||||
/// @brief Must enforce W^X constraints, as we yet don't havea global "NO_EXECUTE" support flag
|
||||
/// the speed loss is minimal, and in fact may be negligible, however for your peace of mind
|
||||
/// I simply included known OSes whom had W^X issues
|
||||
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
|
||||
static const auto default_cg_mode = Xbyak::DontSetProtectRWE;
|
||||
#else
|
||||
static const auto default_cg_mode = nullptr; //Allow RWE
|
||||
#endif
|
||||
|
||||
class MacroJITx64Impl final : public Xbyak::CodeGenerator, public CachedMacro {
|
||||
public:
|
||||
explicit MacroJITx64Impl(Engines::Maxwell3D& maxwell3d_, const std::vector<u32>& code_)
|
||||
: CodeGenerator{MAX_CODE_SIZE}, code{code_}, maxwell3d{maxwell3d_} {
|
||||
: Xbyak::CodeGenerator(MAX_CODE_SIZE, default_cg_mode)
|
||||
, code{code_}, maxwell3d{maxwell3d_} {
|
||||
Compile();
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ using VideoCommon::FileEnvironment;
|
||||
using VideoCommon::GenericEnvironment;
|
||||
using VideoCommon::GraphicsEnvironment;
|
||||
|
||||
constexpr u32 CACHE_VERSION = 13;
|
||||
constexpr u32 CACHE_VERSION = 14;
|
||||
constexpr std::array<char, 8> VULKAN_CACHE_MAGIC_NUMBER{'y', 'u', 'z', 'u', 'v', 'k', 'c', 'h'};
|
||||
|
||||
template <typename Container>
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "yuzu/configuration/configure_per_game.h"
|
||||
#include "yuzu/configuration/configure_per_game_addons.h"
|
||||
#include "yuzu/configuration/configure_system.h"
|
||||
#include "yuzu/configuration/configure_network.h"
|
||||
#include "qt_common/config/uisettings.h"
|
||||
#include "yuzu/util/util.h"
|
||||
#include "yuzu/vk_device_info.h"
|
||||
@@ -69,6 +70,7 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::st
|
||||
input_tab = std::make_unique<ConfigureInputPerGame>(system_, game_config.get(), this);
|
||||
linux_tab = std::make_unique<ConfigureLinuxTab>(system_, tab_group, *builder, this);
|
||||
system_tab = std::make_unique<ConfigureSystem>(system_, tab_group, *builder, this);
|
||||
network_tab = std::make_unique<ConfigureNetwork>(system_, this);
|
||||
|
||||
ui->setupUi(this);
|
||||
|
||||
@@ -80,6 +82,7 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::st
|
||||
ui->tabWidget->addTab(graphics_extensions_tab.get(), tr("GPU Extensions"));
|
||||
ui->tabWidget->addTab(audio_tab.get(), tr("Audio"));
|
||||
ui->tabWidget->addTab(input_tab.get(), tr("Input Profiles"));
|
||||
ui->tabWidget->addTab(network_tab.get(), tr("Network"));
|
||||
|
||||
// Only show Linux tab on Unix
|
||||
linux_tab->setVisible(false);
|
||||
@@ -113,6 +116,7 @@ void ConfigurePerGame::ApplyConfiguration() {
|
||||
}
|
||||
addons_tab->ApplyConfiguration();
|
||||
input_tab->ApplyConfiguration();
|
||||
network_tab->ApplyConfiguration();
|
||||
|
||||
if (Settings::IsDockedMode() && Settings::values.players.GetValue()[0].controller_type ==
|
||||
Settings::ControllerType::Handheld) {
|
||||
|
||||
@@ -38,6 +38,7 @@ class ConfigureGraphicsExtensions;
|
||||
class ConfigureInputPerGame;
|
||||
class ConfigureLinuxTab;
|
||||
class ConfigureSystem;
|
||||
class ConfigureNetwork;
|
||||
|
||||
class QGraphicsScene;
|
||||
class QStandardItem;
|
||||
@@ -93,4 +94,5 @@ private:
|
||||
std::unique_ptr<ConfigureInputPerGame> input_tab;
|
||||
std::unique_ptr<ConfigureLinuxTab> linux_tab;
|
||||
std::unique_ptr<ConfigureSystem> system_tab;
|
||||
std::unique_ptr<ConfigureNetwork> network_tab;
|
||||
};
|
||||
|
||||
@@ -160,20 +160,20 @@
|
||||
<property name="title">
|
||||
<string>Am&iibo</string>
|
||||
</property>
|
||||
<addaction name="action_Load_Cabinet_Nickname_Owner"/>
|
||||
<addaction name="action_Load_Cabinet_Eraser"/>
|
||||
<addaction name="action_Load_Cabinet_Restorer"/>
|
||||
<addaction name="action_Load_Cabinet_Formatter"/>
|
||||
<addaction name="action_Launch_Cabinet_Nickname_Owner"/>
|
||||
<addaction name="action_Launch_Cabinet_Eraser"/>
|
||||
<addaction name="action_Launch_Cabinet_Restorer"/>
|
||||
<addaction name="action_Launch_Cabinet_Formatter"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_Applets">
|
||||
<property name="title">
|
||||
<string>&Applets</string>
|
||||
<string>Launch &Applet</string>
|
||||
</property>
|
||||
<addaction name="action_Load_Home_Menu"/>
|
||||
<addaction name="action_Load_Album"/>
|
||||
<addaction name="action_Load_Mii_Edit"/>
|
||||
<addaction name="action_Open_Controller_Menu"/>
|
||||
<addaction name="action_Open_Setup"/>
|
||||
<addaction name="action_Launch_QLaunch"/>
|
||||
<addaction name="action_Launch_MiiEdit"/>
|
||||
<addaction name="action_Launch_Controller"/>
|
||||
<addaction name="action_Launch_Setup"/>
|
||||
<addaction name="action_Launch_PhotoViewer"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuTAS">
|
||||
<property name="title">
|
||||
@@ -420,34 +420,34 @@
|
||||
<string>&Capture Screenshot</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Load_Album">
|
||||
<action name="action_Launch_PhotoViewer">
|
||||
<property name="text">
|
||||
<string>Open &Album</string>
|
||||
<string>&Album</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Load_Cabinet_Nickname_Owner">
|
||||
<action name="action_Launch_Cabinet_Nickname_Owner">
|
||||
<property name="text">
|
||||
<string>&Set Nickname and Owner</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Load_Cabinet_Eraser">
|
||||
<action name="action_Launch_Cabinet_Eraser">
|
||||
<property name="text">
|
||||
<string>&Delete Game Data</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Load_Cabinet_Restorer">
|
||||
<action name="action_Launch_Cabinet_Restorer">
|
||||
<property name="text">
|
||||
<string>&Restore Amiibo</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Load_Cabinet_Formatter">
|
||||
<action name="action_Launch_Cabinet_Formatter">
|
||||
<property name="text">
|
||||
<string>&Format Amiibo</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Load_Mii_Edit">
|
||||
<action name="action_Launch_MiiEdit">
|
||||
<property name="text">
|
||||
<string>Open &Mii Editor</string>
|
||||
<string>&Mii Editor</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Configure_Tas">
|
||||
@@ -493,7 +493,7 @@
|
||||
<string>R&ecord</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Open_Controller_Menu">
|
||||
<action name="action_Launch_Controller">
|
||||
<property name="text">
|
||||
<string>Open &Controller Menu</string>
|
||||
</property>
|
||||
@@ -503,14 +503,14 @@
|
||||
<string>Install Decryption &Keys</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Load_Home_Menu">
|
||||
<action name="action_Launch_QLaunch">
|
||||
<property name="text">
|
||||
<string>Open &Home Menu</string>
|
||||
<string>&Home Menu</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Open_Setup">
|
||||
<action name="action_Launch_Setup">
|
||||
<property name="text">
|
||||
<string>Open &Setup</string>
|
||||
<string>&Setup</string>
|
||||
</property>
|
||||
<property name="menuRole">
|
||||
<enum>QAction::MenuRole::TextHeuristicRole</enum>
|
||||
|
||||
@@ -705,13 +705,13 @@ MainWindow::MainWindow(bool has_broken_vulkan)
|
||||
}
|
||||
|
||||
if (should_launch_setup) {
|
||||
OnInitialSetup();
|
||||
LaunchFirmwareApplet(Service::AM::AppletProgramId::Starter, std::nullopt);
|
||||
} else {
|
||||
if (!game_path.isEmpty()) {
|
||||
BootGame(game_path, ApplicationAppletParameters());
|
||||
} else {
|
||||
if (should_launch_qlaunch) {
|
||||
OnHomeMenu();
|
||||
LaunchFirmwareApplet(Service::AM::AppletProgramId::QLaunch, std::nullopt);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1661,19 +1661,35 @@ void MainWindow::ConnectMenuEvents() {
|
||||
connect(multiplayer_state, &MultiplayerState::SaveConfig, this, &MainWindow::OnSaveConfig);
|
||||
|
||||
// Tools
|
||||
connect_menu(ui->action_Load_Album, &MainWindow::OnAlbum);
|
||||
connect_menu(ui->action_Load_Cabinet_Nickname_Owner,
|
||||
[this]() { OnCabinet(Service::NFP::CabinetMode::StartNicknameAndOwnerSettings); });
|
||||
connect_menu(ui->action_Load_Cabinet_Eraser,
|
||||
[this]() { OnCabinet(Service::NFP::CabinetMode::StartGameDataEraser); });
|
||||
connect_menu(ui->action_Load_Cabinet_Restorer,
|
||||
[this]() { OnCabinet(Service::NFP::CabinetMode::StartRestorer); });
|
||||
connect_menu(ui->action_Load_Cabinet_Formatter,
|
||||
[this]() { OnCabinet(Service::NFP::CabinetMode::StartFormatter); });
|
||||
connect_menu(ui->action_Load_Mii_Edit, &MainWindow::OnMiiEdit);
|
||||
connect_menu(ui->action_Open_Controller_Menu, &MainWindow::OnOpenControllerMenu);
|
||||
connect_menu(ui->action_Load_Home_Menu, &MainWindow::OnHomeMenu);
|
||||
connect_menu(ui->action_Open_Setup, &MainWindow::OnInitialSetup);
|
||||
connect_menu(ui->action_Launch_PhotoViewer, [this]{
|
||||
LaunchFirmwareApplet(Service::AM::AppletProgramId::PhotoViewer, std::nullopt);
|
||||
});
|
||||
connect_menu(ui->action_Launch_MiiEdit, [this]{
|
||||
LaunchFirmwareApplet(Service::AM::AppletProgramId::MiiEdit, std::nullopt);
|
||||
});
|
||||
connect_menu(ui->action_Launch_Controller, [this]{
|
||||
LaunchFirmwareApplet(Service::AM::AppletProgramId::Controller, std::nullopt);
|
||||
});
|
||||
connect_menu(ui->action_Launch_QLaunch, [this]{
|
||||
LaunchFirmwareApplet(Service::AM::AppletProgramId::QLaunch, std::nullopt);
|
||||
});
|
||||
connect_menu(ui->action_Launch_Setup, [this]{
|
||||
LaunchFirmwareApplet(Service::AM::AppletProgramId::Starter, std::nullopt);
|
||||
});
|
||||
// Tools (cabinet)
|
||||
connect_menu(ui->action_Launch_Cabinet_Nickname_Owner, [this]{
|
||||
LaunchFirmwareApplet(Service::AM::AppletProgramId::Cabinet, {Service::NFP::CabinetMode::StartNicknameAndOwnerSettings});
|
||||
});
|
||||
connect_menu(ui->action_Launch_Cabinet_Eraser, [this]{
|
||||
LaunchFirmwareApplet(Service::AM::AppletProgramId::Cabinet, {Service::NFP::CabinetMode::StartGameDataEraser});
|
||||
});
|
||||
connect_menu(ui->action_Launch_Cabinet_Restorer, [this]{
|
||||
LaunchFirmwareApplet(Service::AM::AppletProgramId::Cabinet, {Service::NFP::CabinetMode::StartRestorer});
|
||||
});
|
||||
connect_menu(ui->action_Launch_Cabinet_Formatter, [this]{
|
||||
LaunchFirmwareApplet(Service::AM::AppletProgramId::Cabinet, {Service::NFP::CabinetMode::StartFormatter});
|
||||
});
|
||||
|
||||
connect_menu(ui->action_Desktop, &MainWindow::OnCreateHomeMenuDesktopShortcut);
|
||||
connect_menu(ui->action_Application_Menu,
|
||||
&MainWindow::OnCreateHomeMenuApplicationMenuShortcut);
|
||||
@@ -1714,14 +1730,16 @@ void MainWindow::UpdateMenuState() {
|
||||
ui->action_Pause,
|
||||
};
|
||||
|
||||
const std::array applet_actions{ui->action_Load_Album,
|
||||
ui->action_Load_Cabinet_Nickname_Owner,
|
||||
ui->action_Load_Cabinet_Eraser,
|
||||
ui->action_Load_Cabinet_Restorer,
|
||||
ui->action_Load_Cabinet_Formatter,
|
||||
ui->action_Load_Mii_Edit,
|
||||
ui->action_Load_Home_Menu,
|
||||
ui->action_Open_Controller_Menu};
|
||||
const std::array applet_actions{
|
||||
ui->action_Launch_PhotoViewer,
|
||||
ui->action_Launch_Cabinet_Nickname_Owner,
|
||||
ui->action_Launch_Cabinet_Eraser,
|
||||
ui->action_Launch_Cabinet_Restorer,
|
||||
ui->action_Launch_Cabinet_Formatter,
|
||||
ui->action_Launch_MiiEdit,
|
||||
ui->action_Launch_QLaunch,
|
||||
ui->action_Launch_Controller
|
||||
};
|
||||
|
||||
for (QAction* action : running_actions) {
|
||||
action->setEnabled(emulation_running);
|
||||
@@ -3960,157 +3978,61 @@ void MainWindow::OnGameListRefresh()
|
||||
SetFirmwareVersion();
|
||||
}
|
||||
|
||||
void MainWindow::OnAlbum() {
|
||||
constexpr u64 AlbumId = static_cast<u64>(Service::AM::AppletProgramId::PhotoViewer);
|
||||
auto bis_system = QtCommon::system->GetFileSystemController().GetSystemNANDContents();
|
||||
if (!bis_system) {
|
||||
QMessageBox::warning(this, tr("No firmware available"),
|
||||
tr("Please install firmware to use the Album applet."));
|
||||
return;
|
||||
}
|
||||
|
||||
auto album_nca = bis_system->GetEntry(AlbumId, FileSys::ContentRecordType::Program);
|
||||
if (!album_nca) {
|
||||
QMessageBox::warning(this, tr("Album Applet"),
|
||||
tr("Album applet is not available. Please reinstall firmware."));
|
||||
return;
|
||||
}
|
||||
|
||||
QtCommon::system->GetFrontendAppletHolder().SetCurrentAppletId(Service::AM::AppletId::PhotoViewer);
|
||||
|
||||
const auto filename = QString::fromStdString(album_nca->GetFullPath());
|
||||
UISettings::values.roms_path = QFileInfo(filename).path().toStdString();
|
||||
BootGame(filename, LibraryAppletParameters(AlbumId, Service::AM::AppletId::PhotoViewer));
|
||||
}
|
||||
|
||||
void MainWindow::OnCabinet(Service::NFP::CabinetMode mode) {
|
||||
constexpr u64 CabinetId = static_cast<u64>(Service::AM::AppletProgramId::Cabinet);
|
||||
auto bis_system = QtCommon::system->GetFileSystemController().GetSystemNANDContents();
|
||||
if (!bis_system) {
|
||||
QMessageBox::warning(this, tr("No firmware available"),
|
||||
tr("Please install firmware to use the Cabinet applet."));
|
||||
return;
|
||||
}
|
||||
|
||||
auto cabinet_nca = bis_system->GetEntry(CabinetId, FileSys::ContentRecordType::Program);
|
||||
if (!cabinet_nca) {
|
||||
QMessageBox::warning(this, tr("Cabinet Applet"),
|
||||
tr("Cabinet applet is not available. Please reinstall firmware."));
|
||||
return;
|
||||
}
|
||||
|
||||
QtCommon::system->GetFrontendAppletHolder().SetCurrentAppletId(Service::AM::AppletId::Cabinet);
|
||||
QtCommon::system->GetFrontendAppletHolder().SetCabinetMode(mode);
|
||||
|
||||
const auto filename = QString::fromStdString(cabinet_nca->GetFullPath());
|
||||
UISettings::values.roms_path = QFileInfo(filename).path().toStdString();
|
||||
BootGame(filename, LibraryAppletParameters(CabinetId, Service::AM::AppletId::Cabinet));
|
||||
}
|
||||
|
||||
void MainWindow::OnMiiEdit() {
|
||||
constexpr u64 MiiEditId = static_cast<u64>(Service::AM::AppletProgramId::MiiEdit);
|
||||
auto bis_system = QtCommon::system->GetFileSystemController().GetSystemNANDContents();
|
||||
if (!bis_system) {
|
||||
QMessageBox::warning(this, tr("No firmware available"),
|
||||
tr("Please install firmware to use the Mii editor."));
|
||||
return;
|
||||
}
|
||||
|
||||
auto mii_applet_nca = bis_system->GetEntry(MiiEditId, FileSys::ContentRecordType::Program);
|
||||
if (!mii_applet_nca) {
|
||||
QMessageBox::warning(this, tr("Mii Edit Applet"),
|
||||
tr("Mii editor is not available. Please reinstall firmware."));
|
||||
return;
|
||||
}
|
||||
|
||||
QtCommon::system->GetFrontendAppletHolder().SetCurrentAppletId(Service::AM::AppletId::MiiEdit);
|
||||
|
||||
const auto filename = QString::fromStdString((mii_applet_nca->GetFullPath()));
|
||||
UISettings::values.roms_path = QFileInfo(filename).path().toStdString();
|
||||
BootGame(filename, LibraryAppletParameters(MiiEditId, Service::AM::AppletId::MiiEdit));
|
||||
}
|
||||
|
||||
void MainWindow::OnOpenControllerMenu() {
|
||||
constexpr u64 ControllerAppletId = static_cast<u64>(Service::AM::AppletProgramId::Controller);
|
||||
auto bis_system = QtCommon::system->GetFileSystemController().GetSystemNANDContents();
|
||||
if (!bis_system) {
|
||||
QMessageBox::warning(this, tr("No firmware available"),
|
||||
tr("Please install firmware to use the Controller Menu."));
|
||||
return;
|
||||
}
|
||||
|
||||
auto controller_applet_nca =
|
||||
bis_system->GetEntry(ControllerAppletId, FileSys::ContentRecordType::Program);
|
||||
if (!controller_applet_nca) {
|
||||
QMessageBox::warning(this, tr("Controller Applet"),
|
||||
tr("Controller Menu is not available. Please reinstall firmware."));
|
||||
return;
|
||||
}
|
||||
|
||||
QtCommon::system->GetFrontendAppletHolder().SetCurrentAppletId(Service::AM::AppletId::Controller);
|
||||
|
||||
const auto filename = QString::fromStdString((controller_applet_nca->GetFullPath()));
|
||||
UISettings::values.roms_path = QFileInfo(filename).path().toStdString();
|
||||
BootGame(filename,
|
||||
LibraryAppletParameters(ControllerAppletId, Service::AM::AppletId::Controller));
|
||||
}
|
||||
|
||||
void MainWindow::OnHomeMenu() {
|
||||
void MainWindow::LaunchFirmwareApplet(Service::AM::AppletProgramId program_id, std::optional<Service::NFP::CabinetMode> cabinet_mode) {
|
||||
auto result = FirmwareManager::VerifyFirmware(*QtCommon::system.get());
|
||||
|
||||
using namespace QtCommon::StringLookup;
|
||||
|
||||
switch (result) {
|
||||
case FirmwareManager::ErrorFirmwareMissing:
|
||||
QMessageBox::warning(this, tr("No firmware available"),
|
||||
Lookup(FwCheckErrorFirmwareMissing));
|
||||
QMessageBox::warning(this, tr("No firmware available"), Lookup(FwCheckErrorFirmwareMissing));
|
||||
return;
|
||||
case FirmwareManager::ErrorFirmwareCorrupted:
|
||||
QMessageBox::warning(this, tr("Firmware Corrupted"),
|
||||
Lookup(FwCheckErrorFirmwareCorrupted));
|
||||
QMessageBox::warning(this, tr("Firmware Corrupted"), Lookup(FwCheckErrorFirmwareCorrupted));
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
constexpr u64 QLaunchId = static_cast<u64>(Service::AM::AppletProgramId::QLaunch);
|
||||
auto bis_system = QtCommon::system->GetFileSystemController().GetSystemNANDContents();
|
||||
|
||||
auto qlaunch_applet_nca = bis_system->GetEntry(QLaunchId, FileSys::ContentRecordType::Program);
|
||||
if (!qlaunch_applet_nca) {
|
||||
QMessageBox::warning(this, tr("Home Menu Applet"),
|
||||
tr("Home Menu is not available. Please reinstall firmware."));
|
||||
return;
|
||||
if (auto applet_nca = bis_system->GetEntry(u64(program_id), FileSys::ContentRecordType::Program); applet_nca) {
|
||||
if (auto const applet_id = [program_id] {
|
||||
using namespace Service::AM;
|
||||
switch (program_id) {
|
||||
case AppletProgramId::OverlayDisplay: return AppletId::OverlayDisplay;
|
||||
case AppletProgramId::QLaunch: return AppletId::QLaunch;
|
||||
case AppletProgramId::Starter: return AppletId::Starter;
|
||||
case AppletProgramId::Auth: return AppletId::Auth;
|
||||
case AppletProgramId::Cabinet: return AppletId::Cabinet;
|
||||
case AppletProgramId::Controller: return AppletId::Controller;
|
||||
case AppletProgramId::DataErase: return AppletId::DataErase;
|
||||
case AppletProgramId::Error: return AppletId::Error;
|
||||
case AppletProgramId::NetConnect: return AppletId::NetConnect;
|
||||
case AppletProgramId::ProfileSelect: return AppletId::ProfileSelect;
|
||||
case AppletProgramId::SoftwareKeyboard: return AppletId::SoftwareKeyboard;
|
||||
case AppletProgramId::MiiEdit: return AppletId::MiiEdit;
|
||||
case AppletProgramId::Web: return AppletId::Web;
|
||||
case AppletProgramId::Shop: return AppletId::Shop;
|
||||
case AppletProgramId::PhotoViewer: return AppletId::PhotoViewer;
|
||||
case AppletProgramId::Settings: return AppletId::Settings;
|
||||
case AppletProgramId::OfflineWeb: return AppletId::OfflineWeb;
|
||||
case AppletProgramId::LoginShare: return AppletId::LoginShare;
|
||||
case AppletProgramId::WebAuth: return AppletId::WebAuth;
|
||||
case AppletProgramId::MyPage: return AppletId::MyPage;
|
||||
default: return AppletId::None;
|
||||
}
|
||||
|
||||
QtCommon::system->GetFrontendAppletHolder().SetCurrentAppletId(Service::AM::AppletId::QLaunch);
|
||||
|
||||
const auto filename = QString::fromStdString((qlaunch_applet_nca->GetFullPath()));
|
||||
}(); applet_id != Service::AM::AppletId::None) {
|
||||
QtCommon::system->GetFrontendAppletHolder().SetCurrentAppletId(applet_id);
|
||||
if (cabinet_mode)
|
||||
QtCommon::system->GetFrontendAppletHolder().SetCabinetMode(*cabinet_mode);
|
||||
// ?
|
||||
auto const filename = QString::fromStdString((applet_nca->GetFullPath()));
|
||||
UISettings::values.roms_path = QFileInfo(filename).path().toStdString();
|
||||
BootGame(filename, LibraryAppletParameters(QLaunchId, Service::AM::AppletId::QLaunch));
|
||||
}
|
||||
|
||||
void MainWindow::OnInitialSetup() {
|
||||
constexpr u64 Starter = static_cast<u64>(Service::AM::AppletProgramId::Starter);
|
||||
auto bis_system = QtCommon::system->GetFileSystemController().GetSystemNANDContents();
|
||||
if (!bis_system) {
|
||||
QMessageBox::warning(this, tr("No firmware available"),
|
||||
tr("Please install firmware to use Starter."));
|
||||
return;
|
||||
BootGame(filename, LibraryAppletParameters(u64(program_id), applet_id));
|
||||
} else {
|
||||
QMessageBox::warning(this, tr("Unknown applet"), tr("Applet doesn't map to a known value."));
|
||||
}
|
||||
} else {
|
||||
QMessageBox::warning(this, tr("Record not found"), tr("Applet not found. Please reinstall firmware."));
|
||||
}
|
||||
|
||||
auto qlaunch_nca = bis_system->GetEntry(Starter, FileSys::ContentRecordType::Program);
|
||||
if (!qlaunch_nca) {
|
||||
QMessageBox::warning(this, tr("Starter Applet"),
|
||||
tr("Starter is not available. Please reinstall firmware."));
|
||||
return;
|
||||
}
|
||||
|
||||
QtCommon::system->GetFrontendAppletHolder().SetCurrentAppletId(Service::AM::AppletId::Starter);
|
||||
|
||||
const auto filename = QString::fromStdString((qlaunch_nca->GetFullPath()));
|
||||
UISettings::values.roms_path = QFileInfo(filename).path().toStdString();
|
||||
BootGame(filename, LibraryAppletParameters(Starter, Service::AM::AppletId::Starter));
|
||||
}
|
||||
|
||||
void MainWindow::OnCreateHomeMenuDesktopShortcut() {
|
||||
|
||||
@@ -101,6 +101,7 @@ class InputSubsystem;
|
||||
namespace Service::AM {
|
||||
struct FrontendAppletParameters;
|
||||
enum class AppletId : u32;
|
||||
enum class AppletProgramId : u64;
|
||||
} // namespace Service::AM
|
||||
|
||||
namespace Service::AM::Frontend {
|
||||
@@ -399,12 +400,7 @@ private slots:
|
||||
void ResetWindowSize720();
|
||||
void ResetWindowSize900();
|
||||
void ResetWindowSize1080();
|
||||
void OnAlbum();
|
||||
void OnCabinet(Service::NFP::CabinetMode mode);
|
||||
void OnMiiEdit();
|
||||
void OnOpenControllerMenu();
|
||||
void OnHomeMenu();
|
||||
void OnInitialSetup();
|
||||
void LaunchFirmwareApplet(Service::AM::AppletProgramId program_id, std::optional<Service::NFP::CabinetMode> mode);
|
||||
void OnCreateHomeMenuDesktopShortcut();
|
||||
void OnCreateHomeMenuApplicationMenuShortcut();
|
||||
void OnCaptureScreenshot();
|
||||
@@ -428,7 +424,6 @@ private:
|
||||
bool SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id,
|
||||
u64* selected_title_id, u8* selected_content_record_type);
|
||||
ContentManager::InstallResult InstallNCA(const QString& filename);
|
||||
void MigrateConfigFiles();
|
||||
void UpdateWindowTitle(std::string_view title_name = {}, std::string_view title_version = {},
|
||||
std::string_view gpu_vendor = {});
|
||||
void UpdateDockedButton();
|
||||
|
||||
Reference in New Issue
Block a user