diff options
82 files changed, 1888 insertions, 1189 deletions
@@ -7,7 +7,7 @@ yuzu is an experimental open-source emulator for the Nintendo Switch from the cr It is written in C++ with portability in mind, with builds actively maintained for Windows, Linux and macOS. The emulator is currently only useful for homebrew development and research purposes. -yuzu only emulates a subset of Switch hardware and therefore is generally only useful for running/debugging homebrew applications. At this time, yuzu cannot play any commercial games without major problems. yuzu can boot some games, to varying degrees of success. +yuzu only emulates a subset of Switch hardware and therefore is generally only useful for running/debugging homebrew applications. yuzu can boot some games, to varying degrees of success. yuzu is licensed under the GPLv2 (or any later version). Refer to the license.txt file included. diff --git a/src/audio_core/stream.cpp b/src/audio_core/stream.cpp index 22a3f8c84..11481a776 100644 --- a/src/audio_core/stream.cpp +++ b/src/audio_core/stream.cpp @@ -57,7 +57,9 @@ Stream::State Stream::GetState() const { s64 Stream::GetBufferReleaseCycles(const Buffer& buffer) const { const std::size_t num_samples{buffer.GetSamples().size() / GetNumChannels()}; - return Core::Timing::usToCycles((static_cast<u64>(num_samples) * 1000000) / sample_rate); + const auto us = + std::chrono::microseconds((static_cast<u64>(num_samples) * 1000000) / sample_rate); + return Core::Timing::usToCycles(us); } static void VolumeAdjustSamples(std::vector<s16>& samples) { diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index a56e526a6..6bf512e12 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -328,6 +328,9 @@ add_library(core STATIC hle/service/nim/nim.h hle/service/npns/npns.cpp hle/service/npns/npns.h + hle/service/ns/errors.h + hle/service/ns/language.cpp + hle/service/ns/language.h hle/service/ns/ns.cpp hle/service/ns/ns.h hle/service/ns/pl_u.cpp diff --git a/src/core/core.cpp b/src/core/core.cpp index 7106151bd..ff0721079 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -18,11 +18,6 @@ #include "core/file_sys/registered_cache.h" #include "core/file_sys/vfs_concat.h" #include "core/file_sys/vfs_real.h" -#include "core/frontend/applets/error.h" -#include "core/frontend/applets/general_frontend.h" -#include "core/frontend/applets/profile_select.h" -#include "core/frontend/applets/software_keyboard.h" -#include "core/frontend/applets/web_browser.h" #include "core/gdbstub/gdbstub.h" #include "core/hle/kernel/client_port.h" #include "core/hle/kernel/kernel.h" @@ -37,9 +32,6 @@ #include "core/settings.h" #include "core/telemetry_session.h" #include "file_sys/cheat_engine.h" -#include "frontend/applets/profile_select.h" -#include "frontend/applets/software_keyboard.h" -#include "frontend/applets/web_browser.h" #include "video_core/debug_utils/debug_utils.h" #include "video_core/renderer_base.h" #include "video_core/video_core.h" @@ -144,20 +136,10 @@ struct System::Impl { ResultStatus Load(System& system, Frontend::EmuWindow& emu_window, const std::string& filepath) { app_loader = Loader::GetLoader(GetGameFileFromPath(virtual_filesystem, filepath)); - if (!app_loader) { LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath); return ResultStatus::ErrorGetLoader; } - std::pair<std::optional<u32>, Loader::ResultStatus> system_mode = - app_loader->LoadKernelSystemMode(); - - if (system_mode.second != Loader::ResultStatus::Success) { - LOG_CRITICAL(Core, "Failed to determine system mode (Error {})!", - static_cast<int>(system_mode.second)); - - return ResultStatus::ErrorSystemMode; - } ResultStatus init_result{Init(system, emu_window)}; if (init_result != ResultStatus::Success) { @@ -167,6 +149,7 @@ struct System::Impl { return init_result; } + telemetry_session->AddInitialInfo(*app_loader); auto main_process = Kernel::Process::Create(system, "main"); const auto [load_result, load_parameters] = app_loader->Load(*main_process); if (load_result != Loader::ResultStatus::Success) { diff --git a/src/core/core.h b/src/core/core.h index a9a756a4c..20959de54 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -98,7 +98,6 @@ public: Success, ///< Succeeded ErrorNotInitialized, ///< Error trying to use core prior to initialization ErrorGetLoader, ///< Error finding the correct application loader - ErrorSystemMode, ///< Error determining the system mode ErrorSystemFiles, ///< Error in finding system files ErrorSharedFont, ///< Error in finding shared font ErrorVideoCore, ///< Error in the video core diff --git a/src/core/core_timing_util.cpp b/src/core/core_timing_util.cpp index c0f08cddb..a10472a95 100644 --- a/src/core/core_timing_util.cpp +++ b/src/core/core_timing_util.cpp @@ -13,52 +13,40 @@ namespace Core::Timing { constexpr u64 MAX_VALUE_TO_MULTIPLY = std::numeric_limits<s64>::max() / BASE_CLOCK_RATE; -s64 usToCycles(s64 us) { - if (static_cast<u64>(us / 1000000) > MAX_VALUE_TO_MULTIPLY) { +s64 msToCycles(std::chrono::milliseconds ms) { + if (static_cast<u64>(ms.count() / 1000) > MAX_VALUE_TO_MULTIPLY) { LOG_ERROR(Core_Timing, "Integer overflow, use max value"); return std::numeric_limits<s64>::max(); } - if (static_cast<u64>(us) > MAX_VALUE_TO_MULTIPLY) { + if (static_cast<u64>(ms.count()) > MAX_VALUE_TO_MULTIPLY) { LOG_DEBUG(Core_Timing, "Time very big, do rounding"); - return BASE_CLOCK_RATE * (us / 1000000); + return BASE_CLOCK_RATE * (ms.count() / 1000); } - return (BASE_CLOCK_RATE * us) / 1000000; + return (BASE_CLOCK_RATE * ms.count()) / 1000; } -s64 usToCycles(u64 us) { - if (us / 1000000 > MAX_VALUE_TO_MULTIPLY) { +s64 usToCycles(std::chrono::microseconds us) { + if (static_cast<u64>(us.count() / 1000000) > MAX_VALUE_TO_MULTIPLY) { LOG_ERROR(Core_Timing, "Integer overflow, use max value"); return std::numeric_limits<s64>::max(); } - if (us > MAX_VALUE_TO_MULTIPLY) { + if (static_cast<u64>(us.count()) > MAX_VALUE_TO_MULTIPLY) { LOG_DEBUG(Core_Timing, "Time very big, do rounding"); - return BASE_CLOCK_RATE * static_cast<s64>(us / 1000000); + return BASE_CLOCK_RATE * (us.count() / 1000000); } - return (BASE_CLOCK_RATE * static_cast<s64>(us)) / 1000000; + return (BASE_CLOCK_RATE * us.count()) / 1000000; } -s64 nsToCycles(s64 ns) { - if (static_cast<u64>(ns / 1000000000) > MAX_VALUE_TO_MULTIPLY) { +s64 nsToCycles(std::chrono::nanoseconds ns) { + if (static_cast<u64>(ns.count() / 1000000000) > MAX_VALUE_TO_MULTIPLY) { LOG_ERROR(Core_Timing, "Integer overflow, use max value"); return std::numeric_limits<s64>::max(); } - if (static_cast<u64>(ns) > MAX_VALUE_TO_MULTIPLY) { + if (static_cast<u64>(ns.count()) > MAX_VALUE_TO_MULTIPLY) { LOG_DEBUG(Core_Timing, "Time very big, do rounding"); - return BASE_CLOCK_RATE * (ns / 1000000000); + return BASE_CLOCK_RATE * (ns.count() / 1000000000); } - return (BASE_CLOCK_RATE * ns) / 1000000000; -} - -s64 nsToCycles(u64 ns) { - if (ns / 1000000000 > MAX_VALUE_TO_MULTIPLY) { - LOG_ERROR(Core_Timing, "Integer overflow, use max value"); - return std::numeric_limits<s64>::max(); - } - if (ns > MAX_VALUE_TO_MULTIPLY) { - LOG_DEBUG(Core_Timing, "Time very big, do rounding"); - return BASE_CLOCK_RATE * (static_cast<s64>(ns) / 1000000000); - } - return (BASE_CLOCK_RATE * static_cast<s64>(ns)) / 1000000000; + return (BASE_CLOCK_RATE * ns.count()) / 1000000000; } u64 CpuCyclesToClockCycles(u64 ticks) { diff --git a/src/core/core_timing_util.h b/src/core/core_timing_util.h index 679aa3123..cdd84d70f 100644 --- a/src/core/core_timing_util.h +++ b/src/core/core_timing_util.h @@ -4,6 +4,7 @@ #pragma once +#include <chrono> #include "common/common_types.h" namespace Core::Timing { @@ -13,53 +14,20 @@ namespace Core::Timing { constexpr u64 BASE_CLOCK_RATE = 1019215872; // Switch clock speed is 1020MHz un/docked constexpr u64 CNTFREQ = 19200000; // Value from fusee. -inline s64 msToCycles(int ms) { - // since ms is int there is no way to overflow - return BASE_CLOCK_RATE * static_cast<s64>(ms) / 1000; -} - -inline s64 msToCycles(float ms) { - return static_cast<s64>(BASE_CLOCK_RATE * (0.001f) * ms); -} - -inline s64 msToCycles(double ms) { - return static_cast<s64>(BASE_CLOCK_RATE * (0.001) * ms); -} - -inline s64 usToCycles(float us) { - return static_cast<s64>(BASE_CLOCK_RATE * (0.000001f) * us); -} - -inline s64 usToCycles(int us) { - return (BASE_CLOCK_RATE * static_cast<s64>(us) / 1000000); -} - -s64 usToCycles(s64 us); - -s64 usToCycles(u64 us); - -inline s64 nsToCycles(float ns) { - return static_cast<s64>(BASE_CLOCK_RATE * (0.000000001f) * ns); -} - -inline s64 nsToCycles(int ns) { - return BASE_CLOCK_RATE * static_cast<s64>(ns) / 1000000000; -} - -s64 nsToCycles(s64 ns); - -s64 nsToCycles(u64 ns); +s64 msToCycles(std::chrono::milliseconds ms); +s64 usToCycles(std::chrono::microseconds us); +s64 nsToCycles(std::chrono::nanoseconds ns); -inline u64 cyclesToNs(s64 cycles) { - return cycles * 1000000000 / BASE_CLOCK_RATE; +inline std::chrono::milliseconds CyclesToMs(s64 cycles) { + return std::chrono::milliseconds(cycles * 1000 / BASE_CLOCK_RATE); } -inline s64 cyclesToUs(s64 cycles) { - return cycles * 1000000 / BASE_CLOCK_RATE; +inline std::chrono::nanoseconds CyclesToNs(s64 cycles) { + return std::chrono::nanoseconds(cycles * 1000000000 / BASE_CLOCK_RATE); } -inline u64 cyclesToMs(s64 cycles) { - return cycles * 1000 / BASE_CLOCK_RATE; +inline std::chrono::microseconds CyclesToUs(s64 cycles) { + return std::chrono::microseconds(cycles * 1000000 / BASE_CLOCK_RATE); } u64 CpuCyclesToClockCycles(u64 ticks); diff --git a/src/core/file_sys/control_metadata.cpp b/src/core/file_sys/control_metadata.cpp index 60ea9ad12..04da30825 100644 --- a/src/core/file_sys/control_metadata.cpp +++ b/src/core/file_sys/control_metadata.cpp @@ -87,6 +87,10 @@ u64 NACP::GetDefaultJournalSaveSize() const { return raw.user_account_save_data_journal_size; } +u32 NACP::GetSupportedLanguages() const { + return raw.supported_languages; +} + std::vector<u8> NACP::GetRawBytes() const { std::vector<u8> out(sizeof(RawNACP)); std::memcpy(out.data(), &raw, sizeof(RawNACP)); diff --git a/src/core/file_sys/control_metadata.h b/src/core/file_sys/control_metadata.h index 280710ddf..1be34ed55 100644 --- a/src/core/file_sys/control_metadata.h +++ b/src/core/file_sys/control_metadata.h @@ -109,6 +109,7 @@ public: std::string GetVersionString() const; u64 GetDefaultNormalSaveSize() const; u64 GetDefaultJournalSaveSize() const; + u32 GetSupportedLanguages() const; std::vector<u8> GetRawBytes() const; private: diff --git a/src/core/frontend/framebuffer_layout.cpp b/src/core/frontend/framebuffer_layout.cpp index a1357179f..d6d2cf3f0 100644 --- a/src/core/frontend/framebuffer_layout.cpp +++ b/src/core/frontend/framebuffer_layout.cpp @@ -20,7 +20,7 @@ static Common::Rectangle<T> MaxRectangle(Common::Rectangle<T> window_area, static_cast<T>(std::round(scale * screen_aspect_ratio))}; } -FramebufferLayout DefaultFrameLayout(unsigned width, unsigned height) { +FramebufferLayout DefaultFrameLayout(u32 width, u32 height) { ASSERT(width > 0); ASSERT(height > 0); // The drawing code needs at least somewhat valid values for both screens @@ -29,22 +29,23 @@ FramebufferLayout DefaultFrameLayout(unsigned width, unsigned height) { const float emulation_aspect_ratio{static_cast<float>(ScreenUndocked::Height) / ScreenUndocked::Width}; - Common::Rectangle<unsigned> screen_window_area{0, 0, width, height}; - Common::Rectangle<unsigned> screen = MaxRectangle(screen_window_area, emulation_aspect_ratio); + const auto window_aspect_ratio = static_cast<float>(height) / width; - float window_aspect_ratio = static_cast<float>(height) / width; + const Common::Rectangle<u32> screen_window_area{0, 0, width, height}; + Common::Rectangle<u32> screen = MaxRectangle(screen_window_area, emulation_aspect_ratio); if (window_aspect_ratio < emulation_aspect_ratio) { screen = screen.TranslateX((screen_window_area.GetWidth() - screen.GetWidth()) / 2); } else { screen = screen.TranslateY((height - screen.GetHeight()) / 2); } + res.screen = screen; return res; } -FramebufferLayout FrameLayoutFromResolutionScale(u16 res_scale) { - int width, height; +FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale) { + u32 width, height; if (Settings::values.use_docked_mode) { width = ScreenDocked::WidthDocked * res_scale; diff --git a/src/core/frontend/framebuffer_layout.h b/src/core/frontend/framebuffer_layout.h index c2c63d08c..d2370adde 100644 --- a/src/core/frontend/framebuffer_layout.h +++ b/src/core/frontend/framebuffer_layout.h @@ -8,15 +8,22 @@ namespace Layout { -enum ScreenUndocked : unsigned { Width = 1280, Height = 720 }; -enum ScreenDocked : unsigned { WidthDocked = 1920, HeightDocked = 1080 }; +enum ScreenUndocked : u32 { + Width = 1280, + Height = 720, +}; + +enum ScreenDocked : u32 { + WidthDocked = 1920, + HeightDocked = 1080, +}; /// Describes the layout of the window framebuffer struct FramebufferLayout { - unsigned width{ScreenUndocked::Width}; - unsigned height{ScreenUndocked::Height}; + u32 width{ScreenUndocked::Width}; + u32 height{ScreenUndocked::Height}; - Common::Rectangle<unsigned> screen; + Common::Rectangle<u32> screen; /** * Returns the ration of pixel size of the screen, compared to the native size of the undocked @@ -33,12 +40,12 @@ struct FramebufferLayout { * @param height Window framebuffer height in pixels * @return Newly created FramebufferLayout object with default screen regions initialized */ -FramebufferLayout DefaultFrameLayout(unsigned width, unsigned height); +FramebufferLayout DefaultFrameLayout(u32 width, u32 height); /** * Convenience method to get frame layout by resolution scale * @param res_scale resolution scale factor */ -FramebufferLayout FrameLayoutFromResolutionScale(u16 res_scale); +FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale); } // namespace Layout diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 2abf9efca..c73a40977 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -75,9 +75,9 @@ void Thread::WakeAfterDelay(s64 nanoseconds) { // This function might be called from any thread so we have to be cautious and use the // thread-safe version of ScheduleEvent. + const s64 cycles = Core::Timing::nsToCycles(std::chrono::nanoseconds{nanoseconds}); Core::System::GetInstance().CoreTiming().ScheduleEventThreadsafe( - Core::Timing::nsToCycles(nanoseconds), kernel.ThreadWakeupCallbackEventType(), - callback_handle); + cycles, kernel.ThreadWakeupCallbackEventType(), callback_handle); } void Thread::CancelWakeupTimer() { diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 1a32a109f..3f201c821 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -8,6 +8,8 @@ #include <cstring> #include "audio_core/audio_renderer.h" #include "core/core.h" +#include "core/file_sys/control_metadata.h" +#include "core/file_sys/patch_manager.h" #include "core/file_sys/savedata_factory.h" #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/kernel.h" @@ -29,9 +31,11 @@ #include "core/hle/service/am/tcap.h" #include "core/hle/service/apm/apm.h" #include "core/hle/service/filesystem/filesystem.h" +#include "core/hle/service/ns/ns.h" #include "core/hle/service/nvflinger/nvflinger.h" #include "core/hle/service/pm/pm.h" #include "core/hle/service/set/set.h" +#include "core/hle/service/sm/sm.h" #include "core/hle/service/vi/vi.h" #include "core/settings.h" @@ -1100,10 +1104,42 @@ void IApplicationFunctions::GetDesiredLanguage(Kernel::HLERequestContext& ctx) { // TODO(bunnei): This should be configurable LOG_DEBUG(Service_AM, "called"); + // Get supported languages from NACP, if possible + // Default to 0 (all languages supported) + u32 supported_languages = 0; + FileSys::PatchManager pm{Core::System::GetInstance().CurrentProcess()->GetTitleID()}; + + const auto res = pm.GetControlMetadata(); + if (res.first != nullptr) { + supported_languages = res.first->GetSupportedLanguages(); + } + + // Call IApplicationManagerInterface implementation. + auto& service_manager = Core::System::GetInstance().ServiceManager(); + auto ns_am2 = service_manager.GetService<Service::NS::NS>("ns:am2"); + auto app_man = ns_am2->GetApplicationManagerInterface(); + + // Get desired application language + const auto res_lang = app_man->GetApplicationDesiredLanguage(supported_languages); + if (res_lang.Failed()) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(res_lang.Code()); + return; + } + + // Convert to settings language code. + const auto res_code = app_man->ConvertApplicationLanguageToLanguageCode(*res_lang); + if (res_code.Failed()) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(res_code.Code()); + return; + } + + LOG_DEBUG(Service_AM, "got desired_language={:016X}", *res_code); + IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); - rb.Push( - static_cast<u64>(Service::Set::GetLanguageCodeFromIndex(Settings::values.language_index))); + rb.Push(*res_code); } void IApplicationFunctions::InitializeGamePlayRecording(Kernel::HLERequestContext& ctx) { diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp index e812c66e9..14fa92318 100644 --- a/src/core/hle/service/am/applets/applets.cpp +++ b/src/core/hle/service/am/applets/applets.cpp @@ -121,6 +121,21 @@ void Applet::Initialize() { initialized = true; } +AppletFrontendSet::AppletFrontendSet() = default; + +AppletFrontendSet::AppletFrontendSet(ErrorApplet error, PhotoViewer photo_viewer, + ProfileSelect profile_select, + SoftwareKeyboard software_keyboard, WebBrowser web_browser) + : error{std::move(error)}, photo_viewer{std::move(photo_viewer)}, profile_select{std::move( + profile_select)}, + software_keyboard{std::move(software_keyboard)}, web_browser{std::move(web_browser)} {} + +AppletFrontendSet::~AppletFrontendSet() = default; + +AppletFrontendSet::AppletFrontendSet(AppletFrontendSet&&) noexcept = default; + +AppletFrontendSet& AppletFrontendSet::operator=(AppletFrontendSet&&) noexcept = default; + AppletManager::AppletManager() = default; AppletManager::~AppletManager() = default; diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h index 7f932672c..b46e10a4a 100644 --- a/src/core/hle/service/am/applets/applets.h +++ b/src/core/hle/service/am/applets/applets.h @@ -137,11 +137,28 @@ protected: }; struct AppletFrontendSet { - std::unique_ptr<Core::Frontend::ErrorApplet> error; - std::unique_ptr<Core::Frontend::PhotoViewerApplet> photo_viewer; - std::unique_ptr<Core::Frontend::ProfileSelectApplet> profile_select; - std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet> software_keyboard; - std::unique_ptr<Core::Frontend::WebBrowserApplet> web_browser; + using ErrorApplet = std::unique_ptr<Core::Frontend::ErrorApplet>; + using PhotoViewer = std::unique_ptr<Core::Frontend::PhotoViewerApplet>; + using ProfileSelect = std::unique_ptr<Core::Frontend::ProfileSelectApplet>; + using SoftwareKeyboard = std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet>; + using WebBrowser = std::unique_ptr<Core::Frontend::WebBrowserApplet>; + + AppletFrontendSet(); + AppletFrontendSet(ErrorApplet error, PhotoViewer photo_viewer, ProfileSelect profile_select, + SoftwareKeyboard software_keyboard, WebBrowser web_browser); + ~AppletFrontendSet(); + + AppletFrontendSet(const AppletFrontendSet&) = delete; + AppletFrontendSet& operator=(const AppletFrontendSet&) = delete; + + AppletFrontendSet(AppletFrontendSet&&) noexcept; + AppletFrontendSet& operator=(AppletFrontendSet&&) noexcept; + + ErrorApplet error; + PhotoViewer photo_viewer; + ProfileSelect profile_select; + SoftwareKeyboard software_keyboard; + WebBrowser web_browser; }; class AppletManager { diff --git a/src/core/hle/service/ncm/ncm.cpp b/src/core/hle/service/ncm/ncm.cpp index 5d31f638f..b405a4b66 100644 --- a/src/core/hle/service/ncm/ncm.cpp +++ b/src/core/hle/service/ncm/ncm.cpp @@ -4,15 +4,89 @@ #include <memory> +#include "core/file_sys/romfs_factory.h" +#include "core/hle/ipc_helpers.h" #include "core/hle/service/ncm/ncm.h" #include "core/hle/service/service.h" #include "core/hle/service/sm/sm.h" namespace Service::NCM { -class LocationResolver final : public ServiceFramework<LocationResolver> { +class ILocationResolver final : public ServiceFramework<ILocationResolver> { public: - explicit LocationResolver() : ServiceFramework{"lr"} { + explicit ILocationResolver(FileSys::StorageId id) + : ServiceFramework{"ILocationResolver"}, storage(id) { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "ResolveProgramPath"}, + {1, nullptr, "RedirectProgramPath"}, + {2, nullptr, "ResolveApplicationControlPath"}, + {3, nullptr, "ResolveApplicationHtmlDocumentPath"}, + {4, nullptr, "ResolveDataPath"}, + {5, nullptr, "RedirectApplicationControlPath"}, + {6, nullptr, "RedirectApplicationHtmlDocumentPath"}, + {7, nullptr, "ResolveApplicationLegalInformationPath"}, + {8, nullptr, "RedirectApplicationLegalInformationPath"}, + {9, nullptr, "Refresh"}, + {10, nullptr, "RedirectProgramPath2"}, + {11, nullptr, "Refresh2"}, + {12, nullptr, "DeleteProgramPath"}, + {13, nullptr, "DeleteApplicationControlPath"}, + {14, nullptr, "DeleteApplicationHtmlDocumentPath"}, + {15, nullptr, "DeleteApplicationLegalInformationPath"}, + {16, nullptr, ""}, + {17, nullptr, ""}, + {18, nullptr, ""}, + {19, nullptr, ""}, + }; + // clang-format on + + RegisterHandlers(functions); + } + +private: + FileSys::StorageId storage; +}; + +class IRegisteredLocationResolver final : public ServiceFramework<IRegisteredLocationResolver> { +public: + explicit IRegisteredLocationResolver() : ServiceFramework{"IRegisteredLocationResolver"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "ResolveProgramPath"}, + {1, nullptr, "RegisterProgramPath"}, + {2, nullptr, "UnregisterProgramPath"}, + {3, nullptr, "RedirectProgramPath"}, + {4, nullptr, "ResolveHtmlDocumentPath"}, + {5, nullptr, "RegisterHtmlDocumentPath"}, + {6, nullptr, "UnregisterHtmlDocumentPath"}, + {7, nullptr, "RedirectHtmlDocumentPath"}, + {8, nullptr, ""}, + }; + // clang-format on + + RegisterHandlers(functions); + } +}; + +class IAddOnContentLocationResolver final : public ServiceFramework<IAddOnContentLocationResolver> { +public: + explicit IAddOnContentLocationResolver() : ServiceFramework{"IAddOnContentLocationResolver"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "ResolveAddOnContentPath"}, + {1, nullptr, "RegisterAddOnContentStorage"}, + {2, nullptr, "UnregisterAllAddOnContentPath"}, + }; + // clang-format on + + RegisterHandlers(functions); + } +}; + +class LR final : public ServiceFramework<LR> { +public: + explicit LR() : ServiceFramework{"lr"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "OpenLocationResolver"}, @@ -52,7 +126,7 @@ public: }; void InstallInterfaces(SM::ServiceManager& sm) { - std::make_shared<LocationResolver>()->InstallAsService(sm); + std::make_shared<LR>()->InstallAsService(sm); std::make_shared<NCM>()->InstallAsService(sm); } diff --git a/src/core/hle/service/ns/errors.h b/src/core/hle/service/ns/errors.h new file mode 100644 index 000000000..f4aea8a65 --- /dev/null +++ b/src/core/hle/service/ns/errors.h @@ -0,0 +1,12 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/result.h" + +namespace Service::NS { + +constexpr ResultCode ERR_APPLICATION_LANGUAGE_NOT_FOUND{ErrorModule::NS, 300}; +}
\ No newline at end of file diff --git a/src/core/hle/service/ns/language.cpp b/src/core/hle/service/ns/language.cpp new file mode 100644 index 000000000..29c4a820c --- /dev/null +++ b/src/core/hle/service/ns/language.cpp @@ -0,0 +1,392 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/service/ns/language.h" +#include "core/hle/service/set/set.h" + +namespace Service::NS { + +constexpr ApplicationLanguagePriorityList priority_list_american_english = {{ + ApplicationLanguage::AmericanEnglish, + ApplicationLanguage::BritishEnglish, + ApplicationLanguage::LatinAmericanSpanish, + ApplicationLanguage::CanadianFrench, + ApplicationLanguage::French, + ApplicationLanguage::German, + ApplicationLanguage::Spanish, + ApplicationLanguage::Italian, + ApplicationLanguage::Dutch, + ApplicationLanguage::Portuguese, + ApplicationLanguage::Russian, + ApplicationLanguage::Japanese, + ApplicationLanguage::SimplifiedChinese, + ApplicationLanguage::TraditionalChinese, + ApplicationLanguage::Korean, +}}; + +constexpr ApplicationLanguagePriorityList priority_list_british_english = {{ + ApplicationLanguage::BritishEnglish, + ApplicationLanguage::AmericanEnglish, + ApplicationLanguage::French, + ApplicationLanguage::German, + ApplicationLanguage::Spanish, + ApplicationLanguage::Italian, + ApplicationLanguage::Dutch, + ApplicationLanguage::Portuguese, + ApplicationLanguage::Russian, + ApplicationLanguage::LatinAmericanSpanish, + ApplicationLanguage::CanadianFrench, + ApplicationLanguage::Japanese, + ApplicationLanguage::SimplifiedChinese, + ApplicationLanguage::TraditionalChinese, + ApplicationLanguage::Korean, +}}; + +constexpr ApplicationLanguagePriorityList priority_list_japanese = {{ + ApplicationLanguage::Japanese, + ApplicationLanguage::AmericanEnglish, + ApplicationLanguage::BritishEnglish, + ApplicationLanguage::LatinAmericanSpanish, + ApplicationLanguage::CanadianFrench, + ApplicationLanguage::French, + ApplicationLanguage::German, + ApplicationLanguage::Spanish, + ApplicationLanguage::Italian, + ApplicationLanguage::Dutch, + ApplicationLanguage::Portuguese, + ApplicationLanguage::Russian, + ApplicationLanguage::SimplifiedChinese, + ApplicationLanguage::TraditionalChinese, + ApplicationLanguage::Korean, +}}; + +constexpr ApplicationLanguagePriorityList priority_list_french = {{ + ApplicationLanguage::French, + ApplicationLanguage::CanadianFrench, + ApplicationLanguage::BritishEnglish, + ApplicationLanguage::AmericanEnglish, + ApplicationLanguage::German, + ApplicationLanguage::Spanish, + ApplicationLanguage::Italian, + ApplicationLanguage::Dutch, + ApplicationLanguage::Portuguese, + ApplicationLanguage::Russian, + ApplicationLanguage::LatinAmericanSpanish, + ApplicationLanguage::Japanese, + ApplicationLanguage::SimplifiedChinese, + ApplicationLanguage::TraditionalChinese, + ApplicationLanguage::Korean, +}}; + +constexpr ApplicationLanguagePriorityList priority_list_german = {{ + ApplicationLanguage::German, + ApplicationLanguage::BritishEnglish, + ApplicationLanguage::AmericanEnglish, + ApplicationLanguage::French, + ApplicationLanguage::Spanish, + ApplicationLanguage::Italian, + ApplicationLanguage::Dutch, + ApplicationLanguage::Portuguese, + ApplicationLanguage::Russian, + ApplicationLanguage::LatinAmericanSpanish, + ApplicationLanguage::CanadianFrench, + ApplicationLanguage::Japanese, + ApplicationLanguage::SimplifiedChinese, + ApplicationLanguage::TraditionalChinese, + ApplicationLanguage::Korean, +}}; + +constexpr ApplicationLanguagePriorityList priority_list_latin_american_spanish = {{ + ApplicationLanguage::LatinAmericanSpanish, + ApplicationLanguage::Spanish, + ApplicationLanguage::AmericanEnglish, + ApplicationLanguage::BritishEnglish, + ApplicationLanguage::Portuguese, + ApplicationLanguage::CanadianFrench, + ApplicationLanguage::French, + ApplicationLanguage::Italian, + ApplicationLanguage::German, + ApplicationLanguage::Dutch, + ApplicationLanguage::Russian, + ApplicationLanguage::Japanese, + ApplicationLanguage::SimplifiedChinese, + ApplicationLanguage::TraditionalChinese, + ApplicationLanguage::Korean, +}}; + +constexpr ApplicationLanguagePriorityList priority_list_spanish = {{ + ApplicationLanguage::Spanish, + ApplicationLanguage::LatinAmericanSpanish, + ApplicationLanguage::BritishEnglish, + ApplicationLanguage::AmericanEnglish, + ApplicationLanguage::French, + ApplicationLanguage::German, + ApplicationLanguage::Italian, + ApplicationLanguage::Dutch, + ApplicationLanguage::Portuguese, + ApplicationLanguage::Russian, + ApplicationLanguage::CanadianFrench, + ApplicationLanguage::Japanese, + ApplicationLanguage::SimplifiedChinese, + ApplicationLanguage::TraditionalChinese, + ApplicationLanguage::Korean, +}}; + +constexpr ApplicationLanguagePriorityList priority_list_italian = {{ + ApplicationLanguage::Italian, + ApplicationLanguage::BritishEnglish, + ApplicationLanguage::AmericanEnglish, + ApplicationLanguage::French, + ApplicationLanguage::German, + ApplicationLanguage::Spanish, + ApplicationLanguage::Dutch, + ApplicationLanguage::Portuguese, + ApplicationLanguage::Russian, + ApplicationLanguage::LatinAmericanSpanish, + ApplicationLanguage::CanadianFrench, + ApplicationLanguage::Japanese, + ApplicationLanguage::SimplifiedChinese, + ApplicationLanguage::TraditionalChinese, + ApplicationLanguage::Korean, +}}; + +constexpr ApplicationLanguagePriorityList priority_list_dutch = {{ + ApplicationLanguage::Dutch, + ApplicationLanguage::BritishEnglish, + ApplicationLanguage::AmericanEnglish, + ApplicationLanguage::French, + ApplicationLanguage::German, + ApplicationLanguage::Spanish, + ApplicationLanguage::Italian, + ApplicationLanguage::Portuguese, + ApplicationLanguage::Russian, + ApplicationLanguage::LatinAmericanSpanish, + ApplicationLanguage::CanadianFrench, + ApplicationLanguage::Japanese, + ApplicationLanguage::SimplifiedChinese, + ApplicationLanguage::TraditionalChinese, + ApplicationLanguage::Korean, +}}; + +constexpr ApplicationLanguagePriorityList priority_list_canadian_french = {{ + ApplicationLanguage::CanadianFrench, + ApplicationLanguage::French, + ApplicationLanguage::AmericanEnglish, + ApplicationLanguage::BritishEnglish, + ApplicationLanguage::LatinAmericanSpanish, + ApplicationLanguage::Spanish, + ApplicationLanguage::German, + ApplicationLanguage::Italian, + ApplicationLanguage::Dutch, + ApplicationLanguage::Portuguese, + ApplicationLanguage::Russian, + ApplicationLanguage::Japanese, + ApplicationLanguage::SimplifiedChinese, + ApplicationLanguage::TraditionalChinese, + ApplicationLanguage::Korean, +}}; + +constexpr ApplicationLanguagePriorityList priority_list_portuguese = {{ + ApplicationLanguage::Portuguese, + ApplicationLanguage::BritishEnglish, + ApplicationLanguage::AmericanEnglish, + ApplicationLanguage::French, + ApplicationLanguage::German, + ApplicationLanguage::Spanish, + ApplicationLanguage::Italian, + ApplicationLanguage::Dutch, + ApplicationLanguage::Russian, + ApplicationLanguage::LatinAmericanSpanish, + ApplicationLanguage::CanadianFrench, + ApplicationLanguage::Japanese, + ApplicationLanguage::SimplifiedChinese, + ApplicationLanguage::TraditionalChinese, + ApplicationLanguage::Korean, +}}; + +constexpr ApplicationLanguagePriorityList priority_list_russian = {{ + ApplicationLanguage::Russian, + ApplicationLanguage::BritishEnglish, + ApplicationLanguage::AmericanEnglish, + ApplicationLanguage::French, + ApplicationLanguage::German, + ApplicationLanguage::Spanish, + ApplicationLanguage::Italian, + ApplicationLanguage::Dutch, + ApplicationLanguage::Portuguese, + ApplicationLanguage::LatinAmericanSpanish, + ApplicationLanguage::CanadianFrench, + ApplicationLanguage::Japanese, + ApplicationLanguage::SimplifiedChinese, + ApplicationLanguage::TraditionalChinese, + ApplicationLanguage::Korean, +}}; + +constexpr ApplicationLanguagePriorityList priority_list_korean = {{ + ApplicationLanguage::Korean, + ApplicationLanguage::AmericanEnglish, + ApplicationLanguage::BritishEnglish, + ApplicationLanguage::LatinAmericanSpanish, + ApplicationLanguage::CanadianFrench, + ApplicationLanguage::French, + ApplicationLanguage::German, + ApplicationLanguage::Spanish, + ApplicationLanguage::Italian, + ApplicationLanguage::Dutch, + ApplicationLanguage::Portuguese, + ApplicationLanguage::Russian, + ApplicationLanguage::Japanese, + ApplicationLanguage::SimplifiedChinese, + ApplicationLanguage::TraditionalChinese, +}}; + +constexpr ApplicationLanguagePriorityList priority_list_traditional_chinese = {{ + ApplicationLanguage::TraditionalChinese, + ApplicationLanguage::SimplifiedChinese, + ApplicationLanguage::AmericanEnglish, + ApplicationLanguage::BritishEnglish, + ApplicationLanguage::Japanese, + ApplicationLanguage::LatinAmericanSpanish, + ApplicationLanguage::CanadianFrench, + ApplicationLanguage::French, + ApplicationLanguage::German, + ApplicationLanguage::Spanish, + ApplicationLanguage::Italian, + ApplicationLanguage::Dutch, + ApplicationLanguage::Portuguese, + ApplicationLanguage::Russian, + ApplicationLanguage::Korean, +}}; + +constexpr ApplicationLanguagePriorityList priority_list_simplified_chinese = {{ + ApplicationLanguage::SimplifiedChinese, + ApplicationLanguage::TraditionalChinese, + ApplicationLanguage::AmericanEnglish, + ApplicationLanguage::BritishEnglish, + ApplicationLanguage::Japanese, + ApplicationLanguage::LatinAmericanSpanish, + ApplicationLanguage::CanadianFrench, + ApplicationLanguage::French, + ApplicationLanguage::German, + ApplicationLanguage::Spanish, + ApplicationLanguage::Italian, + ApplicationLanguage::Dutch, + ApplicationLanguage::Portuguese, + ApplicationLanguage::Russian, + ApplicationLanguage::Korean, +}}; + +const ApplicationLanguagePriorityList* GetApplicationLanguagePriorityList( + const ApplicationLanguage lang) { + switch (lang) { + case ApplicationLanguage::AmericanEnglish: + return &priority_list_american_english; + case ApplicationLanguage::BritishEnglish: + return &priority_list_british_english; + case ApplicationLanguage::Japanese: + return &priority_list_japanese; + case ApplicationLanguage::French: + return &priority_list_french; + case ApplicationLanguage::German: + return &priority_list_german; + case ApplicationLanguage::LatinAmericanSpanish: + return &priority_list_latin_american_spanish; + case ApplicationLanguage::Spanish: + return &priority_list_spanish; + case ApplicationLanguage::Italian: + return &priority_list_italian; + case ApplicationLanguage::Dutch: + return &priority_list_dutch; + case ApplicationLanguage::CanadianFrench: + return &priority_list_canadian_french; + case ApplicationLanguage::Portuguese: + return &priority_list_portuguese; + case ApplicationLanguage::Russian: + return &priority_list_russian; + case ApplicationLanguage::Korean: + return &priority_list_korean; + case ApplicationLanguage::TraditionalChinese: + return &priority_list_traditional_chinese; + case ApplicationLanguage::SimplifiedChinese: + return &priority_list_simplified_chinese; + default: + return nullptr; + } +} + +std::optional<ApplicationLanguage> ConvertToApplicationLanguage( + const Set::LanguageCode language_code) { + switch (language_code) { + case Set::LanguageCode::EN_US: + return ApplicationLanguage::AmericanEnglish; + case Set::LanguageCode::EN_GB: + return ApplicationLanguage::BritishEnglish; + case Set::LanguageCode::JA: + return ApplicationLanguage::Japanese; + case Set::LanguageCode::FR: + return ApplicationLanguage::French; + case Set::LanguageCode::DE: + return ApplicationLanguage::German; + case Set::LanguageCode::ES_419: + return ApplicationLanguage::LatinAmericanSpanish; + case Set::LanguageCode::ES: + return ApplicationLanguage::Spanish; + case Set::LanguageCode::IT: + return ApplicationLanguage::Italian; + case Set::LanguageCode::NL: + return ApplicationLanguage::Dutch; + case Set::LanguageCode::FR_CA: + return ApplicationLanguage::CanadianFrench; + case Set::LanguageCode::PT: + return ApplicationLanguage::Portuguese; + case Set::LanguageCode::RU: + return ApplicationLanguage::Russian; + case Set::LanguageCode::KO: + return ApplicationLanguage::Korean; + case Set::LanguageCode::ZH_HANT: + return ApplicationLanguage::TraditionalChinese; + case Set::LanguageCode::ZH_HANS: + return ApplicationLanguage::SimplifiedChinese; + default: + return std::nullopt; + } +} + +std::optional<Set::LanguageCode> ConvertToLanguageCode(const ApplicationLanguage lang) { + switch (lang) { + case ApplicationLanguage::AmericanEnglish: + return Set::LanguageCode::EN_US; + case ApplicationLanguage::BritishEnglish: + return Set::LanguageCode::EN_GB; + case ApplicationLanguage::Japanese: + return Set::LanguageCode::JA; + case ApplicationLanguage::French: + return Set::LanguageCode::FR; + case ApplicationLanguage::German: + return Set::LanguageCode::DE; + case ApplicationLanguage::LatinAmericanSpanish: + return Set::LanguageCode::ES_419; + case ApplicationLanguage::Spanish: + return Set::LanguageCode::ES; + case ApplicationLanguage::Italian: + return Set::LanguageCode::IT; + case ApplicationLanguage::Dutch: + return Set::LanguageCode::NL; + case ApplicationLanguage::CanadianFrench: + return Set::LanguageCode::FR_CA; + case ApplicationLanguage::Portuguese: + return Set::LanguageCode::PT; + case ApplicationLanguage::Russian: + return Set::LanguageCode::RU; + case ApplicationLanguage::Korean: + return Set::LanguageCode::KO; + case ApplicationLanguage::TraditionalChinese: + return Set::LanguageCode::ZH_HANT; + case ApplicationLanguage::SimplifiedChinese: + return Set::LanguageCode::ZH_HANS; + default: + return std::nullopt; + } +} +} // namespace Service::NS
\ No newline at end of file diff --git a/src/core/hle/service/ns/language.h b/src/core/hle/service/ns/language.h new file mode 100644 index 000000000..e9829f9d2 --- /dev/null +++ b/src/core/hle/service/ns/language.h @@ -0,0 +1,45 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <optional> +#include <string> +#include "common/common_types.h" + +namespace Service::Set { +enum class LanguageCode : u64; +} + +namespace Service::NS { +/// This is nn::ns::detail::ApplicationLanguage +enum class ApplicationLanguage : u8 { + AmericanEnglish = 0, + BritishEnglish, + Japanese, + French, + German, + LatinAmericanSpanish, + Spanish, + Italian, + Dutch, + CanadianFrench, + Portuguese, + Russian, + Korean, + TraditionalChinese, + SimplifiedChinese, + Count +}; +using ApplicationLanguagePriorityList = + const std::array<ApplicationLanguage, static_cast<std::size_t>(ApplicationLanguage::Count)>; + +constexpr u32 GetSupportedLanguageFlag(const ApplicationLanguage lang) { + return 1U << static_cast<u32>(lang); +} + +const ApplicationLanguagePriorityList* GetApplicationLanguagePriorityList(ApplicationLanguage lang); +std::optional<ApplicationLanguage> ConvertToApplicationLanguage(Set::LanguageCode language_code); +std::optional<Set::LanguageCode> ConvertToLanguageCode(ApplicationLanguage lang); +} // namespace Service::NS
\ No newline at end of file diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp index 0eb04037a..ce88a2941 100644 --- a/src/core/hle/service/ns/ns.cpp +++ b/src/core/hle/service/ns/ns.cpp @@ -7,445 +7,507 @@ #include "core/file_sys/patch_manager.h" #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/hle_ipc.h" +#include "core/hle/service/ns/errors.h" +#include "core/hle/service/ns/language.h" #include "core/hle/service/ns/ns.h" #include "core/hle/service/ns/pl_u.h" +#include "core/hle/service/set/set.h" +#include "core/settings.h" namespace Service::NS { -class IAccountProxyInterface final : public ServiceFramework<IAccountProxyInterface> { -public: - explicit IAccountProxyInterface() : ServiceFramework{"IAccountProxyInterface"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "CreateUserAccount"}, - }; - // clang-format on +IAccountProxyInterface::IAccountProxyInterface() : ServiceFramework{"IAccountProxyInterface"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "CreateUserAccount"}, + }; + // clang-format on - RegisterHandlers(functions); - } -}; + RegisterHandlers(functions); +} -class IApplicationManagerInterface final : public ServiceFramework<IApplicationManagerInterface> { -public: - explicit IApplicationManagerInterface() : ServiceFramework{"IApplicationManagerInterface"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "ListApplicationRecord"}, - {1, nullptr, "GenerateApplicationRecordCount"}, - {2, nullptr, "GetApplicationRecordUpdateSystemEvent"}, - {3, nullptr, "GetApplicationViewDeprecated"}, - {4, nullptr, "DeleteApplicationEntity"}, - {5, nullptr, "DeleteApplicationCompletely"}, - {6, nullptr, "IsAnyApplicationEntityRedundant"}, - {7, nullptr, "DeleteRedundantApplicationEntity"}, - {8, nullptr, "IsApplicationEntityMovable"}, - {9, nullptr, "MoveApplicationEntity"}, - {11, nullptr, "CalculateApplicationOccupiedSize"}, - {16, nullptr, "PushApplicationRecord"}, - {17, nullptr, "ListApplicationRecordContentMeta"}, - {19, nullptr, "LaunchApplicationOld"}, - {21, nullptr, "GetApplicationContentPath"}, - {22, nullptr, "TerminateApplication"}, - {23, nullptr, "ResolveApplicationContentPath"}, - {26, nullptr, "BeginInstallApplication"}, - {27, nullptr, "DeleteApplicationRecord"}, - {30, nullptr, "RequestApplicationUpdateInfo"}, - {32, nullptr, "CancelApplicationDownload"}, - {33, nullptr, "ResumeApplicationDownload"}, - {35, nullptr, "UpdateVersionList"}, - {36, nullptr, "PushLaunchVersion"}, - {37, nullptr, "ListRequiredVersion"}, - {38, nullptr, "CheckApplicationLaunchVersion"}, - {39, nullptr, "CheckApplicationLaunchRights"}, - {40, nullptr, "GetApplicationLogoData"}, - {41, nullptr, "CalculateApplicationDownloadRequiredSize"}, - {42, nullptr, "CleanupSdCard"}, - {43, nullptr, "CheckSdCardMountStatus"}, - {44, nullptr, "GetSdCardMountStatusChangedEvent"}, - {45, nullptr, "GetGameCardAttachmentEvent"}, - {46, nullptr, "GetGameCardAttachmentInfo"}, - {47, nullptr, "GetTotalSpaceSize"}, - {48, nullptr, "GetFreeSpaceSize"}, - {49, nullptr, "GetSdCardRemovedEvent"}, - {52, nullptr, "GetGameCardUpdateDetectionEvent"}, - {53, nullptr, "DisableApplicationAutoDelete"}, - {54, nullptr, "EnableApplicationAutoDelete"}, - {55, nullptr, "GetApplicationDesiredLanguage"}, - {56, nullptr, "SetApplicationTerminateResult"}, - {57, nullptr, "ClearApplicationTerminateResult"}, - {58, nullptr, "GetLastSdCardMountUnexpectedResult"}, - {59, nullptr, "ConvertApplicationLanguageToLanguageCode"}, - {60, nullptr, "ConvertLanguageCodeToApplicationLanguage"}, - {61, nullptr, "GetBackgroundDownloadStressTaskInfo"}, - {62, nullptr, "GetGameCardStopper"}, - {63, nullptr, "IsSystemProgramInstalled"}, - {64, nullptr, "StartApplyDeltaTask"}, - {65, nullptr, "GetRequestServerStopper"}, - {66, nullptr, "GetBackgroundApplyDeltaStressTaskInfo"}, - {67, nullptr, "CancelApplicationApplyDelta"}, - {68, nullptr, "ResumeApplicationApplyDelta"}, - {69, nullptr, "CalculateApplicationApplyDeltaRequiredSize"}, - {70, nullptr, "ResumeAll"}, - {71, nullptr, "GetStorageSize"}, - {80, nullptr, "RequestDownloadApplication"}, - {81, nullptr, "RequestDownloadAddOnContent"}, - {82, nullptr, "DownloadApplication"}, - {83, nullptr, "CheckApplicationResumeRights"}, - {84, nullptr, "GetDynamicCommitEvent"}, - {85, nullptr, "RequestUpdateApplication2"}, - {86, nullptr, "EnableApplicationCrashReport"}, - {87, nullptr, "IsApplicationCrashReportEnabled"}, - {90, nullptr, "BoostSystemMemoryResourceLimit"}, - {91, nullptr, "DeprecatedLaunchApplication"}, - {92, nullptr, "GetRunningApplicationProgramId"}, - {93, nullptr, "GetMainApplicationProgramIndex"}, - {94, nullptr, "LaunchApplication"}, - {95, nullptr, "GetApplicationLaunchInfo"}, - {96, nullptr, "AcquireApplicationLaunchInfo"}, - {97, nullptr, "GetMainApplicationProgramIndex2"}, - {98, nullptr, "EnableApplicationAllThreadDumpOnCrash"}, - {100, nullptr, "ResetToFactorySettings"}, - {101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"}, - {102, nullptr, "ResetToFactorySettingsForRefurbishment"}, - {200, nullptr, "CalculateUserSaveDataStatistics"}, - {201, nullptr, "DeleteUserSaveDataAll"}, - {210, nullptr, "DeleteUserSystemSaveData"}, - {211, nullptr, "DeleteSaveData"}, - {220, nullptr, "UnregisterNetworkServiceAccount"}, - {221, nullptr, "UnregisterNetworkServiceAccountWithUserSaveDataDeletion"}, - {300, nullptr, "GetApplicationShellEvent"}, - {301, nullptr, "PopApplicationShellEventInfo"}, - {302, nullptr, "LaunchLibraryApplet"}, - {303, nullptr, "TerminateLibraryApplet"}, - {304, nullptr, "LaunchSystemApplet"}, - {305, nullptr, "TerminateSystemApplet"}, - {306, nullptr, "LaunchOverlayApplet"}, - {307, nullptr, "TerminateOverlayApplet"}, - {400, &IApplicationManagerInterface::GetApplicationControlData, "GetApplicationControlData"}, - {401, nullptr, "InvalidateAllApplicationControlCache"}, - {402, nullptr, "RequestDownloadApplicationControlData"}, - {403, nullptr, "GetMaxApplicationControlCacheCount"}, - {404, nullptr, "InvalidateApplicationControlCache"}, - {405, nullptr, "ListApplicationControlCacheEntryInfo"}, - {406, nullptr, "GetApplicationControlProperty"}, - {502, nullptr, "RequestCheckGameCardRegistration"}, - {503, nullptr, "RequestGameCardRegistrationGoldPoint"}, - {504, nullptr, "RequestRegisterGameCard"}, - {505, nullptr, "GetGameCardMountFailureEvent"}, - {506, nullptr, "IsGameCardInserted"}, - {507, nullptr, "EnsureGameCardAccess"}, - {508, nullptr, "GetLastGameCardMountFailureResult"}, - {509, nullptr, "ListApplicationIdOnGameCard"}, - {600, nullptr, "CountApplicationContentMeta"}, - {601, nullptr, "ListApplicationContentMetaStatus"}, - {602, nullptr, "ListAvailableAddOnContent"}, - {603, nullptr, "GetOwnedApplicationContentMetaStatus"}, - {604, nullptr, "RegisterContentsExternalKey"}, - {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"}, - {606, nullptr, "GetContentMetaStorage"}, - {607, nullptr, "ListAvailableAddOnContent"}, - {700, nullptr, "PushDownloadTaskList"}, - {701, nullptr, "ClearTaskStatusList"}, - {702, nullptr, "RequestDownloadTaskList"}, - {703, nullptr, "RequestEnsureDownloadTask"}, - {704, nullptr, "ListDownloadTaskStatus"}, - {705, nullptr, "RequestDownloadTaskListData"}, - {800, nullptr, "RequestVersionList"}, - {801, nullptr, "ListVersionList"}, - {802, nullptr, "RequestVersionListData"}, - {900, nullptr, "GetApplicationRecord"}, - {901, nullptr, "GetApplicationRecordProperty"}, - {902, nullptr, "EnableApplicationAutoUpdate"}, - {903, nullptr, "DisableApplicationAutoUpdate"}, - {904, nullptr, "TouchApplication"}, - {905, nullptr, "RequestApplicationUpdate"}, - {906, nullptr, "IsApplicationUpdateRequested"}, - {907, nullptr, "WithdrawApplicationUpdateRequest"}, - {908, nullptr, "ListApplicationRecordInstalledContentMeta"}, - {909, nullptr, "WithdrawCleanupAddOnContentsWithNoRightsRecommendation"}, - {910, nullptr, "HasApplicationRecord"}, - {911, nullptr, "SetPreInstalledApplication"}, - {912, nullptr, "ClearPreInstalledApplicationFlag"}, - {1000, nullptr, "RequestVerifyApplicationDeprecated"}, - {1001, nullptr, "CorruptApplicationForDebug"}, - {1002, nullptr, "RequestVerifyAddOnContentsRights"}, - {1003, nullptr, "RequestVerifyApplication"}, - {1004, nullptr, "CorruptContentForDebug"}, - {1200, nullptr, "NeedsUpdateVulnerability"}, - {1300, nullptr, "IsAnyApplicationEntityInstalled"}, - {1301, nullptr, "DeleteApplicationContentEntities"}, - {1302, nullptr, "CleanupUnrecordedApplicationEntity"}, - {1303, nullptr, "CleanupAddOnContentsWithNoRights"}, - {1304, nullptr, "DeleteApplicationContentEntity"}, - {1305, nullptr, "TryDeleteRunningApplicationEntity"}, - {1306, nullptr, "TryDeleteRunningApplicationCompletely"}, - {1307, nullptr, "TryDeleteRunningApplicationContentEntities"}, - {1308, nullptr, "DeleteApplicationCompletelyForDebug"}, - {1309, nullptr, "CleanupUnavailableAddOnContents"}, - {1400, nullptr, "PrepareShutdown"}, - {1500, nullptr, "FormatSdCard"}, - {1501, nullptr, "NeedsSystemUpdateToFormatSdCard"}, - {1502, nullptr, "GetLastSdCardFormatUnexpectedResult"}, - {1504, nullptr, "InsertSdCard"}, - {1505, nullptr, "RemoveSdCard"}, - {1600, nullptr, "GetSystemSeedForPseudoDeviceId"}, - {1601, nullptr, "ResetSystemSeedForPseudoDeviceId"}, - {1700, nullptr, "ListApplicationDownloadingContentMeta"}, - {1701, nullptr, "GetApplicationView"}, - {1702, nullptr, "GetApplicationDownloadTaskStatus"}, - {1703, nullptr, "GetApplicationViewDownloadErrorContext"}, - {1800, nullptr, "IsNotificationSetupCompleted"}, - {1801, nullptr, "GetLastNotificationInfoCount"}, - {1802, nullptr, "ListLastNotificationInfo"}, - {1803, nullptr, "ListNotificationTask"}, - {1900, nullptr, "IsActiveAccount"}, - {1901, nullptr, "RequestDownloadApplicationPrepurchasedRights"}, - {1902, nullptr, "GetApplicationTicketInfo"}, - {2000, nullptr, "GetSystemDeliveryInfo"}, - {2001, nullptr, "SelectLatestSystemDeliveryInfo"}, - {2002, nullptr, "VerifyDeliveryProtocolVersion"}, - {2003, nullptr, "GetApplicationDeliveryInfo"}, - {2004, nullptr, "HasAllContentsToDeliver"}, - {2005, nullptr, "CompareApplicationDeliveryInfo"}, - {2006, nullptr, "CanDeliverApplication"}, - {2007, nullptr, "ListContentMetaKeyToDeliverApplication"}, - {2008, nullptr, "NeedsSystemUpdateToDeliverApplication"}, - {2009, nullptr, "EstimateRequiredSize"}, - {2010, nullptr, "RequestReceiveApplication"}, - {2011, nullptr, "CommitReceiveApplication"}, - {2012, nullptr, "GetReceiveApplicationProgress"}, - {2013, nullptr, "RequestSendApplication"}, - {2014, nullptr, "GetSendApplicationProgress"}, - {2015, nullptr, "CompareSystemDeliveryInfo"}, - {2016, nullptr, "ListNotCommittedContentMeta"}, - {2017, nullptr, "CreateDownloadTask"}, - {2018, nullptr, "GetApplicationDeliveryInfoHash"}, - {2050, nullptr, "GetApplicationRightsOnClient"}, - {2100, nullptr, "GetApplicationTerminateResult"}, - {2101, nullptr, "GetRawApplicationTerminateResult"}, - {2150, nullptr, "CreateRightsEnvironment"}, - {2151, nullptr, "DestroyRightsEnvironment"}, - {2152, nullptr, "ActivateRightsEnvironment"}, - {2153, nullptr, "DeactivateRightsEnvironment"}, - {2154, nullptr, "ForceActivateRightsContextForExit"}, - {2160, nullptr, "AddTargetApplicationToRightsEnvironment"}, - {2161, nullptr, "SetUsersToRightsEnvironment"}, - {2170, nullptr, "GetRightsEnvironmentStatus"}, - {2171, nullptr, "GetRightsEnvironmentStatusChangedEvent"}, - {2180, nullptr, "RequestExtendRightsInRightsEnvironment"}, - {2181, nullptr, "GetLastResultOfExtendRightsInRightsEnvironment"}, - {2182, nullptr, "SetActiveRightsContextUsingStateToRightsEnvironment"}, - {2190, nullptr, "GetRightsEnvironmentHandleForApplication"}, - {2199, nullptr, "GetRightsEnvironmentCountForDebug"}, - {2200, nullptr, "GetGameCardApplicationCopyIdentifier"}, - {2201, nullptr, "GetInstalledApplicationCopyIdentifier"}, - {2250, nullptr, "RequestReportActiveELicence"}, - {2300, nullptr, "ListEventLog"}, - }; - // clang-format on +IAccountProxyInterface::~IAccountProxyInterface() = default; + +IApplicationManagerInterface::IApplicationManagerInterface() + : ServiceFramework{"IApplicationManagerInterface"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "ListApplicationRecord"}, + {1, nullptr, "GenerateApplicationRecordCount"}, + {2, nullptr, "GetApplicationRecordUpdateSystemEvent"}, + {3, nullptr, "GetApplicationViewDeprecated"}, + {4, nullptr, "DeleteApplicationEntity"}, + {5, nullptr, "DeleteApplicationCompletely"}, + {6, nullptr, "IsAnyApplicationEntityRedundant"}, + {7, nullptr, "DeleteRedundantApplicationEntity"}, + {8, nullptr, "IsApplicationEntityMovable"}, + {9, nullptr, "MoveApplicationEntity"}, + {11, nullptr, "CalculateApplicationOccupiedSize"}, + {16, nullptr, "PushApplicationRecord"}, + {17, nullptr, "ListApplicationRecordContentMeta"}, + {19, nullptr, "LaunchApplicationOld"}, + {21, nullptr, "GetApplicationContentPath"}, + {22, nullptr, "TerminateApplication"}, + {23, nullptr, "ResolveApplicationContentPath"}, + {26, nullptr, "BeginInstallApplication"}, + {27, nullptr, "DeleteApplicationRecord"}, + {30, nullptr, "RequestApplicationUpdateInfo"}, + {32, nullptr, "CancelApplicationDownload"}, + {33, nullptr, "ResumeApplicationDownload"}, + {35, nullptr, "UpdateVersionList"}, + {36, nullptr, "PushLaunchVersion"}, + {37, nullptr, "ListRequiredVersion"}, + {38, nullptr, "CheckApplicationLaunchVersion"}, + {39, nullptr, "CheckApplicationLaunchRights"}, + {40, nullptr, "GetApplicationLogoData"}, + {41, nullptr, "CalculateApplicationDownloadRequiredSize"}, + {42, nullptr, "CleanupSdCard"}, + {43, nullptr, "CheckSdCardMountStatus"}, + {44, nullptr, "GetSdCardMountStatusChangedEvent"}, + {45, nullptr, "GetGameCardAttachmentEvent"}, + {46, nullptr, "GetGameCardAttachmentInfo"}, + {47, nullptr, "GetTotalSpaceSize"}, + {48, nullptr, "GetFreeSpaceSize"}, + {49, nullptr, "GetSdCardRemovedEvent"}, + {52, nullptr, "GetGameCardUpdateDetectionEvent"}, + {53, nullptr, "DisableApplicationAutoDelete"}, + {54, nullptr, "EnableApplicationAutoDelete"}, + {55, &IApplicationManagerInterface::GetApplicationDesiredLanguage, "GetApplicationDesiredLanguage"}, + {56, nullptr, "SetApplicationTerminateResult"}, + {57, nullptr, "ClearApplicationTerminateResult"}, + {58, nullptr, "GetLastSdCardMountUnexpectedResult"}, + {59, &IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode, "ConvertApplicationLanguageToLanguageCode"}, + {60, nullptr, "ConvertLanguageCodeToApplicationLanguage"}, + {61, nullptr, "GetBackgroundDownloadStressTaskInfo"}, + {62, nullptr, "GetGameCardStopper"}, + {63, nullptr, "IsSystemProgramInstalled"}, + {64, nullptr, "StartApplyDeltaTask"}, + {65, nullptr, "GetRequestServerStopper"}, + {66, nullptr, "GetBackgroundApplyDeltaStressTaskInfo"}, + {67, nullptr, "CancelApplicationApplyDelta"}, + {68, nullptr, "ResumeApplicationApplyDelta"}, + {69, nullptr, "CalculateApplicationApplyDeltaRequiredSize"}, + {70, nullptr, "ResumeAll"}, + {71, nullptr, "GetStorageSize"}, + {80, nullptr, "RequestDownloadApplication"}, + {81, nullptr, "RequestDownloadAddOnContent"}, + {82, nullptr, "DownloadApplication"}, + {83, nullptr, "CheckApplicationResumeRights"}, + {84, nullptr, "GetDynamicCommitEvent"}, + {85, nullptr, "RequestUpdateApplication2"}, + {86, nullptr, "EnableApplicationCrashReport"}, + {87, nullptr, "IsApplicationCrashReportEnabled"}, + {90, nullptr, "BoostSystemMemoryResourceLimit"}, + {91, nullptr, "DeprecatedLaunchApplication"}, + {92, nullptr, "GetRunningApplicationProgramId"}, + {93, nullptr, "GetMainApplicationProgramIndex"}, + {94, nullptr, "LaunchApplication"}, + {95, nullptr, "GetApplicationLaunchInfo"}, + {96, nullptr, "AcquireApplicationLaunchInfo"}, + {97, nullptr, "GetMainApplicationProgramIndex2"}, + {98, nullptr, "EnableApplicationAllThreadDumpOnCrash"}, + {100, nullptr, "ResetToFactorySettings"}, + {101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"}, + {102, nullptr, "ResetToFactorySettingsForRefurbishment"}, + {200, nullptr, "CalculateUserSaveDataStatistics"}, + {201, nullptr, "DeleteUserSaveDataAll"}, + {210, nullptr, "DeleteUserSystemSaveData"}, + {211, nullptr, "DeleteSaveData"}, + {220, nullptr, "UnregisterNetworkServiceAccount"}, + {221, nullptr, "UnregisterNetworkServiceAccountWithUserSaveDataDeletion"}, + {300, nullptr, "GetApplicationShellEvent"}, + {301, nullptr, "PopApplicationShellEventInfo"}, + {302, nullptr, "LaunchLibraryApplet"}, + {303, nullptr, "TerminateLibraryApplet"}, + {304, nullptr, "LaunchSystemApplet"}, + {305, nullptr, "TerminateSystemApplet"}, + {306, nullptr, "LaunchOverlayApplet"}, + {307, nullptr, "TerminateOverlayApplet"}, + {400, &IApplicationManagerInterface::GetApplicationControlData, "GetApplicationControlData"}, + {401, nullptr, "InvalidateAllApplicationControlCache"}, + {402, nullptr, "RequestDownloadApplicationControlData"}, + {403, nullptr, "GetMaxApplicationControlCacheCount"}, + {404, nullptr, "InvalidateApplicationControlCache"}, + {405, nullptr, "ListApplicationControlCacheEntryInfo"}, + {406, nullptr, "GetApplicationControlProperty"}, + {502, nullptr, "RequestCheckGameCardRegistration"}, + {503, nullptr, "RequestGameCardRegistrationGoldPoint"}, + {504, nullptr, "RequestRegisterGameCard"}, + {505, nullptr, "GetGameCardMountFailureEvent"}, + {506, nullptr, "IsGameCardInserted"}, + {507, nullptr, "EnsureGameCardAccess"}, + {508, nullptr, "GetLastGameCardMountFailureResult"}, + {509, nullptr, "ListApplicationIdOnGameCard"}, + {600, nullptr, "CountApplicationContentMeta"}, + {601, nullptr, "ListApplicationContentMetaStatus"}, + {602, nullptr, "ListAvailableAddOnContent"}, + {603, nullptr, "GetOwnedApplicationContentMetaStatus"}, + {604, nullptr, "RegisterContentsExternalKey"}, + {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"}, + {606, nullptr, "GetContentMetaStorage"}, + {607, nullptr, "ListAvailableAddOnContent"}, + {700, nullptr, "PushDownloadTaskList"}, + {701, nullptr, "ClearTaskStatusList"}, + {702, nullptr, "RequestDownloadTaskList"}, + {703, nullptr, "RequestEnsureDownloadTask"}, + {704, nullptr, "ListDownloadTaskStatus"}, + {705, nullptr, "RequestDownloadTaskListData"}, + {800, nullptr, "RequestVersionList"}, + {801, nullptr, "ListVersionList"}, + {802, nullptr, "RequestVersionListData"}, + {900, nullptr, "GetApplicationRecord"}, + {901, nullptr, "GetApplicationRecordProperty"}, + {902, nullptr, "EnableApplicationAutoUpdate"}, + {903, nullptr, "DisableApplicationAutoUpdate"}, + {904, nullptr, "TouchApplication"}, + {905, nullptr, "RequestApplicationUpdate"}, + {906, nullptr, "IsApplicationUpdateRequested"}, + {907, nullptr, "WithdrawApplicationUpdateRequest"}, + {908, nullptr, "ListApplicationRecordInstalledContentMeta"}, + {909, nullptr, "WithdrawCleanupAddOnContentsWithNoRightsRecommendation"}, + {910, nullptr, "HasApplicationRecord"}, + {911, nullptr, "SetPreInstalledApplication"}, + {912, nullptr, "ClearPreInstalledApplicationFlag"}, + {1000, nullptr, "RequestVerifyApplicationDeprecated"}, + {1001, nullptr, "CorruptApplicationForDebug"}, + {1002, nullptr, "RequestVerifyAddOnContentsRights"}, + {1003, nullptr, "RequestVerifyApplication"}, + {1004, nullptr, "CorruptContentForDebug"}, + {1200, nullptr, "NeedsUpdateVulnerability"}, + {1300, nullptr, "IsAnyApplicationEntityInstalled"}, + {1301, nullptr, "DeleteApplicationContentEntities"}, + {1302, nullptr, "CleanupUnrecordedApplicationEntity"}, + {1303, nullptr, "CleanupAddOnContentsWithNoRights"}, + {1304, nullptr, "DeleteApplicationContentEntity"}, + {1305, nullptr, "TryDeleteRunningApplicationEntity"}, + {1306, nullptr, "TryDeleteRunningApplicationCompletely"}, + {1307, nullptr, "TryDeleteRunningApplicationContentEntities"}, + {1308, nullptr, "DeleteApplicationCompletelyForDebug"}, + {1309, nullptr, "CleanupUnavailableAddOnContents"}, + {1400, nullptr, "PrepareShutdown"}, + {1500, nullptr, "FormatSdCard"}, + {1501, nullptr, "NeedsSystemUpdateToFormatSdCard"}, + {1502, nullptr, "GetLastSdCardFormatUnexpectedResult"}, + {1504, nullptr, "InsertSdCard"}, + {1505, nullptr, "RemoveSdCard"}, + {1600, nullptr, "GetSystemSeedForPseudoDeviceId"}, + {1601, nullptr, "ResetSystemSeedForPseudoDeviceId"}, + {1700, nullptr, "ListApplicationDownloadingContentMeta"}, + {1701, nullptr, "GetApplicationView"}, + {1702, nullptr, "GetApplicationDownloadTaskStatus"}, + {1703, nullptr, "GetApplicationViewDownloadErrorContext"}, + {1800, nullptr, "IsNotificationSetupCompleted"}, + {1801, nullptr, "GetLastNotificationInfoCount"}, + {1802, nullptr, "ListLastNotificationInfo"}, + {1803, nullptr, "ListNotificationTask"}, + {1900, nullptr, "IsActiveAccount"}, + {1901, nullptr, "RequestDownloadApplicationPrepurchasedRights"}, + {1902, nullptr, "GetApplicationTicketInfo"}, + {2000, nullptr, "GetSystemDeliveryInfo"}, + {2001, nullptr, "SelectLatestSystemDeliveryInfo"}, + {2002, nullptr, "VerifyDeliveryProtocolVersion"}, + {2003, nullptr, "GetApplicationDeliveryInfo"}, + {2004, nullptr, "HasAllContentsToDeliver"}, + {2005, nullptr, "CompareApplicationDeliveryInfo"}, + {2006, nullptr, "CanDeliverApplication"}, + {2007, nullptr, "ListContentMetaKeyToDeliverApplication"}, + {2008, nullptr, "NeedsSystemUpdateToDeliverApplication"}, + {2009, nullptr, "EstimateRequiredSize"}, + {2010, nullptr, "RequestReceiveApplication"}, + {2011, nullptr, "CommitReceiveApplication"}, + {2012, nullptr, "GetReceiveApplicationProgress"}, + {2013, nullptr, "RequestSendApplication"}, + {2014, nullptr, "GetSendApplicationProgress"}, + {2015, nullptr, "CompareSystemDeliveryInfo"}, + {2016, nullptr, "ListNotCommittedContentMeta"}, + {2017, nullptr, "CreateDownloadTask"}, + {2018, nullptr, "GetApplicationDeliveryInfoHash"}, + {2050, nullptr, "GetApplicationRightsOnClient"}, + {2100, nullptr, "GetApplicationTerminateResult"}, + {2101, nullptr, "GetRawApplicationTerminateResult"}, + {2150, nullptr, "CreateRightsEnvironment"}, + {2151, nullptr, "DestroyRightsEnvironment"}, + {2152, nullptr, "ActivateRightsEnvironment"}, + {2153, nullptr, "DeactivateRightsEnvironment"}, + {2154, nullptr, "ForceActivateRightsContextForExit"}, + {2160, nullptr, "AddTargetApplicationToRightsEnvironment"}, + {2161, nullptr, "SetUsersToRightsEnvironment"}, + {2170, nullptr, "GetRightsEnvironmentStatus"}, + {2171, nullptr, "GetRightsEnvironmentStatusChangedEvent"}, + {2180, nullptr, "RequestExtendRightsInRightsEnvironment"}, + {2181, nullptr, "GetLastResultOfExtendRightsInRightsEnvironment"}, + {2182, nullptr, "SetActiveRightsContextUsingStateToRightsEnvironment"}, + {2190, nullptr, "GetRightsEnvironmentHandleForApplication"}, + {2199, nullptr, "GetRightsEnvironmentCountForDebug"}, + {2200, nullptr, "GetGameCardApplicationCopyIdentifier"}, + {2201, nullptr, "GetInstalledApplicationCopyIdentifier"}, + {2250, nullptr, "RequestReportActiveELicence"}, + {2300, nullptr, "ListEventLog"}, + }; + // clang-format on + + RegisterHandlers(functions); +} - RegisterHandlers(functions); - } +IApplicationManagerInterface::~IApplicationManagerInterface() = default; + +void IApplicationManagerInterface::GetApplicationControlData(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto flag = rp.PopRaw<u64>(); + LOG_DEBUG(Service_NS, "called with flag={:016X}", flag); - void GetApplicationControlData(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto flag = rp.PopRaw<u64>(); - LOG_DEBUG(Service_NS, "called with flag={:016X}", flag); - - const auto title_id = rp.PopRaw<u64>(); - - const auto size = ctx.GetWriteBufferSize(); - - const FileSys::PatchManager pm{title_id}; - const auto control = pm.GetControlMetadata(); - - std::vector<u8> out; - - if (control.first != nullptr) { - if (size < 0x4000) { - LOG_ERROR(Service_NS, - "output buffer is too small! (actual={:016X}, expected_min=0x4000)", - size); - IPC::ResponseBuilder rb{ctx, 2}; - // TODO(DarkLordZach): Find a better error code for this. - rb.Push(ResultCode(-1)); - return; - } - - out.resize(0x4000); - const auto bytes = control.first->GetRawBytes(); - std::memcpy(out.data(), bytes.data(), bytes.size()); - } else { - LOG_WARNING(Service_NS, "missing NACP data for title_id={:016X}, defaulting to zeros.", - title_id); - out.resize(std::min<u64>(0x4000, size)); + const auto title_id = rp.PopRaw<u64>(); + + const auto size = ctx.GetWriteBufferSize(); + + const FileSys::PatchManager pm{title_id}; + const auto control = pm.GetControlMetadata(); + + std::vector<u8> out; + + if (control.first != nullptr) { + if (size < 0x4000) { + LOG_ERROR(Service_NS, + "output buffer is too small! (actual={:016X}, expected_min=0x4000)", size); + IPC::ResponseBuilder rb{ctx, 2}; + // TODO(DarkLordZach): Find a better error code for this. + rb.Push(ResultCode(-1)); + return; } - if (control.second != nullptr) { - if (size < 0x4000 + control.second->GetSize()) { - LOG_ERROR(Service_NS, - "output buffer is too small! (actual={:016X}, expected_min={:016X})", - size, 0x4000 + control.second->GetSize()); - IPC::ResponseBuilder rb{ctx, 2}; - // TODO(DarkLordZach): Find a better error code for this. - rb.Push(ResultCode(-1)); - return; - } - - out.resize(0x4000 + control.second->GetSize()); - control.second->Read(out.data() + 0x4000, control.second->GetSize()); - } else { - LOG_WARNING(Service_NS, "missing icon data for title_id={:016X}, defaulting to zeros.", - title_id); + out.resize(0x4000); + const auto bytes = control.first->GetRawBytes(); + std::memcpy(out.data(), bytes.data(), bytes.size()); + } else { + LOG_WARNING(Service_NS, "missing NACP data for title_id={:016X}, defaulting to zeros.", + title_id); + out.resize(std::min<u64>(0x4000, size)); + } + + if (control.second != nullptr) { + if (size < 0x4000 + control.second->GetSize()) { + LOG_ERROR(Service_NS, + "output buffer is too small! (actual={:016X}, expected_min={:016X})", size, + 0x4000 + control.second->GetSize()); + IPC::ResponseBuilder rb{ctx, 2}; + // TODO(DarkLordZach): Find a better error code for this. + rb.Push(ResultCode(-1)); + return; } - ctx.WriteBuffer(out); + out.resize(0x4000 + control.second->GetSize()); + control.second->Read(out.data() + 0x4000, control.second->GetSize()); + } else { + LOG_WARNING(Service_NS, "missing icon data for title_id={:016X}, defaulting to zeros.", + title_id); + } + + ctx.WriteBuffer(out); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push<u32>(static_cast<u32>(out.size())); +} + +void IApplicationManagerInterface::GetApplicationDesiredLanguage(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto supported_languages = rp.Pop<u32>(); + const auto res = GetApplicationDesiredLanguage(supported_languages); + if (res.Succeeded()) { IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - rb.Push<u32>(static_cast<u32>(out.size())); + rb.Push<u32>(*res); + } else { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(res.Code()); } -}; +} -class IApplicationVersionInterface final : public ServiceFramework<IApplicationVersionInterface> { -public: - explicit IApplicationVersionInterface() : ServiceFramework{"IApplicationVersionInterface"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "GetLaunchRequiredVersion"}, - {1, nullptr, "UpgradeLaunchRequiredVersion"}, - {35, nullptr, "UpdateVersionList"}, - {36, nullptr, "PushLaunchVersion"}, - {37, nullptr, "ListRequiredVersion"}, - {800, nullptr, "RequestVersionList"}, - {801, nullptr, "ListVersionList"}, - {802, nullptr, "RequestVersionListData"}, - {1000, nullptr, "PerformAutoUpdate"}, - }; - // clang-format on +ResultVal<u8> IApplicationManagerInterface::GetApplicationDesiredLanguage( + const u32 supported_languages) { + LOG_DEBUG(Service_NS, "called with supported_languages={:08X}", supported_languages); - RegisterHandlers(functions); - } -}; + // Get language code from settings + const auto language_code = Set::GetLanguageCodeFromIndex(Settings::values.language_index); -class IContentManagerInterface final : public ServiceFramework<IContentManagerInterface> { -public: - explicit IContentManagerInterface() : ServiceFramework{"IContentManagerInterface"} { - // clang-format off - static const FunctionInfo functions[] = { - {11, nullptr, "CalculateApplicationOccupiedSize"}, - {43, nullptr, "CheckSdCardMountStatus"}, - {47, nullptr, "GetTotalSpaceSize"}, - {48, nullptr, "GetFreeSpaceSize"}, - {600, nullptr, "CountApplicationContentMeta"}, - {601, nullptr, "ListApplicationContentMetaStatus"}, - {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"}, - {607, nullptr, "IsAnyApplicationRunning"}, - }; - // clang-format on + // Convert to application language, get priority list + const auto application_language = ConvertToApplicationLanguage(language_code); + if (application_language == std::nullopt) { + return ERR_APPLICATION_LANGUAGE_NOT_FOUND; + } + const auto priority_list = GetApplicationLanguagePriorityList(*application_language); + if (!priority_list) { + return ERR_APPLICATION_LANGUAGE_NOT_FOUND; + } - RegisterHandlers(functions); + // Try to find a valid language. + for (const auto lang : *priority_list) { + const auto supported_flag = GetSupportedLanguageFlag(lang); + if (supported_languages == 0 || (supported_languages & supported_flag) == supported_flag) { + return MakeResult(static_cast<u8>(lang)); + } } -}; -class IDocumentInterface final : public ServiceFramework<IDocumentInterface> { -public: - explicit IDocumentInterface() : ServiceFramework{"IDocumentInterface"} { - // clang-format off - static const FunctionInfo functions[] = { - {21, nullptr, "GetApplicationContentPath"}, - {23, nullptr, "ResolveApplicationContentPath"}, - {93, nullptr, "GetRunningApplicationProgramId"}, - }; - // clang-format on + return ERR_APPLICATION_LANGUAGE_NOT_FOUND; +} - RegisterHandlers(functions); - } -}; +void IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode( + Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto application_language = rp.Pop<u8>(); -class IDownloadTaskInterface final : public ServiceFramework<IDownloadTaskInterface> { -public: - explicit IDownloadTaskInterface() : ServiceFramework{"IDownloadTaskInterface"} { - // clang-format off - static const FunctionInfo functions[] = { - {701, nullptr, "ClearTaskStatusList"}, - {702, nullptr, "RequestDownloadTaskList"}, - {703, nullptr, "RequestEnsureDownloadTask"}, - {704, nullptr, "ListDownloadTaskStatus"}, - {705, nullptr, "RequestDownloadTaskListData"}, - {706, nullptr, "TryCommitCurrentApplicationDownloadTask"}, - {707, nullptr, "EnableAutoCommit"}, - {708, nullptr, "DisableAutoCommit"}, - {709, nullptr, "TriggerDynamicCommitEvent"}, - }; - // clang-format on + const auto res = ConvertApplicationLanguageToLanguageCode(application_language); + if (res.Succeeded()) { + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(RESULT_SUCCESS); + rb.Push(*res); + } else { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(res.Code()); + } +} - RegisterHandlers(functions); +ResultVal<u64> IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode( + u8 application_language) { + const auto language_code = + ConvertToLanguageCode(static_cast<ApplicationLanguage>(application_language)); + if (language_code == std::nullopt) { + return ERR_APPLICATION_LANGUAGE_NOT_FOUND; } -}; -class IECommerceInterface final : public ServiceFramework<IECommerceInterface> { -public: - explicit IECommerceInterface() : ServiceFramework{"IECommerceInterface"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "RequestLinkDevice"}, - {1, nullptr, "RequestCleanupAllPreInstalledApplications"}, - {2, nullptr, "RequestCleanupPreInstalledApplication"}, - {3, nullptr, "RequestSyncRights"}, - {4, nullptr, "RequestUnlinkDevice"}, - {5, nullptr, "RequestRevokeAllELicense"}, - }; - // clang-format on + return MakeResult(static_cast<u64>(*language_code)); +} - RegisterHandlers(functions); - } -}; +IApplicationVersionInterface::IApplicationVersionInterface() + : ServiceFramework{"IApplicationVersionInterface"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "GetLaunchRequiredVersion"}, + {1, nullptr, "UpgradeLaunchRequiredVersion"}, + {35, nullptr, "UpdateVersionList"}, + {36, nullptr, "PushLaunchVersion"}, + {37, nullptr, "ListRequiredVersion"}, + {800, nullptr, "RequestVersionList"}, + {801, nullptr, "ListVersionList"}, + {802, nullptr, "RequestVersionListData"}, + {1000, nullptr, "PerformAutoUpdate"}, + }; + // clang-format on + + RegisterHandlers(functions); +} -class IFactoryResetInterface final : public ServiceFramework<IFactoryResetInterface> { -public: - explicit IFactoryResetInterface() : ServiceFramework{"IFactoryResetInterface"} { - // clang-format off +IApplicationVersionInterface::~IApplicationVersionInterface() = default; + +IContentManagerInterface::IContentManagerInterface() + : ServiceFramework{"IContentManagerInterface"} { + // clang-format off + static const FunctionInfo functions[] = { + {11, nullptr, "CalculateApplicationOccupiedSize"}, + {43, nullptr, "CheckSdCardMountStatus"}, + {47, nullptr, "GetTotalSpaceSize"}, + {48, nullptr, "GetFreeSpaceSize"}, + {600, nullptr, "CountApplicationContentMeta"}, + {601, nullptr, "ListApplicationContentMetaStatus"}, + {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"}, + {607, nullptr, "IsAnyApplicationRunning"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IContentManagerInterface::~IContentManagerInterface() = default; + +IDocumentInterface::IDocumentInterface() : ServiceFramework{"IDocumentInterface"} { + // clang-format off + static const FunctionInfo functions[] = { + {21, nullptr, "GetApplicationContentPath"}, + {23, nullptr, "ResolveApplicationContentPath"}, + {93, nullptr, "GetRunningApplicationProgramId"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IDocumentInterface::~IDocumentInterface() = default; + +IDownloadTaskInterface::IDownloadTaskInterface() : ServiceFramework{"IDownloadTaskInterface"} { + // clang-format off + static const FunctionInfo functions[] = { + {701, nullptr, "ClearTaskStatusList"}, + {702, nullptr, "RequestDownloadTaskList"}, + {703, nullptr, "RequestEnsureDownloadTask"}, + {704, nullptr, "ListDownloadTaskStatus"}, + {705, nullptr, "RequestDownloadTaskListData"}, + {706, nullptr, "TryCommitCurrentApplicationDownloadTask"}, + {707, nullptr, "EnableAutoCommit"}, + {708, nullptr, "DisableAutoCommit"}, + {709, nullptr, "TriggerDynamicCommitEvent"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IDownloadTaskInterface::~IDownloadTaskInterface() = default; + +IECommerceInterface::IECommerceInterface() : ServiceFramework{"IECommerceInterface"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "RequestLinkDevice"}, + {1, nullptr, "RequestCleanupAllPreInstalledApplications"}, + {2, nullptr, "RequestCleanupPreInstalledApplication"}, + {3, nullptr, "RequestSyncRights"}, + {4, nullptr, "RequestUnlinkDevice"}, + {5, nullptr, "RequestRevokeAllELicense"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IECommerceInterface::~IECommerceInterface() = default; + +IFactoryResetInterface::IFactoryResetInterface::IFactoryResetInterface() + : ServiceFramework{"IFactoryResetInterface"} { + // clang-format off static const FunctionInfo functions[] = { {100, nullptr, "ResetToFactorySettings"}, {101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"}, {102, nullptr, "ResetToFactorySettingsForRefurbishment"}, }; - // clang-format on + // clang-format on - RegisterHandlers(functions); - } -}; - -class NS final : public ServiceFramework<NS> { -public: - explicit NS(const char* name) : ServiceFramework{name} { - // clang-format off - static const FunctionInfo functions[] = { - {7992, &NS::PushInterface<IECommerceInterface>, "GetECommerceInterface"}, - {7993, &NS::PushInterface<IApplicationVersionInterface>, "GetApplicationVersionInterface"}, - {7994, &NS::PushInterface<IFactoryResetInterface>, "GetFactoryResetInterface"}, - {7995, &NS::PushInterface<IAccountProxyInterface>, "GetAccountProxyInterface"}, - {7996, &NS::PushInterface<IApplicationManagerInterface>, "GetApplicationManagerInterface"}, - {7997, &NS::PushInterface<IDownloadTaskInterface>, "GetDownloadTaskInterface"}, - {7998, &NS::PushInterface<IContentManagerInterface>, "GetContentManagementInterface"}, - {7999, &NS::PushInterface<IDocumentInterface>, "GetDocumentInterface"}, - }; - // clang-format on + RegisterHandlers(functions); +} - RegisterHandlers(functions); - } +IFactoryResetInterface::~IFactoryResetInterface() = default; + +NS::NS(const char* name) : ServiceFramework{name} { + // clang-format off + static const FunctionInfo functions[] = { + {7992, &NS::PushInterface<IECommerceInterface>, "GetECommerceInterface"}, + {7993, &NS::PushInterface<IApplicationVersionInterface>, "GetApplicationVersionInterface"}, + {7994, &NS::PushInterface<IFactoryResetInterface>, "GetFactoryResetInterface"}, + {7995, &NS::PushInterface<IAccountProxyInterface>, "GetAccountProxyInterface"}, + {7996, &NS::PushInterface<IApplicationManagerInterface>, "GetApplicationManagerInterface"}, + {7997, &NS::PushInterface<IDownloadTaskInterface>, "GetDownloadTaskInterface"}, + {7998, &NS::PushInterface<IContentManagerInterface>, "GetContentManagementInterface"}, + {7999, &NS::PushInterface<IDocumentInterface>, "GetDocumentInterface"}, + }; + // clang-format on + + RegisterHandlers(functions); +} -private: - template <typename T> - void PushInterface(Kernel::HLERequestContext& ctx) { - LOG_DEBUG(Service_NS, "called"); +NS::~NS() = default; - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<T>(); - } -}; +std::shared_ptr<IApplicationManagerInterface> NS::GetApplicationManagerInterface() const { + return GetInterface<IApplicationManagerInterface>(); +} class NS_DEV final : public ServiceFramework<NS_DEV> { public: diff --git a/src/core/hle/service/ns/ns.h b/src/core/hle/service/ns/ns.h index b81ca8f1e..0f4bab4cb 100644 --- a/src/core/hle/service/ns/ns.h +++ b/src/core/hle/service/ns/ns.h @@ -8,6 +8,88 @@ namespace Service::NS { +class IAccountProxyInterface final : public ServiceFramework<IAccountProxyInterface> { +public: + explicit IAccountProxyInterface(); + ~IAccountProxyInterface(); +}; + +class IApplicationManagerInterface final : public ServiceFramework<IApplicationManagerInterface> { +public: + explicit IApplicationManagerInterface(); + ~IApplicationManagerInterface(); + + ResultVal<u8> GetApplicationDesiredLanguage(u32 supported_languages); + ResultVal<u64> ConvertApplicationLanguageToLanguageCode(u8 application_language); + +private: + void GetApplicationControlData(Kernel::HLERequestContext& ctx); + void GetApplicationDesiredLanguage(Kernel::HLERequestContext& ctx); + void ConvertApplicationLanguageToLanguageCode(Kernel::HLERequestContext& ctx); +}; + +class IApplicationVersionInterface final : public ServiceFramework<IApplicationVersionInterface> { +public: + explicit IApplicationVersionInterface(); + ~IApplicationVersionInterface(); +}; + +class IContentManagerInterface final : public ServiceFramework<IContentManagerInterface> { +public: + explicit IContentManagerInterface(); + ~IContentManagerInterface(); +}; + +class IDocumentInterface final : public ServiceFramework<IDocumentInterface> { +public: + explicit IDocumentInterface(); + ~IDocumentInterface(); +}; + +class IDownloadTaskInterface final : public ServiceFramework<IDownloadTaskInterface> { +public: + explicit IDownloadTaskInterface(); + ~IDownloadTaskInterface(); +}; + +class IECommerceInterface final : public ServiceFramework<IECommerceInterface> { +public: + explicit IECommerceInterface(); + ~IECommerceInterface(); +}; + +class IFactoryResetInterface final : public ServiceFramework<IFactoryResetInterface> { +public: + explicit IFactoryResetInterface(); + ~IFactoryResetInterface(); +}; + +class NS final : public ServiceFramework<NS> { +public: + explicit NS(const char* name); + ~NS(); + + std::shared_ptr<IApplicationManagerInterface> GetApplicationManagerInterface() const; + +private: + template <typename T> + void PushInterface(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_NS, "called"); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface<T>(); + } + + template <typename T> + std::shared_ptr<T> GetInterface() const { + static_assert(std::is_base_of_v<Kernel::SessionRequestHandler, T>, + "Not a base of ServiceFrameworkBase"); + + return std::make_shared<T>(); + } +}; + /// Registers all NS services with the specified service manager. void InstallInterfaces(SM::ServiceManager& service_manager); diff --git a/src/core/hle/service/ns/ns_language.h b/src/core/hle/service/ns/ns_language.h new file mode 100644 index 000000000..59ac85a19 --- /dev/null +++ b/src/core/hle/service/ns/ns_language.h @@ -0,0 +1,42 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once +#include <optional> +#include <string> +#include "common/common_types.h" +#include "core/hle/service/set/set.h" + +namespace Service::NS { +/// This is nn::ns::detail::ApplicationLanguage +enum class ApplicationLanguage : u8 { + AmericanEnglish = 0, + BritishEnglish, + Japanese, + French, + German, + LatinAmericanSpanish, + Spanish, + Italian, + Dutch, + CanadianFrench, + Portuguese, + Russian, + Korean, + TraditionalChinese, + SimplifiedChinese, + Count +}; +using ApplicationLanguagePriorityList = + const std::array<ApplicationLanguage, static_cast<std::size_t>(ApplicationLanguage::Count)>; + +constexpr u32 GetSupportedLanguageFlag(const ApplicationLanguage lang) { + return 1U << static_cast<u32>(lang); +} + +const ApplicationLanguagePriorityList* GetApplicationLanguagePriorityList(ApplicationLanguage lang); +std::optional<ApplicationLanguage> ConvertToApplicationLanguage( + Service::Set::LanguageCode language_code); +std::optional<Service::Set::LanguageCode> ConvertToLanguageCode(ApplicationLanguage lang); +} // namespace Service::NS
\ No newline at end of file diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp index 45812d238..0e28755bd 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp @@ -185,7 +185,8 @@ u32 nvhost_ctrl_gpu::GetGpuTime(const std::vector<u8>& input, std::vector<u8>& o IoctlGetGpuTime params{}; std::memcpy(¶ms, input.data(), input.size()); - params.gpu_time = Core::Timing::cyclesToNs(Core::System::GetInstance().CoreTiming().GetTicks()); + const auto ns = Core::Timing::CyclesToNs(Core::System::GetInstance().CoreTiming().GetTicks()); + params.gpu_time = static_cast<u64_le>(ns.count()); std::memcpy(output.data(), ¶ms, output.size()); return 0; } diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp index aa115935d..346bad80d 100644 --- a/src/core/hle/service/time/time.cpp +++ b/src/core/hle/service/time/time.cpp @@ -108,8 +108,9 @@ private: LOG_DEBUG(Service_Time, "called"); const auto& core_timing = Core::System::GetInstance().CoreTiming(); - const SteadyClockTimePoint steady_clock_time_point{ - Core::Timing::cyclesToMs(core_timing.GetTicks()) / 1000}; + const auto ms = Core::Timing::CyclesToMs(core_timing.GetTicks()); + const SteadyClockTimePoint steady_clock_time_point{static_cast<u64_le>(ms.count() / 1000), + {}}; IPC::ResponseBuilder rb{ctx, (sizeof(SteadyClockTimePoint) / 4) + 2}; rb.Push(RESULT_SUCCESS); rb.PushRaw(steady_clock_time_point); @@ -284,8 +285,8 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) { } const auto& core_timing = Core::System::GetInstance().CoreTiming(); - const SteadyClockTimePoint steady_clock_time_point{ - Core::Timing::cyclesToMs(core_timing.GetTicks()) / 1000, {}}; + const auto ms = Core::Timing::CyclesToMs(core_timing.GetTicks()); + const SteadyClockTimePoint steady_clock_time_point{static_cast<u64_le>(ms.count() / 1000), {}}; CalendarTime calendar_time{}; calendar_time.year = tm->tm_year + 1900; diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index f7846db52..869406b75 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h @@ -154,17 +154,6 @@ public: virtual LoadResult Load(Kernel::Process& process) = 0; /** - * Loads the system mode that this application needs. - * This function defaults to 2 (96MB allocated to the application) if it can't read the - * information. - * @returns A pair with the optional system mode, and and the status. - */ - virtual std::pair<std::optional<u32>, ResultStatus> LoadKernelSystemMode() { - // 96MB allocated to the application. - return std::make_pair(2, ResultStatus::Success); - } - - /** * Get the code (typically .code section) of the application * @param buffer Reference to buffer to store data * @return ResultStatus result of function diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp index 4b17bada5..90d06830f 100644 --- a/src/core/telemetry_session.cpp +++ b/src/core/telemetry_session.cpp @@ -12,7 +12,6 @@ #include "common/file_util.h" #include "common/logging/log.h" -#include "core/core.h" #include "core/file_sys/control_metadata.h" #include "core/file_sys/patch_manager.h" #include "core/loader/loader.h" @@ -101,7 +100,30 @@ bool VerifyLogin(const std::string& username, const std::string& token) { #endif } -TelemetrySession::TelemetrySession() { +TelemetrySession::TelemetrySession() = default; + +TelemetrySession::~TelemetrySession() { + // Log one-time session end information + const s64 shutdown_time{std::chrono::duration_cast<std::chrono::milliseconds>( + std::chrono::system_clock::now().time_since_epoch()) + .count()}; + AddField(Telemetry::FieldType::Session, "Shutdown_Time", shutdown_time); + +#ifdef ENABLE_WEB_SERVICE + auto backend = std::make_unique<WebService::TelemetryJson>( + Settings::values.web_api_url, Settings::values.yuzu_username, Settings::values.yuzu_token); +#else + auto backend = std::make_unique<Telemetry::NullVisitor>(); +#endif + + // Complete the session, submitting to the web service backend if necessary + field_collection.Accept(*backend); + if (Settings::values.enable_telemetry) { + backend->Complete(); + } +} + +void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader) { // Log one-time top-level information AddField(Telemetry::FieldType::None, "TelemetryId", GetTelemetryId()); @@ -112,26 +134,28 @@ TelemetrySession::TelemetrySession() { AddField(Telemetry::FieldType::Session, "Init_Time", init_time); u64 program_id{}; - const Loader::ResultStatus res{System::GetInstance().GetAppLoader().ReadProgramId(program_id)}; + const Loader::ResultStatus res{app_loader.ReadProgramId(program_id)}; if (res == Loader::ResultStatus::Success) { const std::string formatted_program_id{fmt::format("{:016X}", program_id)}; AddField(Telemetry::FieldType::Session, "ProgramId", formatted_program_id); std::string name; - System::GetInstance().GetAppLoader().ReadTitle(name); + app_loader.ReadTitle(name); if (name.empty()) { auto [nacp, icon_file] = FileSys::PatchManager(program_id).GetControlMetadata(); - if (nacp != nullptr) + if (nacp != nullptr) { name = nacp->GetApplicationName(); + } } - if (!name.empty()) + if (!name.empty()) { AddField(Telemetry::FieldType::Session, "ProgramName", name); + } } AddField(Telemetry::FieldType::Session, "ProgramFormat", - static_cast<u8>(System::GetInstance().GetAppLoader().GetFileType())); + static_cast<u8>(app_loader.GetFileType())); // Log application information Telemetry::AppendBuildInfo(field_collection); @@ -162,27 +186,6 @@ TelemetrySession::TelemetrySession() { Settings::values.use_docked_mode); } -TelemetrySession::~TelemetrySession() { - // Log one-time session end information - const s64 shutdown_time{std::chrono::duration_cast<std::chrono::milliseconds>( - std::chrono::system_clock::now().time_since_epoch()) - .count()}; - AddField(Telemetry::FieldType::Session, "Shutdown_Time", shutdown_time); - -#ifdef ENABLE_WEB_SERVICE - auto backend = std::make_unique<WebService::TelemetryJson>( - Settings::values.web_api_url, Settings::values.yuzu_username, Settings::values.yuzu_token); -#else - auto backend = std::make_unique<Telemetry::NullVisitor>(); -#endif - - // Complete the session, submitting to web service if necessary - field_collection.Accept(*backend); - if (Settings::values.enable_telemetry) - backend->Complete(); - backend = nullptr; -} - bool TelemetrySession::SubmitTestcase() { #ifdef ENABLE_WEB_SERVICE auto backend = std::make_unique<WebService::TelemetryJson>( diff --git a/src/core/telemetry_session.h b/src/core/telemetry_session.h index cae5a45a0..17ac22377 100644 --- a/src/core/telemetry_session.h +++ b/src/core/telemetry_session.h @@ -4,10 +4,13 @@ #pragma once -#include <memory> #include <string> #include "common/telemetry.h" +namespace Loader { +class AppLoader; +} + namespace Core { /** @@ -15,11 +18,33 @@ namespace Core { * session, logging any one-time fields. Interfaces with the telemetry backend used for submitting * data to the web service. Submits session data on close. */ -class TelemetrySession : NonCopyable { +class TelemetrySession { public: - TelemetrySession(); + explicit TelemetrySession(); ~TelemetrySession(); + TelemetrySession(const TelemetrySession&) = delete; + TelemetrySession& operator=(const TelemetrySession&) = delete; + + TelemetrySession(TelemetrySession&&) = delete; + TelemetrySession& operator=(TelemetrySession&&) = delete; + + /** + * Adds the initial telemetry info necessary when starting up a title. + * + * This includes information such as: + * - Telemetry ID + * - Initialization time + * - Title ID + * - Title name + * - Title file format + * - Miscellaneous settings values. + * + * @param app_loader The application loader to use to retrieve + * title-specific information. + */ + void AddInitialInfo(Loader::AppLoader& app_loader); + /** * Wrapper around the Telemetry::FieldCollection::AddField method. * @param type Type of the field to add. diff --git a/src/input_common/sdl/sdl.h b/src/input_common/sdl/sdl.h index d7f24c68a..5306daa70 100644 --- a/src/input_common/sdl/sdl.h +++ b/src/input_common/sdl/sdl.h @@ -6,15 +6,8 @@ #include <memory> #include <vector> -#include "core/frontend/input.h" #include "input_common/main.h" -union SDL_Event; - -namespace Common { -class ParamPackage; -} // namespace Common - namespace InputCommon::Polling { class DevicePoller; enum class DeviceType; diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp index 0b69bfede..d2e9d278f 100644 --- a/src/input_common/sdl/sdl_impl.cpp +++ b/src/input_common/sdl/sdl_impl.cpp @@ -6,7 +6,6 @@ #include <atomic> #include <cmath> #include <functional> -#include <iterator> #include <mutex> #include <string> #include <thread> @@ -15,7 +14,6 @@ #include <utility> #include <vector> #include <SDL.h> -#include "common/assert.h" #include "common/logging/log.h" #include "common/math_util.h" #include "common/param_package.h" @@ -23,12 +21,10 @@ #include "core/frontend/input.h" #include "input_common/sdl/sdl_impl.h" -namespace InputCommon { - -namespace SDL { +namespace InputCommon::SDL { static std::string GetGUID(SDL_Joystick* joystick) { - SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick); + const SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick); char guid_str[33]; SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str)); return guid_str; @@ -37,26 +33,27 @@ static std::string GetGUID(SDL_Joystick* joystick) { /// Creates a ParamPackage from an SDL_Event that can directly be used to create a ButtonDevice static Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event); -static int SDLEventWatcher(void* userdata, SDL_Event* event) { - SDLState* sdl_state = reinterpret_cast<SDLState*>(userdata); +static int SDLEventWatcher(void* user_data, SDL_Event* event) { + auto* const sdl_state = static_cast<SDLState*>(user_data); + // Don't handle the event if we are configuring if (sdl_state->polling) { sdl_state->event_queue.Push(*event); } else { sdl_state->HandleGameControllerEvent(*event); } + return 0; } class SDLJoystick { public: - SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick, - decltype(&SDL_JoystickClose) deleter = &SDL_JoystickClose) - : guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, deleter} {} + SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick) + : guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose} {} void SetButton(int button, bool value) { std::lock_guard lock{mutex}; - state.buttons[button] = value; + state.buttons.insert_or_assign(button, value); } bool GetButton(int button) const { @@ -66,7 +63,7 @@ public: void SetAxis(int axis, Sint16 value) { std::lock_guard lock{mutex}; - state.axes[axis] = value; + state.axes.insert_or_assign(axis, value); } float GetAxis(int axis) const { @@ -93,7 +90,7 @@ public: void SetHat(int hat, Uint8 direction) { std::lock_guard lock{mutex}; - state.hats[hat] = direction; + state.hats.insert_or_assign(hat, direction); } bool GetHatDirection(int hat, Uint8 direction) const { @@ -118,10 +115,8 @@ public: return sdl_joystick.get(); } - void SetSDLJoystick(SDL_Joystick* joystick, - decltype(&SDL_JoystickClose) deleter = &SDL_JoystickClose) { - sdl_joystick = - std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)>(joystick, deleter); + void SetSDLJoystick(SDL_Joystick* joystick) { + sdl_joystick.reset(joystick); } private: @@ -136,59 +131,57 @@ private: mutable std::mutex mutex; }; -/** - * Get the nth joystick with the corresponding GUID - */ std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickByGUID(const std::string& guid, int port) { std::lock_guard lock{joystick_map_mutex}; const auto it = joystick_map.find(guid); if (it != joystick_map.end()) { while (it->second.size() <= static_cast<std::size_t>(port)) { - auto joystick = std::make_shared<SDLJoystick>(guid, static_cast<int>(it->second.size()), - nullptr, [](SDL_Joystick*) {}); + auto joystick = + std::make_shared<SDLJoystick>(guid, static_cast<int>(it->second.size()), nullptr); it->second.emplace_back(std::move(joystick)); } return it->second[port]; } - auto joystick = std::make_shared<SDLJoystick>(guid, 0, nullptr, [](SDL_Joystick*) {}); + auto joystick = std::make_shared<SDLJoystick>(guid, 0, nullptr); return joystick_map[guid].emplace_back(std::move(joystick)); } -/** - * Check how many identical joysticks (by guid) were connected before the one with sdl_id and so tie - * it to a SDLJoystick with the same guid and that port - */ std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickBySDLID(SDL_JoystickID sdl_id) { auto sdl_joystick = SDL_JoystickFromInstanceID(sdl_id); const std::string guid = GetGUID(sdl_joystick); std::lock_guard lock{joystick_map_mutex}; - auto map_it = joystick_map.find(guid); + const auto map_it = joystick_map.find(guid); if (map_it != joystick_map.end()) { - auto vec_it = std::find_if(map_it->second.begin(), map_it->second.end(), - [&sdl_joystick](const std::shared_ptr<SDLJoystick>& joystick) { - return sdl_joystick == joystick->GetSDLJoystick(); - }); + const auto vec_it = + std::find_if(map_it->second.begin(), map_it->second.end(), + [&sdl_joystick](const std::shared_ptr<SDLJoystick>& joystick) { + return sdl_joystick == joystick->GetSDLJoystick(); + }); if (vec_it != map_it->second.end()) { // This is the common case: There is already an existing SDL_Joystick maped to a // SDLJoystick. return the SDLJoystick return *vec_it; } + // Search for a SDLJoystick without a mapped SDL_Joystick... - auto nullptr_it = std::find_if(map_it->second.begin(), map_it->second.end(), - [](const std::shared_ptr<SDLJoystick>& joystick) { - return !joystick->GetSDLJoystick(); - }); + const auto nullptr_it = std::find_if(map_it->second.begin(), map_it->second.end(), + [](const std::shared_ptr<SDLJoystick>& joystick) { + return !joystick->GetSDLJoystick(); + }); if (nullptr_it != map_it->second.end()) { // ... and map it (*nullptr_it)->SetSDLJoystick(sdl_joystick); return *nullptr_it; } + // There is no SDLJoystick without a mapped SDL_Joystick // Create a new SDLJoystick - auto joystick = std::make_shared<SDLJoystick>(guid, map_it->second.size(), sdl_joystick); + const int port = static_cast<int>(map_it->second.size()); + auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick); return map_it->second.emplace_back(std::move(joystick)); } + auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick); return joystick_map[guid].emplace_back(std::move(joystick)); } @@ -215,17 +208,19 @@ void SDLState::InitJoystick(int joystick_index) { (*it)->SetSDLJoystick(sdl_joystick); return; } - auto joystick = std::make_shared<SDLJoystick>(guid, joystick_guid_list.size(), sdl_joystick); + const int port = static_cast<int>(joystick_guid_list.size()); + auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick); joystick_guid_list.emplace_back(std::move(joystick)); } void SDLState::CloseJoystick(SDL_Joystick* sdl_joystick) { - std::string guid = GetGUID(sdl_joystick); + const std::string guid = GetGUID(sdl_joystick); + std::shared_ptr<SDLJoystick> joystick; { std::lock_guard lock{joystick_map_mutex}; // This call to guid is safe since the joystick is guaranteed to be in the map - auto& joystick_guid_list = joystick_map[guid]; + const auto& joystick_guid_list = joystick_map[guid]; const auto joystick_it = std::find_if(joystick_guid_list.begin(), joystick_guid_list.end(), [&sdl_joystick](const std::shared_ptr<SDLJoystick>& joystick) { @@ -233,9 +228,10 @@ void SDLState::CloseJoystick(SDL_Joystick* sdl_joystick) { }); joystick = *joystick_it; } - // Destruct SDL_Joystick outside the lock guard because SDL can internally call event calback - // which locks the mutex again - joystick->SetSDLJoystick(nullptr, [](SDL_Joystick*) {}); + + // Destruct SDL_Joystick outside the lock guard because SDL can internally call the + // event callback which locks the mutex again. + joystick->SetSDLJoystick(nullptr); } void SDLState::HandleGameControllerEvent(const SDL_Event& event) { @@ -317,9 +313,10 @@ public: trigger_if_greater(trigger_if_greater_) {} bool GetStatus() const override { - float axis_value = joystick->GetAxis(axis); - if (trigger_if_greater) + const float axis_value = joystick->GetAxis(axis); + if (trigger_if_greater) { return axis_value > threshold; + } return axis_value < threshold; } @@ -444,7 +441,7 @@ public: const int port = params.Get("port", 0); const int axis_x = params.Get("axis_x", 0); const int axis_y = params.Get("axis_y", 1); - float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, .99f); + const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, .99f); auto joystick = state.GetSDLJoystickByGUID(guid, port); @@ -470,7 +467,7 @@ SDLState::SDLState() { return; } if (SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1") == SDL_FALSE) { - LOG_ERROR(Input, "Failed to set Hint for background events", SDL_GetError()); + LOG_ERROR(Input, "Failed to set hint for background events with: {}", SDL_GetError()); } SDL_AddEventWatch(&SDLEventWatcher, this); @@ -507,12 +504,12 @@ SDLState::~SDLState() { } } -Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event) { +static Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event) { Common::ParamPackage params({{"engine", "sdl"}}); switch (event.type) { case SDL_JOYAXISMOTION: { - auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); + const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); params.Set("port", joystick->GetPort()); params.Set("guid", joystick->GetGUID()); params.Set("axis", event.jaxis.axis); @@ -526,14 +523,14 @@ Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Eve break; } case SDL_JOYBUTTONUP: { - auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which); + const auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which); params.Set("port", joystick->GetPort()); params.Set("guid", joystick->GetGUID()); params.Set("button", event.jbutton.button); break; } case SDL_JOYHATMOTION: { - auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which); + const auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which); params.Set("port", joystick->GetPort()); params.Set("guid", joystick->GetGUID()); params.Set("hat", event.jhat.hat); @@ -607,8 +604,8 @@ public: SDLPoller::Start(); // Reset stored axes - analog_xaxis = -1; - analog_yaxis = -1; + analog_x_axis = -1; + analog_y_axis = -1; analog_axes_joystick = -1; } @@ -620,25 +617,25 @@ public: } // An analog device needs two axes, so we need to store the axis for later and wait for // a second SDL event. The axes also must be from the same joystick. - int axis = event.jaxis.axis; - if (analog_xaxis == -1) { - analog_xaxis = axis; + const int axis = event.jaxis.axis; + if (analog_x_axis == -1) { + analog_x_axis = axis; analog_axes_joystick = event.jaxis.which; - } else if (analog_yaxis == -1 && analog_xaxis != axis && + } else if (analog_y_axis == -1 && analog_x_axis != axis && analog_axes_joystick == event.jaxis.which) { - analog_yaxis = axis; + analog_y_axis = axis; } } Common::ParamPackage params; - if (analog_xaxis != -1 && analog_yaxis != -1) { - auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); + if (analog_x_axis != -1 && analog_y_axis != -1) { + const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); params.Set("engine", "sdl"); params.Set("port", joystick->GetPort()); params.Set("guid", joystick->GetGUID()); - params.Set("axis_x", analog_xaxis); - params.Set("axis_y", analog_yaxis); - analog_xaxis = -1; - analog_yaxis = -1; + params.Set("axis_x", analog_x_axis); + params.Set("axis_y", analog_y_axis); + analog_x_axis = -1; + analog_y_axis = -1; analog_axes_joystick = -1; return params; } @@ -646,8 +643,8 @@ public: } private: - int analog_xaxis = -1; - int analog_yaxis = -1; + int analog_x_axis = -1; + int analog_y_axis = -1; SDL_JoystickID analog_axes_joystick = -1; }; } // namespace Polling @@ -667,5 +664,4 @@ SDLState::Pollers SDLState::GetPollers(InputCommon::Polling::DeviceType type) { return pollers; } -} // namespace SDL -} // namespace InputCommon +} // namespace InputCommon::SDL diff --git a/src/input_common/sdl/sdl_impl.h b/src/input_common/sdl/sdl_impl.h index 2579741d6..606a32c5b 100644 --- a/src/input_common/sdl/sdl_impl.h +++ b/src/input_common/sdl/sdl_impl.h @@ -6,7 +6,10 @@ #include <atomic> #include <memory> +#include <mutex> #include <thread> +#include <unordered_map> +#include "common/common_types.h" #include "common/threadsafe_queue.h" #include "input_common/sdl/sdl.h" @@ -16,9 +19,9 @@ using SDL_JoystickID = s32; namespace InputCommon::SDL { -class SDLJoystick; -class SDLButtonFactory; class SDLAnalogFactory; +class SDLButtonFactory; +class SDLJoystick; class SDLState : public State { public: @@ -31,7 +34,13 @@ public: /// Handle SDL_Events for joysticks from SDL_PollEvent void HandleGameControllerEvent(const SDL_Event& event); + /// Get the nth joystick with the corresponding GUID std::shared_ptr<SDLJoystick> GetSDLJoystickBySDLID(SDL_JoystickID sdl_id); + + /** + * Check how many identical joysticks (by guid) were connected before the one with sdl_id and so + * tie it to a SDLJoystick with the same guid and that port + */ std::shared_ptr<SDLJoystick> GetSDLJoystickByGUID(const std::string& guid, int port); /// Get all DevicePoller that use the SDL backend for a specific device type diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index e83f25fa1..ffb3ec3e0 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -1663,6 +1663,7 @@ private: INST("111000100100----", Id::BRA, Type::Flow, "BRA"), INST("1111000011111---", Id::SYNC, Type::Flow, "SYNC"), INST("111000110100---", Id::BRK, Type::Flow, "BRK"), + INST("111000110000----", Id::EXIT, Type::Flow, "EXIT"), INST("1111000011110---", Id::DEPBAR, Type::Synch, "DEPBAR"), INST("1110111111011---", Id::LD_A, Type::Memory, "LD_A"), INST("1110111101001---", Id::LD_S, Type::Memory, "LD_S"), @@ -1686,7 +1687,6 @@ private: INST("1101111100------", Id::TLD4S, Type::Texture, "TLD4S"), INST("110111110110----", Id::TMML_B, Type::Texture, "TMML_B"), INST("1101111101011---", Id::TMML, Type::Texture, "TMML"), - INST("111000110000----", Id::EXIT, Type::Trivial, "EXIT"), INST("11100000--------", Id::IPA, Type::Trivial, "IPA"), INST("1111101111100---", Id::OUT_R, Type::Trivial, "OUT_R"), INST("1110111111010---", Id::ISBERD, Type::Trivial, "ISBERD"), diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index 1e2ff46b0..3f0939ec9 100644 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp @@ -75,7 +75,7 @@ void ThreadManager::StartThread(VideoCore::RendererBase& renderer, Tegra::DmaPus void ThreadManager::SubmitList(Tegra::CommandList&& entries) { const u64 fence{PushCommand(SubmitListCommand(std::move(entries)))}; - const s64 synchronization_ticks{Core::Timing::usToCycles(9000)}; + const s64 synchronization_ticks{Core::Timing::usToCycles(std::chrono::microseconds{9000})}; system.CoreTiming().ScheduleEvent(synchronization_ticks, synchronization_event, fence); } diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp index 1d1581f49..65a88b06c 100644 --- a/src/video_core/renderer_opengl/gl_device.cpp +++ b/src/video_core/renderer_opengl/gl_device.cpp @@ -2,11 +2,14 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <array> #include <cstddef> #include <glad/glad.h> #include "common/logging/log.h" +#include "common/scope_exit.h" #include "video_core/renderer_opengl/gl_device.h" +#include "video_core/renderer_opengl/gl_resource_manager.h" namespace OpenGL { @@ -24,6 +27,7 @@ Device::Device() { max_vertex_attributes = GetInteger<u32>(GL_MAX_VERTEX_ATTRIBS); max_varyings = GetInteger<u32>(GL_MAX_VARYING_VECTORS); has_variable_aoffi = TestVariableAoffi(); + has_component_indexing_bug = TestComponentIndexingBug(); } Device::Device(std::nullptr_t) { @@ -31,6 +35,7 @@ Device::Device(std::nullptr_t) { max_vertex_attributes = 16; max_varyings = 15; has_variable_aoffi = true; + has_component_indexing_bug = false; } bool Device::TestVariableAoffi() { @@ -52,4 +57,53 @@ void main() { return supported; } +bool Device::TestComponentIndexingBug() { + constexpr char log_message[] = "Renderer_ComponentIndexingBug: {}"; + const GLchar* COMPONENT_TEST = R"(#version 430 core +layout (std430, binding = 0) buffer OutputBuffer { + uint output_value; +}; +layout (std140, binding = 0) uniform InputBuffer { + uvec4 input_value[4096]; +}; +layout (location = 0) uniform uint idx; +void main() { + output_value = input_value[idx >> 2][idx & 3]; +})"; + const GLuint shader{glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &COMPONENT_TEST)}; + SCOPE_EXIT({ glDeleteProgram(shader); }); + glUseProgram(shader); + + OGLVertexArray vao; + vao.Create(); + glBindVertexArray(vao.handle); + + constexpr std::array<GLuint, 8> values{0, 0, 0, 0, 0x1236327, 0x985482, 0x872753, 0x2378432}; + OGLBuffer ubo; + ubo.Create(); + glNamedBufferData(ubo.handle, sizeof(values), values.data(), GL_STATIC_DRAW); + glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo.handle); + + OGLBuffer ssbo; + ssbo.Create(); + glNamedBufferStorage(ssbo.handle, sizeof(GLuint), nullptr, GL_CLIENT_STORAGE_BIT); + + for (GLuint index = 4; index < 8; ++index) { + glInvalidateBufferData(ssbo.handle); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo.handle); + + glProgramUniform1ui(shader, 0, index); + glDrawArrays(GL_POINTS, 0, 1); + + GLuint result; + glGetNamedBufferSubData(ssbo.handle, 0, sizeof(result), &result); + if (result != values.at(index)) { + LOG_INFO(Render_OpenGL, log_message, true); + return true; + } + } + LOG_INFO(Render_OpenGL, log_message, false); + return false; +} + } // namespace OpenGL diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h index de8490682..8c8c93760 100644 --- a/src/video_core/renderer_opengl/gl_device.h +++ b/src/video_core/renderer_opengl/gl_device.h @@ -30,13 +30,19 @@ public: return has_variable_aoffi; } + bool HasComponentIndexingBug() const { + return has_component_indexing_bug; + } + private: static bool TestVariableAoffi(); + static bool TestComponentIndexingBug(); std::size_t uniform_buffer_alignment{}; u32 max_vertex_attributes{}; u32 max_varyings{}; bool has_variable_aoffi{}; + bool has_component_indexing_bug{}; }; } // namespace OpenGL diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index d66252224..ac8a9e6b7 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -35,8 +35,8 @@ struct UnspecializedShader { namespace { /// Gets the address for the specified shader stage program -GPUVAddr GetShaderAddress(Maxwell::ShaderProgram program) { - const auto& gpu{Core::System::GetInstance().GPU().Maxwell3D()}; +GPUVAddr GetShaderAddress(Core::System& system, Maxwell::ShaderProgram program) { + const auto& gpu{system.GPU().Maxwell3D()}; const auto& shader_config{gpu.regs.shader_config[static_cast<std::size_t>(program)]}; return gpu.regs.code_address.CodeAddress() + shader_config.offset; } @@ -350,7 +350,8 @@ ShaderDiskCacheUsage CachedShader::GetUsage(GLenum primitive_mode, ShaderCacheOpenGL::ShaderCacheOpenGL(RasterizerOpenGL& rasterizer, Core::System& system, Core::Frontend::EmuWindow& emu_window, const Device& device) - : RasterizerCache{rasterizer}, emu_window{emu_window}, device{device}, disk_cache{system} {} + : RasterizerCache{rasterizer}, system{system}, emu_window{emu_window}, device{device}, + disk_cache{system} {} void ShaderCacheOpenGL::LoadDiskCache(const std::atomic_bool& stop_loading, const VideoCore::DiskResourceLoadCallback& callback) { @@ -546,42 +547,45 @@ std::unordered_map<u64, UnspecializedShader> ShaderCacheOpenGL::GenerateUnspecia } Shader ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) { - if (!Core::System::GetInstance().GPU().Maxwell3D().dirty_flags.shaders) { - return last_shaders[static_cast<u32>(program)]; + if (!system.GPU().Maxwell3D().dirty_flags.shaders) { + return last_shaders[static_cast<std::size_t>(program)]; } - auto& memory_manager{Core::System::GetInstance().GPU().MemoryManager()}; - const GPUVAddr program_addr{GetShaderAddress(program)}; + auto& memory_manager{system.GPU().MemoryManager()}; + const GPUVAddr program_addr{GetShaderAddress(system, program)}; // Look up shader in the cache based on address - const auto& host_ptr{memory_manager.GetPointer(program_addr)}; + const auto host_ptr{memory_manager.GetPointer(program_addr)}; Shader shader{TryGet(host_ptr)}; + if (shader) { + return last_shaders[static_cast<std::size_t>(program)] = shader; + } - if (!shader) { - // No shader found - create a new one - ProgramCode program_code{GetShaderCode(memory_manager, program_addr, host_ptr)}; - ProgramCode program_code_b; - if (program == Maxwell::ShaderProgram::VertexA) { - const GPUVAddr program_addr_b{GetShaderAddress(Maxwell::ShaderProgram::VertexB)}; - program_code_b = GetShaderCode(memory_manager, program_addr_b, - memory_manager.GetPointer(program_addr_b)); - } - const u64 unique_identifier = GetUniqueIdentifier(program, program_code, program_code_b); - const VAddr cpu_addr{*memory_manager.GpuToCpuAddress(program_addr)}; - const auto found = precompiled_shaders.find(unique_identifier); - if (found != precompiled_shaders.end()) { - shader = - std::make_shared<CachedShader>(cpu_addr, unique_identifier, program, disk_cache, - precompiled_programs, found->second, host_ptr); - } else { - shader = std::make_shared<CachedShader>( - device, cpu_addr, unique_identifier, program, disk_cache, precompiled_programs, - std::move(program_code), std::move(program_code_b), host_ptr); - } - Register(shader); + // No shader found - create a new one + ProgramCode program_code{GetShaderCode(memory_manager, program_addr, host_ptr)}; + ProgramCode program_code_b; + if (program == Maxwell::ShaderProgram::VertexA) { + const GPUVAddr program_addr_b{GetShaderAddress(system, Maxwell::ShaderProgram::VertexB)}; + program_code_b = GetShaderCode(memory_manager, program_addr_b, + memory_manager.GetPointer(program_addr_b)); + } + + const u64 unique_identifier = GetUniqueIdentifier(program, program_code, program_code_b); + const VAddr cpu_addr{*memory_manager.GpuToCpuAddress(program_addr)}; + const auto found = precompiled_shaders.find(unique_identifier); + if (found != precompiled_shaders.end()) { + // Create a shader from the cache + shader = std::make_shared<CachedShader>(cpu_addr, unique_identifier, program, disk_cache, + precompiled_programs, found->second, host_ptr); + } else { + // Create a shader from guest memory + shader = std::make_shared<CachedShader>( + device, cpu_addr, unique_identifier, program, disk_cache, precompiled_programs, + std::move(program_code), std::move(program_code_b), host_ptr); } + Register(shader); - return last_shaders[static_cast<u32>(program)] = shader; + return last_shaders[static_cast<std::size_t>(program)] = shader; } } // namespace OpenGL diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h index 64e5a5594..09bd0761d 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.h +++ b/src/video_core/renderer_opengl/gl_shader_cache.h @@ -137,6 +137,7 @@ private: CachedProgram GeneratePrecompiledProgram(const ShaderDiskCacheDump& dump, const std::set<GLenum>& supported_formats); + Core::System& system; Core::Frontend::EmuWindow& emu_window; const Device& device; ShaderDiskCacheOpenGL disk_cache; diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 1ca9825b4..29de5c9db 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -576,9 +576,26 @@ private: if (std::holds_alternative<OperationNode>(*offset)) { // Indirect access const std::string final_offset = code.GenerateTemporary(); - code.AddLine("uint {} = (ftou({}) / 4);", final_offset, Visit(offset)); - return fmt::format("{}[{} / 4][{} % 4]", GetConstBuffer(cbuf->GetIndex()), - final_offset, final_offset); + code.AddLine("uint {} = ftou({}) >> 2;", final_offset, Visit(offset)); + + if (!device.HasComponentIndexingBug()) { + return fmt::format("{}[{} >> 2][{} & 3]", GetConstBuffer(cbuf->GetIndex()), + final_offset, final_offset); + } + + // AMD's proprietary GLSL compiler emits ill code for variable component access. + // To bypass this driver bug generate 4 ifs, one per each component. + const std::string pack = code.GenerateTemporary(); + code.AddLine("vec4 {} = {}[{} >> 2];", pack, GetConstBuffer(cbuf->GetIndex()), + final_offset); + + const std::string result = code.GenerateTemporary(); + code.AddLine("float {};", result); + for (u32 swizzle = 0; swizzle < 4; ++swizzle) { + code.AddLine("if (({} & 3) == {}) {} = {}{};", final_offset, swizzle, result, + pack, GetSwizzle(swizzle)); + } + return result; } UNREACHABLE_MSG("Unmanaged offset node type"); diff --git a/src/yuzu/applets/profile_select.cpp b/src/yuzu/applets/profile_select.cpp index 42e26b978..6b5c7ba61 100644 --- a/src/yuzu/applets/profile_select.cpp +++ b/src/yuzu/applets/profile_select.cpp @@ -122,21 +122,15 @@ QtProfileSelectionDialog::QtProfileSelectionDialog(QWidget* parent) QtProfileSelectionDialog::~QtProfileSelectionDialog() = default; void QtProfileSelectionDialog::accept() { - ok = true; QDialog::accept(); } void QtProfileSelectionDialog::reject() { - ok = false; user_index = 0; QDialog::reject(); } -bool QtProfileSelectionDialog::GetStatus() const { - return ok; -} - -u32 QtProfileSelectionDialog::GetIndex() const { +int QtProfileSelectionDialog::GetIndex() const { return user_index; } diff --git a/src/yuzu/applets/profile_select.h b/src/yuzu/applets/profile_select.h index c5b90a78e..cee886a77 100644 --- a/src/yuzu/applets/profile_select.h +++ b/src/yuzu/applets/profile_select.h @@ -30,15 +30,13 @@ public: void accept() override; void reject() override; - bool GetStatus() const; - u32 GetIndex() const; + int GetIndex() const; private: - bool ok = false; - u32 user_index = 0; - void SelectUser(const QModelIndex& index); + int user_index = 0; + QVBoxLayout* layout; QTreeView* tree_view; QStandardItemModel* item_model; diff --git a/src/yuzu/applets/software_keyboard.cpp b/src/yuzu/applets/software_keyboard.cpp index 5223ec977..af36f07c6 100644 --- a/src/yuzu/applets/software_keyboard.cpp +++ b/src/yuzu/applets/software_keyboard.cpp @@ -104,13 +104,11 @@ QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog( QtSoftwareKeyboardDialog::~QtSoftwareKeyboardDialog() = default; void QtSoftwareKeyboardDialog::accept() { - ok = true; text = line_edit->text().toStdU16String(); QDialog::accept(); } void QtSoftwareKeyboardDialog::reject() { - ok = false; text.clear(); QDialog::reject(); } @@ -119,10 +117,6 @@ std::u16string QtSoftwareKeyboardDialog::GetText() const { return text; } -bool QtSoftwareKeyboardDialog::GetStatus() const { - return ok; -} - QtSoftwareKeyboard::QtSoftwareKeyboard(GMainWindow& main_window) { connect(this, &QtSoftwareKeyboard::MainWindowGetText, &main_window, &GMainWindow::SoftwareKeyboardGetText, Qt::QueuedConnection); diff --git a/src/yuzu/applets/software_keyboard.h b/src/yuzu/applets/software_keyboard.h index 78c5a042b..44bcece75 100644 --- a/src/yuzu/applets/software_keyboard.h +++ b/src/yuzu/applets/software_keyboard.h @@ -36,10 +36,8 @@ public: void reject() override; std::u16string GetText() const; - bool GetStatus() const; private: - bool ok = false; std::u16string text; QDialogButtonBox* buttons; diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 9e420b359..afec33b61 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -26,6 +26,8 @@ EmuThread::EmuThread(GRenderWindow* render_window) : render_window(render_window) {} +EmuThread::~EmuThread() = default; + void EmuThread::run() { render_window->MakeCurrent(); @@ -185,7 +187,7 @@ private: bool do_painting; }; -GRenderWindow::GRenderWindow(QWidget* parent, EmuThread* emu_thread) +GRenderWindow::GRenderWindow(GMainWindow* parent, EmuThread* emu_thread) : QWidget(parent), emu_thread(emu_thread) { setWindowTitle(QStringLiteral("yuzu %1 | %2-%3") .arg(QString::fromUtf8(Common::g_build_name), @@ -194,8 +196,7 @@ GRenderWindow::GRenderWindow(QWidget* parent, EmuThread* emu_thread) setAttribute(Qt::WA_AcceptTouchEvents); InputCommon::Init(); - connect(this, &GRenderWindow::FirstFrameDisplayed, static_cast<GMainWindow*>(parent), - &GMainWindow::OnLoadComplete); + connect(this, &GRenderWindow::FirstFrameDisplayed, parent, &GMainWindow::OnLoadComplete); } GRenderWindow::~GRenderWindow() { @@ -247,9 +248,9 @@ void GRenderWindow::PollEvents() {} void GRenderWindow::OnFramebufferSizeChanged() { // Screen changes potentially incur a change in screen DPI, hence we should update the // framebuffer size - qreal pixelRatio = GetWindowPixelRatio(); - unsigned width = child->QPaintDevice::width() * pixelRatio; - unsigned height = child->QPaintDevice::height() * pixelRatio; + const qreal pixel_ratio = GetWindowPixelRatio(); + const u32 width = child->QPaintDevice::width() * pixel_ratio; + const u32 height = child->QPaintDevice::height() * pixel_ratio; UpdateCurrentFramebufferLayout(width, height); } @@ -266,7 +267,7 @@ void GRenderWindow::ForwardKeyReleaseEvent(QKeyEvent* event) { } void GRenderWindow::BackupGeometry() { - geometry = ((QWidget*)this)->saveGeometry(); + geometry = QWidget::saveGeometry(); } void GRenderWindow::RestoreGeometry() { @@ -283,10 +284,11 @@ void GRenderWindow::restoreGeometry(const QByteArray& geometry) { QByteArray GRenderWindow::saveGeometry() { // If we are a top-level widget, store the current geometry // otherwise, store the last backup - if (parent() == nullptr) - return ((QWidget*)this)->saveGeometry(); - else - return geometry; + if (parent() == nullptr) { + return QWidget::saveGeometry(); + } + + return geometry; } qreal GRenderWindow::GetWindowPixelRatio() const { @@ -294,10 +296,10 @@ qreal GRenderWindow::GetWindowPixelRatio() const { return windowHandle() ? windowHandle()->screen()->devicePixelRatio() : 1.0f; } -std::pair<unsigned, unsigned> GRenderWindow::ScaleTouch(const QPointF pos) const { +std::pair<u32, u32> GRenderWindow::ScaleTouch(const QPointF pos) const { const qreal pixel_ratio = GetWindowPixelRatio(); - return {static_cast<unsigned>(std::max(std::round(pos.x() * pixel_ratio), qreal{0.0})), - static_cast<unsigned>(std::max(std::round(pos.y() * pixel_ratio), qreal{0.0}))}; + return {static_cast<u32>(std::max(std::round(pos.x() * pixel_ratio), qreal{0.0})), + static_cast<u32>(std::max(std::round(pos.y() * pixel_ratio), qreal{0.0}))}; } void GRenderWindow::closeEvent(QCloseEvent* event) { @@ -353,7 +355,7 @@ void GRenderWindow::focusOutEvent(QFocusEvent* event) { InputCommon::GetKeyboard()->ReleaseAllKeys(); } -void GRenderWindow::OnClientAreaResized(unsigned width, unsigned height) { +void GRenderWindow::OnClientAreaResized(u32 width, u32 height) { NotifyClientAreaSizeChanged(std::make_pair(width, height)); } @@ -394,7 +396,7 @@ void GRenderWindow::InitRenderTarget() { context->setShareContext(shared_context.get()); context->setFormat(fmt); context->create(); - fmt.setSwapInterval(false); + fmt.setSwapInterval(0); child = new GGLWidgetInternal(this, shared_context.get()); container = QWidget::createWindowContainer(child, this); @@ -424,23 +426,29 @@ void GRenderWindow::InitRenderTarget() { BackupGeometry(); } -void GRenderWindow::CaptureScreenshot(u16 res_scale, const QString& screenshot_path) { +void GRenderWindow::CaptureScreenshot(u32 res_scale, const QString& screenshot_path) { auto& renderer = Core::System::GetInstance().Renderer(); - if (!res_scale) + if (res_scale == 0) { res_scale = VideoCore::GetResolutionScaleFactor(renderer); + } const Layout::FramebufferLayout layout{Layout::FrameLayoutFromResolutionScale(res_scale)}; screenshot_image = QImage(QSize(layout.width, layout.height), QImage::Format_RGB32); - renderer.RequestScreenshot(screenshot_image.bits(), - [=] { - screenshot_image.mirrored(false, true).save(screenshot_path); - LOG_INFO(Frontend, "The screenshot is saved."); - }, - layout); + renderer.RequestScreenshot( + screenshot_image.bits(), + [=] { + const std::string std_screenshot_path = screenshot_path.toStdString(); + if (screenshot_image.mirrored(false, true).save(screenshot_path)) { + LOG_INFO(Frontend, "Screenshot saved to \"{}\"", std_screenshot_path); + } else { + LOG_ERROR(Frontend, "Failed to save screenshot to \"{}\"", std_screenshot_path); + } + }, + layout); } -void GRenderWindow::OnMinimalClientAreaChangeRequest(std::pair<unsigned, unsigned> minimal_size) { +void GRenderWindow::OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minimal_size) { setMinimumSize(minimal_size.first, minimal_size.second); } diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h index 7f9f8e8e3..2fc64895f 100644 --- a/src/yuzu/bootmanager.h +++ b/src/yuzu/bootmanager.h @@ -27,11 +27,12 @@ namespace VideoCore { enum class LoadCallbackStage; } -class EmuThread : public QThread { +class EmuThread final : public QThread { Q_OBJECT public: explicit EmuThread(GRenderWindow* render_window); + ~EmuThread() override; /** * Start emulation (on new thread) @@ -114,7 +115,7 @@ class GRenderWindow : public QWidget, public Core::Frontend::EmuWindow { Q_OBJECT public: - GRenderWindow(QWidget* parent, EmuThread* emu_thread); + GRenderWindow(GMainWindow* parent, EmuThread* emu_thread); ~GRenderWindow() override; // EmuWindow implementation @@ -133,17 +134,17 @@ public: QByteArray saveGeometry(); // overridden qreal GetWindowPixelRatio() const; - std::pair<unsigned, unsigned> ScaleTouch(const QPointF pos) const; + std::pair<u32, u32> ScaleTouch(QPointF pos) const; void closeEvent(QCloseEvent* event) override; bool event(QEvent* event) override; void focusOutEvent(QFocusEvent* event) override; - void OnClientAreaResized(unsigned width, unsigned height); + void OnClientAreaResized(u32 width, u32 height); void InitRenderTarget(); - void CaptureScreenshot(u16 res_scale, const QString& screenshot_path); + void CaptureScreenshot(u32 res_scale, const QString& screenshot_path); public slots: void moveContext(); // overridden @@ -162,7 +163,7 @@ private: void TouchUpdateEvent(const QTouchEvent* event); void TouchEndEvent(); - void OnMinimalClientAreaChangeRequest(std::pair<unsigned, unsigned> minimal_size) override; + void OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minimal_size) override; QWidget* container = nullptr; GGLWidgetInternal* child = nullptr; diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp index b0f9b814d..110842eb2 100644 --- a/src/yuzu/configuration/configure_audio.cpp +++ b/src/yuzu/configuration/configure_audio.cpp @@ -22,11 +22,11 @@ ConfigureAudio::ConfigureAudio(QWidget* parent) } connect(ui->volume_slider, &QSlider::valueChanged, this, - &ConfigureAudio::setVolumeIndicatorText); + &ConfigureAudio::SetVolumeIndicatorText); - this->setConfiguration(); + SetConfiguration(); connect(ui->output_sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), this, - &ConfigureAudio::updateAudioDevices); + &ConfigureAudio::UpdateAudioDevices); const bool is_powered_on = Core::System::GetInstance().IsPoweredOn(); ui->output_sink_combo_box->setEnabled(!is_powered_on); @@ -35,20 +35,20 @@ ConfigureAudio::ConfigureAudio(QWidget* parent) ConfigureAudio::~ConfigureAudio() = default; -void ConfigureAudio::setConfiguration() { - setOutputSinkFromSinkID(); +void ConfigureAudio::SetConfiguration() { + SetOutputSinkFromSinkID(); // The device list cannot be pre-populated (nor listed) until the output sink is known. - updateAudioDevices(ui->output_sink_combo_box->currentIndex()); + UpdateAudioDevices(ui->output_sink_combo_box->currentIndex()); - setAudioDeviceFromDeviceID(); + SetAudioDeviceFromDeviceID(); ui->toggle_audio_stretching->setChecked(Settings::values.enable_audio_stretching); ui->volume_slider->setValue(Settings::values.volume * ui->volume_slider->maximum()); - setVolumeIndicatorText(ui->volume_slider->sliderPosition()); + SetVolumeIndicatorText(ui->volume_slider->sliderPosition()); } -void ConfigureAudio::setOutputSinkFromSinkID() { +void ConfigureAudio::SetOutputSinkFromSinkID() { int new_sink_index = 0; const QString sink_id = QString::fromStdString(Settings::values.sink_id); @@ -62,7 +62,7 @@ void ConfigureAudio::setOutputSinkFromSinkID() { ui->output_sink_combo_box->setCurrentIndex(new_sink_index); } -void ConfigureAudio::setAudioDeviceFromDeviceID() { +void ConfigureAudio::SetAudioDeviceFromDeviceID() { int new_device_index = -1; const QString device_id = QString::fromStdString(Settings::values.audio_device_id); @@ -76,11 +76,11 @@ void ConfigureAudio::setAudioDeviceFromDeviceID() { ui->audio_device_combo_box->setCurrentIndex(new_device_index); } -void ConfigureAudio::setVolumeIndicatorText(int percentage) { +void ConfigureAudio::SetVolumeIndicatorText(int percentage) { ui->volume_indicator->setText(tr("%1%", "Volume percentage (e.g. 50%)").arg(percentage)); } -void ConfigureAudio::applyConfiguration() { +void ConfigureAudio::ApplyConfiguration() { Settings::values.sink_id = ui->output_sink_combo_box->itemText(ui->output_sink_combo_box->currentIndex()) .toStdString(); @@ -92,7 +92,7 @@ void ConfigureAudio::applyConfiguration() { static_cast<float>(ui->volume_slider->sliderPosition()) / ui->volume_slider->maximum(); } -void ConfigureAudio::updateAudioDevices(int sink_index) { +void ConfigureAudio::UpdateAudioDevices(int sink_index) { ui->audio_device_combo_box->clear(); ui->audio_device_combo_box->addItem(QString::fromUtf8(AudioCore::auto_device_name)); @@ -102,6 +102,6 @@ void ConfigureAudio::updateAudioDevices(int sink_index) { } } -void ConfigureAudio::retranslateUi() { +void ConfigureAudio::RetranslateUI() { ui->retranslateUi(this); } diff --git a/src/yuzu/configuration/configure_audio.h b/src/yuzu/configuration/configure_audio.h index 8771421c0..2bb92d9b5 100644 --- a/src/yuzu/configuration/configure_audio.h +++ b/src/yuzu/configuration/configure_audio.h @@ -18,16 +18,16 @@ public: explicit ConfigureAudio(QWidget* parent = nullptr); ~ConfigureAudio() override; - void applyConfiguration(); - void retranslateUi(); + void ApplyConfiguration(); + void RetranslateUI(); private: - void updateAudioDevices(int sink_index); + void UpdateAudioDevices(int sink_index); - void setConfiguration(); - void setOutputSinkFromSinkID(); - void setAudioDeviceFromDeviceID(); - void setVolumeIndicatorText(int percentage); + void SetConfiguration(); + void SetOutputSinkFromSinkID(); + void SetAudioDeviceFromDeviceID(); + void SetVolumeIndicatorText(int percentage); std::unique_ptr<Ui::ConfigureAudio> ui; }; diff --git a/src/yuzu/configuration/configure_audio.ui b/src/yuzu/configuration/configure_audio.ui index a29a0e265..a098b9acc 100644 --- a/src/yuzu/configuration/configure_audio.ui +++ b/src/yuzu/configuration/configure_audio.ui @@ -20,7 +20,7 @@ <item> <layout class="QHBoxLayout"> <item> - <widget class="QLabel" name="label"> + <widget class="QLabel" name="label_1"> <property name="text"> <string>Output Engine:</string> </property> @@ -44,7 +44,7 @@ <item> <layout class="QHBoxLayout"> <item> - <widget class="QLabel" name="label"> + <widget class="QLabel" name="label_2"> <property name="text"> <string>Audio Device:</string> </property> @@ -61,7 +61,7 @@ <number>0</number> </property> <item> - <widget class="QLabel" name="label"> + <widget class="QLabel" name="label_3"> <property name="text"> <string>Volume:</string> </property> diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp index 550cf9dca..afc2e3b38 100644 --- a/src/yuzu/configuration/configure_debug.cpp +++ b/src/yuzu/configuration/configure_debug.cpp @@ -16,7 +16,8 @@ ConfigureDebug::ConfigureDebug(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureDebug) { ui->setupUi(this); - this->setConfiguration(); + SetConfiguration(); + connect(ui->open_log_button, &QPushButton::pressed, []() { QString path = QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::LogDir)); QDesktopServices::openUrl(QUrl::fromLocalFile(path)); @@ -25,7 +26,7 @@ ConfigureDebug::ConfigureDebug(QWidget* parent) : QWidget(parent), ui(new Ui::Co ConfigureDebug::~ConfigureDebug() = default; -void ConfigureDebug::setConfiguration() { +void ConfigureDebug::SetConfiguration() { ui->toggle_gdbstub->setChecked(Settings::values.use_gdbstub); ui->gdbport_spinbox->setEnabled(Settings::values.use_gdbstub); ui->gdbport_spinbox->setValue(Settings::values.gdbstub_port); @@ -37,7 +38,7 @@ void ConfigureDebug::setConfiguration() { ui->dump_decompressed_nso->setChecked(Settings::values.dump_nso); } -void ConfigureDebug::applyConfiguration() { +void ConfigureDebug::ApplyConfiguration() { Settings::values.use_gdbstub = ui->toggle_gdbstub->isChecked(); Settings::values.gdbstub_port = ui->gdbport_spinbox->value(); UISettings::values.show_console = ui->toggle_console->isChecked(); diff --git a/src/yuzu/configuration/configure_debug.h b/src/yuzu/configuration/configure_debug.h index c6420b18c..06b89026c 100644 --- a/src/yuzu/configuration/configure_debug.h +++ b/src/yuzu/configuration/configure_debug.h @@ -18,10 +18,10 @@ public: explicit ConfigureDebug(QWidget* parent = nullptr); ~ConfigureDebug() override; - void applyConfiguration(); + void ApplyConfiguration(); private: - void setConfiguration(); + void SetConfiguration(); std::unique_ptr<Ui::ConfigureDebug> ui; }; diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui index 758a92335..5ca9ce0e6 100644 --- a/src/yuzu/configuration/configure_debug.ui +++ b/src/yuzu/configuration/configure_debug.ui @@ -45,7 +45,7 @@ </spacer> </item> <item> - <widget class="QLabel" name="label_2"> + <widget class="QLabel" name="label_1"> <property name="text"> <string>Port:</string> </property> @@ -70,11 +70,11 @@ <property name="title"> <string>Logging</string> </property> - <layout class="QVBoxLayout" name="verticalLayout"> + <layout class="QVBoxLayout" name="verticalLayout_4"> <item> - <layout class="QHBoxLayout" name="horizontalLayout"> + <layout class="QHBoxLayout" name="horizontalLayout_2"> <item> - <widget class="QLabel" name="label"> + <widget class="QLabel" name="label_2"> <property name="text"> <string>Global Log Filter</string> </property> @@ -86,7 +86,7 @@ </layout> </item> <item> - <layout class="QHBoxLayout" name="horizontalLayout_2"> + <layout class="QHBoxLayout" name="horizontalLayout_3"> <item> <widget class="QCheckBox" name="toggle_console"> <property name="text"> @@ -111,11 +111,11 @@ <property name="title"> <string>Homebrew</string> </property> - <layout class="QVBoxLayout" name="verticalLayout"> + <layout class="QVBoxLayout" name="verticalLayout_5"> <item> - <layout class="QHBoxLayout" name="horizontalLayout"> + <layout class="QHBoxLayout" name="horizontalLayout_4"> <item> - <widget class="QLabel" name="label"> + <widget class="QLabel" name="label_3"> <property name="text"> <string>Arguments String</string> </property> @@ -134,7 +134,7 @@ <property name="title"> <string>Dump</string> </property> - <layout class="QVBoxLayout" name="verticalLayout_4"> + <layout class="QVBoxLayout" name="verticalLayout_6"> <item> <widget class="QCheckBox" name="dump_decompressed_nso"> <property name="whatsThis"> diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp index 8086f9d6b..a1b1e00bc 100644 --- a/src/yuzu/configuration/configure_dialog.cpp +++ b/src/yuzu/configuration/configure_dialog.cpp @@ -15,11 +15,11 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry) : QDialog(parent), ui(new Ui::ConfigureDialog), registry(registry) { ui->setupUi(this); ui->hotkeysTab->Populate(registry); - this->setConfiguration(); - this->PopulateSelectionList(); - setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + SetConfiguration(); + PopulateSelectionList(); + connect(ui->selectorList, &QListWidget::itemSelectionChanged, this, &ConfigureDialog::UpdateVisibleTabs); @@ -29,19 +29,19 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry) ConfigureDialog::~ConfigureDialog() = default; -void ConfigureDialog::setConfiguration() {} - -void ConfigureDialog::applyConfiguration() { - ui->generalTab->applyConfiguration(); - ui->gameListTab->applyConfiguration(); - ui->systemTab->applyConfiguration(); - ui->profileManagerTab->applyConfiguration(); - ui->inputTab->applyConfiguration(); - ui->hotkeysTab->applyConfiguration(registry); - ui->graphicsTab->applyConfiguration(); - ui->audioTab->applyConfiguration(); - ui->debugTab->applyConfiguration(); - ui->webTab->applyConfiguration(); +void ConfigureDialog::SetConfiguration() {} + +void ConfigureDialog::ApplyConfiguration() { + ui->generalTab->ApplyConfiguration(); + ui->gameListTab->ApplyConfiguration(); + ui->systemTab->ApplyConfiguration(); + ui->profileManagerTab->ApplyConfiguration(); + ui->inputTab->ApplyConfiguration(); + ui->hotkeysTab->ApplyConfiguration(registry); + ui->graphicsTab->ApplyConfiguration(); + ui->audioTab->ApplyConfiguration(); + ui->debugTab->ApplyConfiguration(); + ui->webTab->ApplyConfiguration(); Settings::Apply(); Settings::LogSettings(); } diff --git a/src/yuzu/configuration/configure_dialog.h b/src/yuzu/configuration/configure_dialog.h index 2363ba584..7e7d90f59 100644 --- a/src/yuzu/configuration/configure_dialog.h +++ b/src/yuzu/configuration/configure_dialog.h @@ -20,10 +20,10 @@ public: explicit ConfigureDialog(QWidget* parent, HotkeyRegistry& registry); ~ConfigureDialog() override; - void applyConfiguration(); + void ApplyConfiguration(); private: - void setConfiguration(); + void SetConfiguration(); void UpdateVisibleTabs(); void PopulateSelectionList(); diff --git a/src/yuzu/configuration/configure_gamelist.cpp b/src/yuzu/configuration/configure_gamelist.cpp index 6f0d75605..4b5b0ee48 100644 --- a/src/yuzu/configuration/configure_gamelist.cpp +++ b/src/yuzu/configuration/configure_gamelist.cpp @@ -12,20 +12,20 @@ #include "yuzu/ui_settings.h" namespace { -constexpr std::array<std::pair<u32, const char*>, 5> default_icon_sizes{{ +constexpr std::array default_icon_sizes{ std::make_pair(0, QT_TR_NOOP("None")), std::make_pair(32, QT_TR_NOOP("Small (32x32)")), std::make_pair(64, QT_TR_NOOP("Standard (64x64)")), std::make_pair(128, QT_TR_NOOP("Large (128x128)")), std::make_pair(256, QT_TR_NOOP("Full Size (256x256)")), -}}; +}; -constexpr std::array<const char*, 4> row_text_names{{ +constexpr std::array row_text_names{ QT_TR_NOOP("Filename"), QT_TR_NOOP("Filetype"), QT_TR_NOOP("Title ID"), QT_TR_NOOP("Title Name"), -}}; +}; } // Anonymous namespace ConfigureGameList::ConfigureGameList(QWidget* parent) @@ -35,7 +35,7 @@ ConfigureGameList::ConfigureGameList(QWidget* parent) InitializeIconSizeComboBox(); InitializeRowComboBoxes(); - this->setConfiguration(); + SetConfiguration(); // Force game list reload if any of the relevant settings are changed. connect(ui->show_unknown, &QCheckBox::stateChanged, this, @@ -50,7 +50,7 @@ ConfigureGameList::ConfigureGameList(QWidget* parent) ConfigureGameList::~ConfigureGameList() = default; -void ConfigureGameList::applyConfiguration() { +void ConfigureGameList::ApplyConfiguration() { UISettings::values.show_unknown = ui->show_unknown->isChecked(); UISettings::values.show_add_ons = ui->show_add_ons->isChecked(); UISettings::values.icon_size = ui->icon_size_combobox->currentData().toUInt(); @@ -63,7 +63,7 @@ void ConfigureGameList::RequestGameListUpdate() { UISettings::values.is_game_list_reload_pending.exchange(true); } -void ConfigureGameList::setConfiguration() { +void ConfigureGameList::SetConfiguration() { ui->show_unknown->setChecked(UISettings::values.show_unknown); ui->show_add_ons->setChecked(UISettings::values.show_add_ons); ui->icon_size_combobox->setCurrentIndex( diff --git a/src/yuzu/configuration/configure_gamelist.h b/src/yuzu/configuration/configure_gamelist.h index bf3f1cdfa..e11822919 100644 --- a/src/yuzu/configuration/configure_gamelist.h +++ b/src/yuzu/configuration/configure_gamelist.h @@ -18,12 +18,12 @@ public: explicit ConfigureGameList(QWidget* parent = nullptr); ~ConfigureGameList() override; - void applyConfiguration(); + void ApplyConfiguration(); private: void RequestGameListUpdate(); - void setConfiguration(); + void SetConfiguration(); void changeEvent(QEvent*) override; void RetranslateUI(); diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp index dd25dc6e1..8bdc1787a 100644 --- a/src/yuzu/configuration/configure_general.cpp +++ b/src/yuzu/configuration/configure_general.cpp @@ -18,7 +18,7 @@ ConfigureGeneral::ConfigureGeneral(QWidget* parent) QString::fromUtf8(theme.second)); } - this->setConfiguration(); + SetConfiguration(); connect(ui->toggle_deepscan, &QCheckBox::stateChanged, this, [] { UISettings::values.is_game_list_reload_pending.exchange(true); }); @@ -28,7 +28,7 @@ ConfigureGeneral::ConfigureGeneral(QWidget* parent) ConfigureGeneral::~ConfigureGeneral() = default; -void ConfigureGeneral::setConfiguration() { +void ConfigureGeneral::SetConfiguration() { ui->toggle_deepscan->setChecked(UISettings::values.game_directory_deepscan); ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing); ui->toggle_user_on_boot->setChecked(UISettings::values.select_user_on_boot); @@ -36,7 +36,7 @@ void ConfigureGeneral::setConfiguration() { ui->use_cpu_jit->setChecked(Settings::values.use_cpu_jit); } -void ConfigureGeneral::applyConfiguration() { +void ConfigureGeneral::ApplyConfiguration() { UISettings::values.game_directory_deepscan = ui->toggle_deepscan->isChecked(); UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked(); UISettings::values.select_user_on_boot = ui->toggle_user_on_boot->isChecked(); diff --git a/src/yuzu/configuration/configure_general.h b/src/yuzu/configuration/configure_general.h index df41d995b..fd5fd2a91 100644 --- a/src/yuzu/configuration/configure_general.h +++ b/src/yuzu/configuration/configure_general.h @@ -20,10 +20,10 @@ public: explicit ConfigureGeneral(QWidget* parent = nullptr); ~ConfigureGeneral() override; - void applyConfiguration(); + void ApplyConfiguration(); private: - void setConfiguration(); + void SetConfiguration(); std::unique_ptr<Ui::ConfigureGeneral> ui; }; diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index 08ea41b0f..02e91701a 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp @@ -51,29 +51,29 @@ Resolution FromResolutionFactor(float factor) { ConfigureGraphics::ConfigureGraphics(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureGraphics) { - ui->setupUi(this); - this->setConfiguration(); - ui->frame_limit->setEnabled(Settings::values.use_frame_limit); - connect(ui->toggle_frame_limit, &QCheckBox::stateChanged, ui->frame_limit, - &QSpinBox::setEnabled); + SetConfiguration(); + + connect(ui->toggle_frame_limit, &QCheckBox::toggled, ui->frame_limit, &QSpinBox::setEnabled); connect(ui->bg_button, &QPushButton::clicked, this, [this] { const QColor new_bg_color = QColorDialog::getColor(bg_color); - if (!new_bg_color.isValid()) + if (!new_bg_color.isValid()) { return; + } UpdateBackgroundColorButton(new_bg_color); }); } ConfigureGraphics::~ConfigureGraphics() = default; -void ConfigureGraphics::setConfiguration() { +void ConfigureGraphics::SetConfiguration() { const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn(); ui->resolution_factor_combobox->setCurrentIndex( static_cast<int>(FromResolutionFactor(Settings::values.resolution_factor))); ui->toggle_frame_limit->setChecked(Settings::values.use_frame_limit); + ui->frame_limit->setEnabled(ui->toggle_frame_limit->isChecked()); ui->frame_limit->setValue(Settings::values.frame_limit); ui->use_compatibility_profile->setEnabled(runtime_lock); ui->use_compatibility_profile->setChecked(Settings::values.use_compatibility_profile); @@ -88,7 +88,7 @@ void ConfigureGraphics::setConfiguration() { Settings::values.bg_blue)); } -void ConfigureGraphics::applyConfiguration() { +void ConfigureGraphics::ApplyConfiguration() { Settings::values.resolution_factor = ToResolutionFactor(static_cast<Resolution>(ui->resolution_factor_combobox->currentIndex())); Settings::values.use_frame_limit = ui->toggle_frame_limit->isChecked(); diff --git a/src/yuzu/configuration/configure_graphics.h b/src/yuzu/configuration/configure_graphics.h index f2799822d..6b3c39705 100644 --- a/src/yuzu/configuration/configure_graphics.h +++ b/src/yuzu/configuration/configure_graphics.h @@ -18,10 +18,10 @@ public: explicit ConfigureGraphics(QWidget* parent = nullptr); ~ConfigureGraphics() override; - void applyConfiguration(); + void ApplyConfiguration(); private: - void setConfiguration(); + void SetConfiguration(); void UpdateBackgroundColorButton(QColor color); diff --git a/src/yuzu/configuration/configure_hotkeys.cpp b/src/yuzu/configuration/configure_hotkeys.cpp index 9fb970c21..04119e9d7 100644 --- a/src/yuzu/configuration/configure_hotkeys.cpp +++ b/src/yuzu/configuration/configure_hotkeys.cpp @@ -92,7 +92,7 @@ bool ConfigureHotkeys::IsUsedKey(QKeySequence key_sequence) const { return false; } -void ConfigureHotkeys::applyConfiguration(HotkeyRegistry& registry) { +void ConfigureHotkeys::ApplyConfiguration(HotkeyRegistry& registry) { for (int key_id = 0; key_id < model->rowCount(); key_id++) { const QStandardItem* parent = model->item(key_id, 0); for (int key_column_id = 0; key_column_id < parent->rowCount(); key_column_id++) { @@ -113,6 +113,6 @@ void ConfigureHotkeys::applyConfiguration(HotkeyRegistry& registry) { registry.SaveHotkeys(); } -void ConfigureHotkeys::retranslateUi() { +void ConfigureHotkeys::RetranslateUI() { ui->retranslateUi(this); } diff --git a/src/yuzu/configuration/configure_hotkeys.h b/src/yuzu/configuration/configure_hotkeys.h index e77d73c35..a1f4c7134 100644 --- a/src/yuzu/configuration/configure_hotkeys.h +++ b/src/yuzu/configuration/configure_hotkeys.h @@ -21,8 +21,8 @@ public: explicit ConfigureHotkeys(QWidget* parent = nullptr); ~ConfigureHotkeys() override; - void applyConfiguration(HotkeyRegistry& registry); - void retranslateUi(); + void ApplyConfiguration(HotkeyRegistry& registry); + void RetranslateUI(); /** * Populates the hotkey list widget using data from the provided registry. diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index 87e459714..fb1210bcb 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp @@ -50,12 +50,12 @@ void OnDockedModeChanged(bool last_state, bool new_state) { namespace { template <typename Dialog, typename... Args> void CallConfigureDialog(ConfigureInput& parent, Args&&... args) { - parent.applyConfiguration(); + parent.ApplyConfiguration(); Dialog dialog(&parent, std::forward<Args>(args)...); const auto res = dialog.exec(); if (res == QDialog::Accepted) { - dialog.applyConfiguration(); + dialog.ApplyConfiguration(); } } } // Anonymous namespace @@ -79,24 +79,24 @@ ConfigureInput::ConfigureInput(QWidget* parent) tr("Single Right Joycon"), tr("Single Left Joycon")}); } - this->loadConfiguration(); - updateUIEnabled(); + LoadConfiguration(); + UpdateUIEnabled(); connect(ui->restore_defaults_button, &QPushButton::pressed, this, - &ConfigureInput::restoreDefaults); + &ConfigureInput::RestoreDefaults); for (auto* enabled : players_controller) { connect(enabled, QOverload<int>::of(&QComboBox::currentIndexChanged), this, - &ConfigureInput::updateUIEnabled); + &ConfigureInput::UpdateUIEnabled); } - connect(ui->use_docked_mode, &QCheckBox::stateChanged, this, &ConfigureInput::updateUIEnabled); + connect(ui->use_docked_mode, &QCheckBox::stateChanged, this, &ConfigureInput::UpdateUIEnabled); connect(ui->handheld_connected, &QCheckBox::stateChanged, this, - &ConfigureInput::updateUIEnabled); - connect(ui->mouse_enabled, &QCheckBox::stateChanged, this, &ConfigureInput::updateUIEnabled); - connect(ui->keyboard_enabled, &QCheckBox::stateChanged, this, &ConfigureInput::updateUIEnabled); - connect(ui->debug_enabled, &QCheckBox::stateChanged, this, &ConfigureInput::updateUIEnabled); + &ConfigureInput::UpdateUIEnabled); + connect(ui->mouse_enabled, &QCheckBox::stateChanged, this, &ConfigureInput::UpdateUIEnabled); + connect(ui->keyboard_enabled, &QCheckBox::stateChanged, this, &ConfigureInput::UpdateUIEnabled); + connect(ui->debug_enabled, &QCheckBox::stateChanged, this, &ConfigureInput::UpdateUIEnabled); connect(ui->touchscreen_enabled, &QCheckBox::stateChanged, this, - &ConfigureInput::updateUIEnabled); + &ConfigureInput::UpdateUIEnabled); for (std::size_t i = 0; i < players_configure.size(); ++i) { connect(players_configure[i], &QPushButton::pressed, this, @@ -118,7 +118,7 @@ ConfigureInput::ConfigureInput(QWidget* parent) ConfigureInput::~ConfigureInput() = default; -void ConfigureInput::applyConfiguration() { +void ConfigureInput::ApplyConfiguration() { for (std::size_t i = 0; i < players_controller.size(); ++i) { const auto controller_type_index = players_controller[i]->currentIndex(); @@ -144,7 +144,7 @@ void ConfigureInput::applyConfiguration() { Settings::values.touchscreen.enabled = ui->touchscreen_enabled->isChecked(); } -void ConfigureInput::updateUIEnabled() { +void ConfigureInput::UpdateUIEnabled() { bool hit_disabled = false; for (auto* player : players_controller) { player->setDisabled(hit_disabled); @@ -168,7 +168,7 @@ void ConfigureInput::updateUIEnabled() { ui->touchscreen_advanced->setEnabled(ui->touchscreen_enabled->isChecked()); } -void ConfigureInput::loadConfiguration() { +void ConfigureInput::LoadConfiguration() { std::stable_partition( Settings::values.players.begin(), Settings::values.players.begin() + @@ -191,10 +191,10 @@ void ConfigureInput::loadConfiguration() { ui->keyboard_enabled->setChecked(Settings::values.keyboard_enabled); ui->touchscreen_enabled->setChecked(Settings::values.touchscreen.enabled); - updateUIEnabled(); + UpdateUIEnabled(); } -void ConfigureInput::restoreDefaults() { +void ConfigureInput::RestoreDefaults() { players_controller[0]->setCurrentIndex(2); for (std::size_t i = 1; i < players_controller.size(); ++i) { @@ -207,5 +207,5 @@ void ConfigureInput::restoreDefaults() { ui->keyboard_enabled->setCheckState(Qt::Unchecked); ui->debug_enabled->setCheckState(Qt::Unchecked); ui->touchscreen_enabled->setCheckState(Qt::Checked); - updateUIEnabled(); + UpdateUIEnabled(); } diff --git a/src/yuzu/configuration/configure_input.h b/src/yuzu/configuration/configure_input.h index b8e62cc2b..6a2125215 100644 --- a/src/yuzu/configuration/configure_input.h +++ b/src/yuzu/configuration/configure_input.h @@ -30,15 +30,15 @@ public: ~ConfigureInput() override; /// Save all button configurations to settings file - void applyConfiguration(); + void ApplyConfiguration(); private: - void updateUIEnabled(); + void UpdateUIEnabled(); /// Load configuration settings. - void loadConfiguration(); + void LoadConfiguration(); /// Restore all buttons to their default values. - void restoreDefaults(); + void RestoreDefaults(); std::unique_ptr<Ui::ConfigureInput> ui; diff --git a/src/yuzu/configuration/configure_input.ui b/src/yuzu/configuration/configure_input.ui index 0a2d9f024..8378451c8 100644 --- a/src/yuzu/configuration/configure_input.ui +++ b/src/yuzu/configuration/configure_input.ui @@ -17,7 +17,7 @@ <item> <layout class="QVBoxLayout" name="verticalLayout"> <item> - <widget class="QGroupBox" name="gridGroupBox"> + <widget class="QGroupBox" name="gridGroupBox_1"> <property name="title"> <string>Players</string> </property> @@ -260,7 +260,7 @@ </widget> </item> <item> - <widget class="QGroupBox" name="gridGroupBox"> + <widget class="QGroupBox" name="gridGroupBox_2"> <property name="title"> <string>Handheld</string> </property> @@ -332,7 +332,7 @@ </widget> </item> <item> - <widget class="QGroupBox" name="gridGroupBox"> + <widget class="QGroupBox" name="gridGroupBox_3"> <property name="title"> <string>Other</string> </property> diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 95b0a656a..32d2a6815 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -245,7 +245,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i button->setContextMenuPolicy(Qt::CustomContextMenu); connect(button, &QPushButton::released, [=] { - handleClick( + HandleClick( button_map[button_id], [=](const Common::ParamPackage& params) { buttons_param[button_id] = params; }, InputCommon::Polling::DeviceType::Button); @@ -274,7 +274,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i analog_button->setContextMenuPolicy(Qt::CustomContextMenu); connect(analog_button, &QPushButton::released, [=]() { - handleClick(analog_map_buttons[analog_id][sub_button_id], + HandleClick(analog_map_buttons[analog_id][sub_button_id], [=](const Common::ParamPackage& params) { SetAnalogButton(params, analogs_param[analog_id], analog_sub_buttons[sub_button_id]); @@ -304,7 +304,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i QMessageBox::information(this, tr("Information"), tr("After pressing OK, first move your joystick horizontally, " "and then vertically.")); - handleClick( + HandleClick( analog_map_stick[analog_id], [=](const Common::ParamPackage& params) { analogs_param[analog_id] = params; }, InputCommon::Polling::DeviceType::Analog); @@ -312,17 +312,17 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i } connect(ui->buttonClearAll, &QPushButton::released, [this] { ClearAll(); }); - connect(ui->buttonRestoreDefaults, &QPushButton::released, [this]() { restoreDefaults(); }); + connect(ui->buttonRestoreDefaults, &QPushButton::released, [this] { RestoreDefaults(); }); timeout_timer->setSingleShot(true); - connect(timeout_timer.get(), &QTimer::timeout, [this]() { setPollingResult({}, true); }); + connect(timeout_timer.get(), &QTimer::timeout, [this] { SetPollingResult({}, true); }); - connect(poll_timer.get(), &QTimer::timeout, [this]() { + connect(poll_timer.get(), &QTimer::timeout, [this] { Common::ParamPackage params; for (auto& poller : device_pollers) { params = poller->GetNextInput(); if (params.Has("engine")) { - setPollingResult(params, false); + SetPollingResult(params, false); return; } } @@ -340,8 +340,8 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i [this, i] { OnControllerButtonClick(static_cast<int>(i)); }); } - this->loadConfiguration(); - this->resize(0, 0); + LoadConfiguration(); + resize(0, 0); // TODO(wwylele): enable this when we actually emulate it ui->buttonHome->setEnabled(false); @@ -349,7 +349,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i ConfigureInputPlayer::~ConfigureInputPlayer() = default; -void ConfigureInputPlayer::applyConfiguration() { +void ConfigureInputPlayer::ApplyConfiguration() { auto& buttons = debug ? Settings::values.debug_pad_buttons : Settings::values.players[player_index].buttons; auto& analogs = @@ -382,7 +382,7 @@ void ConfigureInputPlayer::OnControllerButtonClick(int i) { QStringLiteral("QPushButton { background-color: %1 }").arg(controller_colors[i].name())); } -void ConfigureInputPlayer::loadConfiguration() { +void ConfigureInputPlayer::LoadConfiguration() { if (debug) { std::transform(Settings::values.debug_pad_buttons.begin(), Settings::values.debug_pad_buttons.end(), buttons_param.begin(), @@ -399,7 +399,7 @@ void ConfigureInputPlayer::loadConfiguration() { [](const std::string& str) { return Common::ParamPackage(str); }); } - updateButtonLabels(); + UpdateButtonLabels(); if (debug) return; @@ -421,7 +421,7 @@ void ConfigureInputPlayer::loadConfiguration() { } } -void ConfigureInputPlayer::restoreDefaults() { +void ConfigureInputPlayer::RestoreDefaults() { for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; button_id++) { buttons_param[button_id] = Common::ParamPackage{ InputCommon::GenerateKeyboardParam(Config::default_buttons[button_id])}; @@ -434,7 +434,7 @@ void ConfigureInputPlayer::restoreDefaults() { SetAnalogButton(params, analogs_param[analog_id], analog_sub_buttons[sub_button_id]); } } - updateButtonLabels(); + UpdateButtonLabels(); } void ConfigureInputPlayer::ClearAll() { @@ -458,10 +458,10 @@ void ConfigureInputPlayer::ClearAll() { } } - updateButtonLabels(); + UpdateButtonLabels(); } -void ConfigureInputPlayer::updateButtonLabels() { +void ConfigureInputPlayer::UpdateButtonLabels() { for (int button = 0; button < Settings::NativeButton::NumButtons; button++) { button_map[button]->setText(ButtonToText(buttons_param[button])); } @@ -481,7 +481,7 @@ void ConfigureInputPlayer::updateButtonLabels() { } } -void ConfigureInputPlayer::handleClick( +void ConfigureInputPlayer::HandleClick( QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter, InputCommon::Polling::DeviceType type) { button->setText(tr("[press key]")); @@ -509,7 +509,7 @@ void ConfigureInputPlayer::handleClick( poll_timer->start(200); // Check for new inputs every 200ms } -void ConfigureInputPlayer::setPollingResult(const Common::ParamPackage& params, bool abort) { +void ConfigureInputPlayer::SetPollingResult(const Common::ParamPackage& params, bool abort) { releaseKeyboard(); releaseMouse(); timeout_timer->stop(); @@ -522,22 +522,23 @@ void ConfigureInputPlayer::setPollingResult(const Common::ParamPackage& params, (*input_setter)(params); } - updateButtonLabels(); + UpdateButtonLabels(); input_setter = std::nullopt; } void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) { - if (!input_setter || !event) + if (!input_setter || !event) { return; + } if (event->key() != Qt::Key_Escape) { if (want_keyboard_keys) { - setPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())}, + SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())}, false); } else { // Escape key wasn't pressed and we don't want any keyboard keys, so don't stop polling return; } } - setPollingResult({}, true); + SetPollingResult({}, true); } diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h index ade8d4435..27924fcce 100644 --- a/src/yuzu/configuration/configure_input_player.h +++ b/src/yuzu/configuration/configure_input_player.h @@ -38,28 +38,28 @@ public: ~ConfigureInputPlayer() override; /// Save all button configurations to settings file - void applyConfiguration(); + void ApplyConfiguration(); private: void OnControllerButtonClick(int i); /// Load configuration settings. - void loadConfiguration(); + void LoadConfiguration(); /// Restore all buttons to their default values. - void restoreDefaults(); + void RestoreDefaults(); /// Clear all input configuration void ClearAll(); /// Update UI to reflect current configuration. - void updateButtonLabels(); + void UpdateButtonLabels(); /// Called when the button was pressed. - void handleClick(QPushButton* button, + void HandleClick(QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter, InputCommon::Polling::DeviceType type); /// Finish polling and configure input using the input_setter - void setPollingResult(const Common::ParamPackage& params, bool abort); + void SetPollingResult(const Common::ParamPackage& params, bool abort); /// Handle key press events. void keyPressEvent(QKeyEvent* event) override; diff --git a/src/yuzu/configuration/configure_input_simple.cpp b/src/yuzu/configuration/configure_input_simple.cpp index 07d71e9d1..6140a5573 100644 --- a/src/yuzu/configuration/configure_input_simple.cpp +++ b/src/yuzu/configuration/configure_input_simple.cpp @@ -15,12 +15,12 @@ namespace { template <typename Dialog, typename... Args> void CallConfigureDialog(ConfigureInputSimple* caller, Args&&... args) { - caller->applyConfiguration(); + caller->ApplyConfiguration(); Dialog dialog(caller, std::forward<Args>(args)...); const auto res = dialog.exec(); if (res == QDialog::Accepted) { - dialog.applyConfiguration(); + dialog.ApplyConfiguration(); } } @@ -103,27 +103,29 @@ ConfigureInputSimple::ConfigureInputSimple(QWidget* parent) &ConfigureInputSimple::OnSelectProfile); connect(ui->profile_configure, &QPushButton::pressed, this, &ConfigureInputSimple::OnConfigure); - this->loadConfiguration(); + LoadConfiguration(); } ConfigureInputSimple::~ConfigureInputSimple() = default; -void ConfigureInputSimple::applyConfiguration() { +void ConfigureInputSimple::ApplyConfiguration() { auto index = ui->profile_combobox->currentIndex(); // Make the stored index for "Custom" very large so that if new profiles are added it // doesn't change. - if (index >= static_cast<int>(INPUT_PROFILES.size() - 1)) + if (index >= static_cast<int>(INPUT_PROFILES.size() - 1)) { index = std::numeric_limits<int>::max(); + } UISettings::values.profile_index = index; } -void ConfigureInputSimple::loadConfiguration() { +void ConfigureInputSimple::LoadConfiguration() { const auto index = UISettings::values.profile_index; - if (index >= static_cast<int>(INPUT_PROFILES.size()) || index < 0) + if (index >= static_cast<int>(INPUT_PROFILES.size()) || index < 0) { ui->profile_combobox->setCurrentIndex(static_cast<int>(INPUT_PROFILES.size() - 1)); - else + } else { ui->profile_combobox->setCurrentIndex(index); + } } void ConfigureInputSimple::OnSelectProfile(int index) { diff --git a/src/yuzu/configuration/configure_input_simple.h b/src/yuzu/configuration/configure_input_simple.h index 5b6b69994..573c2db2b 100644 --- a/src/yuzu/configuration/configure_input_simple.h +++ b/src/yuzu/configuration/configure_input_simple.h @@ -27,11 +27,11 @@ public: ~ConfigureInputSimple() override; /// Save all button configurations to settings file - void applyConfiguration(); + void ApplyConfiguration(); private: /// Load configuration settings. - void loadConfiguration(); + void LoadConfiguration(); void OnSelectProfile(int index); void OnConfigure(); diff --git a/src/yuzu/configuration/configure_mouse_advanced.cpp b/src/yuzu/configuration/configure_mouse_advanced.cpp index a14bb1475..26f53128f 100644 --- a/src/yuzu/configuration/configure_mouse_advanced.cpp +++ b/src/yuzu/configuration/configure_mouse_advanced.cpp @@ -84,7 +84,7 @@ ConfigureMouseAdvanced::ConfigureMouseAdvanced(QWidget* parent) button->setContextMenuPolicy(Qt::CustomContextMenu); connect(button, &QPushButton::released, [=] { - handleClick( + HandleClick( button_map[button_id], [=](const Common::ParamPackage& params) { buttons_param[button_id] = params; }, InputCommon::Polling::DeviceType::Button); @@ -105,48 +105,48 @@ ConfigureMouseAdvanced::ConfigureMouseAdvanced(QWidget* parent) } connect(ui->buttonClearAll, &QPushButton::released, [this] { ClearAll(); }); - connect(ui->buttonRestoreDefaults, &QPushButton::released, [this]() { restoreDefaults(); }); + connect(ui->buttonRestoreDefaults, &QPushButton::released, [this] { RestoreDefaults(); }); timeout_timer->setSingleShot(true); - connect(timeout_timer.get(), &QTimer::timeout, [this]() { setPollingResult({}, true); }); + connect(timeout_timer.get(), &QTimer::timeout, [this] { SetPollingResult({}, true); }); - connect(poll_timer.get(), &QTimer::timeout, [this]() { + connect(poll_timer.get(), &QTimer::timeout, [this] { Common::ParamPackage params; for (auto& poller : device_pollers) { params = poller->GetNextInput(); if (params.Has("engine")) { - setPollingResult(params, false); + SetPollingResult(params, false); return; } } }); - loadConfiguration(); + LoadConfiguration(); resize(0, 0); } ConfigureMouseAdvanced::~ConfigureMouseAdvanced() = default; -void ConfigureMouseAdvanced::applyConfiguration() { +void ConfigureMouseAdvanced::ApplyConfiguration() { std::transform(buttons_param.begin(), buttons_param.end(), Settings::values.mouse_buttons.begin(), [](const Common::ParamPackage& param) { return param.Serialize(); }); } -void ConfigureMouseAdvanced::loadConfiguration() { +void ConfigureMouseAdvanced::LoadConfiguration() { std::transform(Settings::values.mouse_buttons.begin(), Settings::values.mouse_buttons.end(), buttons_param.begin(), [](const std::string& str) { return Common::ParamPackage(str); }); - updateButtonLabels(); + UpdateButtonLabels(); } -void ConfigureMouseAdvanced::restoreDefaults() { +void ConfigureMouseAdvanced::RestoreDefaults() { for (int button_id = 0; button_id < Settings::NativeMouseButton::NumMouseButtons; button_id++) { buttons_param[button_id] = Common::ParamPackage{ InputCommon::GenerateKeyboardParam(Config::default_mouse_buttons[button_id])}; } - updateButtonLabels(); + UpdateButtonLabels(); } void ConfigureMouseAdvanced::ClearAll() { @@ -157,16 +157,16 @@ void ConfigureMouseAdvanced::ClearAll() { } } - updateButtonLabels(); + UpdateButtonLabels(); } -void ConfigureMouseAdvanced::updateButtonLabels() { +void ConfigureMouseAdvanced::UpdateButtonLabels() { for (int button = 0; button < Settings::NativeMouseButton::NumMouseButtons; button++) { button_map[button]->setText(ButtonToText(buttons_param[button])); } } -void ConfigureMouseAdvanced::handleClick( +void ConfigureMouseAdvanced::HandleClick( QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter, InputCommon::Polling::DeviceType type) { button->setText(tr("[press key]")); @@ -194,7 +194,7 @@ void ConfigureMouseAdvanced::handleClick( poll_timer->start(200); // Check for new inputs every 200ms } -void ConfigureMouseAdvanced::setPollingResult(const Common::ParamPackage& params, bool abort) { +void ConfigureMouseAdvanced::SetPollingResult(const Common::ParamPackage& params, bool abort) { releaseKeyboard(); releaseMouse(); timeout_timer->stop(); @@ -207,22 +207,23 @@ void ConfigureMouseAdvanced::setPollingResult(const Common::ParamPackage& params (*input_setter)(params); } - updateButtonLabels(); + UpdateButtonLabels(); input_setter = std::nullopt; } void ConfigureMouseAdvanced::keyPressEvent(QKeyEvent* event) { - if (!input_setter || !event) + if (!input_setter || !event) { return; + } if (event->key() != Qt::Key_Escape) { if (want_keyboard_keys) { - setPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())}, + SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())}, false); } else { // Escape key wasn't pressed and we don't want any keyboard keys, so don't stop polling return; } } - setPollingResult({}, true); + SetPollingResult({}, true); } diff --git a/src/yuzu/configuration/configure_mouse_advanced.h b/src/yuzu/configuration/configure_mouse_advanced.h index e04da4bf2..373f992c9 100644 --- a/src/yuzu/configuration/configure_mouse_advanced.h +++ b/src/yuzu/configuration/configure_mouse_advanced.h @@ -25,26 +25,26 @@ public: explicit ConfigureMouseAdvanced(QWidget* parent); ~ConfigureMouseAdvanced() override; - void applyConfiguration(); + void ApplyConfiguration(); private: /// Load configuration settings. - void loadConfiguration(); + void LoadConfiguration(); /// Restore all buttons to their default values. - void restoreDefaults(); + void RestoreDefaults(); /// Clear all input configuration void ClearAll(); /// Update UI to reflect current configuration. - void updateButtonLabels(); + void UpdateButtonLabels(); /// Called when the button was pressed. - void handleClick(QPushButton* button, + void HandleClick(QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter, InputCommon::Polling::DeviceType type); /// Finish polling and configure input using the input_setter - void setPollingResult(const Common::ParamPackage& params, bool abort); + void SetPollingResult(const Common::ParamPackage& params, bool abort); /// Handle key press events. void keyPressEvent(QKeyEvent* event) override; diff --git a/src/yuzu/configuration/configure_per_general.cpp b/src/yuzu/configuration/configure_per_general.cpp index c3e68fdf5..275519c7b 100644 --- a/src/yuzu/configuration/configure_per_general.cpp +++ b/src/yuzu/configuration/configure_per_general.cpp @@ -67,12 +67,12 @@ ConfigurePerGameGeneral::ConfigurePerGameGeneral(QWidget* parent, u64 title_id) connect(item_model, &QStandardItemModel::itemChanged, [] { UISettings::values.is_game_list_reload_pending.exchange(true); }); - this->loadConfiguration(); + LoadConfiguration(); } ConfigurePerGameGeneral::~ConfigurePerGameGeneral() = default; -void ConfigurePerGameGeneral::applyConfiguration() { +void ConfigurePerGameGeneral::ApplyConfiguration() { std::vector<std::string> disabled_addons; for (const auto& item : list_items) { @@ -92,12 +92,12 @@ void ConfigurePerGameGeneral::applyConfiguration() { Settings::values.disabled_addons[title_id] = disabled_addons; } -void ConfigurePerGameGeneral::loadFromFile(FileSys::VirtualFile file) { +void ConfigurePerGameGeneral::LoadFromFile(FileSys::VirtualFile file) { this->file = std::move(file); - this->loadConfiguration(); + LoadConfiguration(); } -void ConfigurePerGameGeneral::loadConfiguration() { +void ConfigurePerGameGeneral::LoadConfiguration() { if (file == nullptr) { return; } diff --git a/src/yuzu/configuration/configure_per_general.h b/src/yuzu/configuration/configure_per_general.h index f8a7d5326..b95e07079 100644 --- a/src/yuzu/configuration/configure_per_general.h +++ b/src/yuzu/configuration/configure_per_general.h @@ -30,11 +30,13 @@ public: ~ConfigurePerGameGeneral() override; /// Save all button configurations to settings file - void applyConfiguration(); + void ApplyConfiguration(); - void loadFromFile(FileSys::VirtualFile file); + void LoadFromFile(FileSys::VirtualFile file); private: + void LoadConfiguration(); + std::unique_ptr<Ui::ConfigurePerGameGeneral> ui; FileSys::VirtualFile file; u64 title_id; @@ -45,6 +47,4 @@ private: QGraphicsScene* scene; std::vector<QList<QStandardItem*>> list_items; - - void loadConfiguration(); }; diff --git a/src/yuzu/configuration/configure_profile_manager.cpp b/src/yuzu/configuration/configure_profile_manager.cpp index 6d7d04c98..7c1597488 100644 --- a/src/yuzu/configuration/configure_profile_manager.cpp +++ b/src/yuzu/configuration/configure_profile_manager.cpp @@ -119,12 +119,12 @@ ConfigureProfileManager ::ConfigureProfileManager(QWidget* parent) scene = new QGraphicsScene; ui->current_user_icon->setScene(scene); - this->setConfiguration(); + SetConfiguration(); } ConfigureProfileManager::~ConfigureProfileManager() = default; -void ConfigureProfileManager::setConfiguration() { +void ConfigureProfileManager::SetConfiguration() { enabled = !Core::System::GetInstance().IsPoweredOn(); item_model->removeRows(0, item_model->rowCount()); list_items.clear(); @@ -164,9 +164,10 @@ void ConfigureProfileManager::UpdateCurrentUser() { ui->current_user_username->setText(username); } -void ConfigureProfileManager::applyConfiguration() { - if (!enabled) +void ConfigureProfileManager::ApplyConfiguration() { + if (!enabled) { return; + } Settings::Apply(); } diff --git a/src/yuzu/configuration/configure_profile_manager.h b/src/yuzu/configuration/configure_profile_manager.h index 7fe95a2a8..4e9b4e8ea 100644 --- a/src/yuzu/configuration/configure_profile_manager.h +++ b/src/yuzu/configuration/configure_profile_manager.h @@ -30,10 +30,11 @@ public: explicit ConfigureProfileManager(QWidget* parent = nullptr); ~ConfigureProfileManager() override; - void applyConfiguration(); - void setConfiguration(); + void ApplyConfiguration(); private: + void SetConfiguration(); + void PopulateUserList(); void UpdateCurrentUser(); diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp index ff18ace40..5f0ed2f61 100644 --- a/src/yuzu/configuration/configure_system.cpp +++ b/src/yuzu/configuration/configure_system.cpp @@ -16,49 +16,31 @@ #include "ui_configure_system.h" #include "yuzu/configuration/configure_system.h" -namespace { -constexpr std::array<int, 12> days_in_month = {{ - 31, - 29, - 31, - 30, - 31, - 30, - 31, - 31, - 30, - 31, - 30, - 31, -}}; -} // Anonymous namespace - ConfigureSystem::ConfigureSystem(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureSystem) { ui->setupUi(this); - connect(ui->combo_birthmonth, - static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, - &ConfigureSystem::UpdateBirthdayComboBox); connect(ui->button_regenerate_console_id, &QPushButton::clicked, this, &ConfigureSystem::RefreshConsoleID); connect(ui->rng_seed_checkbox, &QCheckBox::stateChanged, this, [this](bool checked) { ui->rng_seed_edit->setEnabled(checked); - if (!checked) + if (!checked) { ui->rng_seed_edit->setText(QStringLiteral("00000000")); + } }); connect(ui->custom_rtc_checkbox, &QCheckBox::stateChanged, this, [this](bool checked) { ui->custom_rtc_edit->setEnabled(checked); - if (!checked) + if (!checked) { ui->custom_rtc_edit->setDateTime(QDateTime::currentDateTime()); + } }); - this->setConfiguration(); + SetConfiguration(); } ConfigureSystem::~ConfigureSystem() = default; -void ConfigureSystem::setConfiguration() { +void ConfigureSystem::SetConfiguration() { enabled = !Core::System::GetInstance().IsPoweredOn(); ui->combo_language->setCurrentIndex(Settings::values.language_index); @@ -81,49 +63,27 @@ void ConfigureSystem::setConfiguration() { void ConfigureSystem::ReadSystemSettings() {} -void ConfigureSystem::applyConfiguration() { - if (!enabled) +void ConfigureSystem::ApplyConfiguration() { + if (!enabled) { return; + } Settings::values.language_index = ui->combo_language->currentIndex(); - if (ui->rng_seed_checkbox->isChecked()) + if (ui->rng_seed_checkbox->isChecked()) { Settings::values.rng_seed = ui->rng_seed_edit->text().toULongLong(nullptr, 16); - else + } else { Settings::values.rng_seed = std::nullopt; + } - if (ui->custom_rtc_checkbox->isChecked()) + if (ui->custom_rtc_checkbox->isChecked()) { Settings::values.custom_rtc = std::chrono::seconds(ui->custom_rtc_edit->dateTime().toSecsSinceEpoch()); - else + } else { Settings::values.custom_rtc = std::nullopt; - - Settings::Apply(); -} - -void ConfigureSystem::UpdateBirthdayComboBox(int birthmonth_index) { - if (birthmonth_index < 0 || birthmonth_index >= 12) - return; - - // store current day selection - int birthday_index = ui->combo_birthday->currentIndex(); - - // get number of days in the new selected month - int days = days_in_month[birthmonth_index]; - - // if the selected day is out of range, - // reset it to 1st - if (birthday_index < 0 || birthday_index >= days) - birthday_index = 0; - - // update the day combo box - ui->combo_birthday->clear(); - for (int i = 1; i <= days; ++i) { - ui->combo_birthday->addItem(QString::number(i)); } - // restore the day selection - ui->combo_birthday->setCurrentIndex(birthday_index); + Settings::Apply(); } void ConfigureSystem::RefreshConsoleID() { @@ -134,8 +94,10 @@ void ConfigureSystem::RefreshConsoleID() { "if you use an outdated config savegame. Continue?"); reply = QMessageBox::critical(this, tr("Warning"), warning_text, QMessageBox::No | QMessageBox::Yes); - if (reply == QMessageBox::No) + if (reply == QMessageBox::No) { return; + } + u64 console_id{}; ui->label_console_id->setText( tr("Console ID: 0x%1").arg(QString::number(console_id, 16).toUpper())); diff --git a/src/yuzu/configuration/configure_system.h b/src/yuzu/configuration/configure_system.h index cf1e54de5..4c0329d57 100644 --- a/src/yuzu/configuration/configure_system.h +++ b/src/yuzu/configuration/configure_system.h @@ -20,20 +20,18 @@ public: explicit ConfigureSystem(QWidget* parent = nullptr); ~ConfigureSystem() override; - void applyConfiguration(); - void setConfiguration(); + void ApplyConfiguration(); private: + void SetConfiguration(); + void ReadSystemSettings(); - void UpdateBirthdayComboBox(int birthmonth_index); void RefreshConsoleID(); std::unique_ptr<Ui::ConfigureSystem> ui; bool enabled = false; - int birthmonth = 0; - int birthday = 0; int language_index = 0; int sound_index = 0; }; diff --git a/src/yuzu/configuration/configure_system.ui b/src/yuzu/configuration/configure_system.ui index 073327298..65745a2f8 100644 --- a/src/yuzu/configuration/configure_system.ui +++ b/src/yuzu/configuration/configure_system.ui @@ -22,14 +22,21 @@ <string>System Settings</string> </property> <layout class="QGridLayout" name="gridLayout"> - <item row="2" column="0"> + <item row="1" column="0"> <widget class="QLabel" name="label_sound"> <property name="text"> <string>Sound output mode</string> </property> </widget> </item> - <item row="1" column="1"> + <item row="2" column="0"> + <widget class="QLabel" name="label_console_id"> + <property name="text"> + <string>Console ID:</string> + </property> + </widget> + </item> + <item row="0" column="1"> <widget class="QComboBox" name="combo_language"> <property name="toolTip"> <string>Note: this can be overridden when region setting is auto-select</string> @@ -121,108 +128,14 @@ </item> </widget> </item> - <item row="0" column="1"> - <layout class="QHBoxLayout" name="horizontalLayout_birthday2"> - <item> - <widget class="QComboBox" name="combo_birthmonth"> - <item> - <property name="text"> - <string>January</string> - </property> - </item> - <item> - <property name="text"> - <string>February</string> - </property> - </item> - <item> - <property name="text"> - <string>March</string> - </property> - </item> - <item> - <property name="text"> - <string>April</string> - </property> - </item> - <item> - <property name="text"> - <string>May</string> - </property> - </item> - <item> - <property name="text"> - <string>June</string> - </property> - </item> - <item> - <property name="text"> - <string>July</string> - </property> - </item> - <item> - <property name="text"> - <string>August</string> - </property> - </item> - <item> - <property name="text"> - <string>September</string> - </property> - </item> - <item> - <property name="text"> - <string>October</string> - </property> - </item> - <item> - <property name="text"> - <string>November</string> - </property> - </item> - <item> - <property name="text"> - <string>December</string> - </property> - </item> - </widget> - </item> - <item> - <widget class="QComboBox" name="combo_birthday"/> - </item> - </layout> - </item> - <item row="3" column="0"> - <widget class="QLabel" name="label_console_id"> - <property name="text"> - <string>Console ID:</string> - </property> - </widget> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="label_birthday"> - <property name="text"> - <string>Birthday</string> - </property> - </widget> - </item> - <item row="3" column="1"> - <widget class="QPushButton" name="button_regenerate_console_id"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="layoutDirection"> - <enum>Qt::RightToLeft</enum> - </property> + <item row="4" column="0"> + <widget class="QCheckBox" name="rng_seed_checkbox"> <property name="text"> - <string>Regenerate</string> + <string>RNG Seed</string> </property> </widget> </item> - <item row="2" column="1"> + <item row="1" column="1"> <widget class="QComboBox" name="combo_sound"> <item> <property name="text"> @@ -241,49 +154,37 @@ </item> </widget> </item> - <item row="5" column="0"> - <widget class="QCheckBox" name="rng_seed_checkbox"> - <property name="text"> - <string>RNG Seed</string> - </property> - </widget> - </item> - <item row="1" column="0"> + <item row="0" column="0"> <widget class="QLabel" name="label_language"> <property name="text"> <string>Language</string> </property> </widget> </item> - <item row="5" column="1"> - <widget class="QLineEdit" name="rng_seed_edit"> + <item row="2" column="1"> + <widget class="QPushButton" name="button_regenerate_console_id"> <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="font"> - <font> - <family>Lucida Console</family> - </font> - </property> - <property name="inputMask"> - <string notr="true">HHHHHHHH</string> + <property name="layoutDirection"> + <enum>Qt::RightToLeft</enum> </property> - <property name="maxLength"> - <number>8</number> + <property name="text"> + <string>Regenerate</string> </property> </widget> </item> - <item row="4" column="0"> + <item row="3" column="0"> <widget class="QCheckBox" name="custom_rtc_checkbox"> <property name="text"> <string>Custom RTC</string> </property> </widget> </item> - <item row="4" column="1"> + <item row="3" column="1"> <widget class="QDateTimeEdit" name="custom_rtc_edit"> <property name="minimumDate"> <date> @@ -297,6 +198,27 @@ </property> </widget> </item> + <item row="4" column="1"> + <widget class="QLineEdit" name="rng_seed_edit"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="font"> + <font> + <family>Lucida Console</family> + </font> + </property> + <property name="inputMask"> + <string notr="true">HHHHHHHH</string> + </property> + <property name="maxLength"> + <number>8</number> + </property> + </widget> + </item> </layout> </widget> </item> diff --git a/src/yuzu/configuration/configure_touchscreen_advanced.cpp b/src/yuzu/configuration/configure_touchscreen_advanced.cpp index 9c1561e9d..bad224239 100644 --- a/src/yuzu/configuration/configure_touchscreen_advanced.cpp +++ b/src/yuzu/configuration/configure_touchscreen_advanced.cpp @@ -12,29 +12,29 @@ ConfigureTouchscreenAdvanced::ConfigureTouchscreenAdvanced(QWidget* parent) ui->setupUi(this); connect(ui->restore_defaults_button, &QPushButton::pressed, this, - &ConfigureTouchscreenAdvanced::restoreDefaults); + &ConfigureTouchscreenAdvanced::RestoreDefaults); - loadConfiguration(); + LoadConfiguration(); resize(0, 0); } ConfigureTouchscreenAdvanced::~ConfigureTouchscreenAdvanced() = default; -void ConfigureTouchscreenAdvanced::applyConfiguration() { +void ConfigureTouchscreenAdvanced::ApplyConfiguration() { Settings::values.touchscreen.finger = ui->finger_box->value(); Settings::values.touchscreen.diameter_x = ui->diameter_x_box->value(); Settings::values.touchscreen.diameter_y = ui->diameter_y_box->value(); Settings::values.touchscreen.rotation_angle = ui->angle_box->value(); } -void ConfigureTouchscreenAdvanced::loadConfiguration() { +void ConfigureTouchscreenAdvanced::LoadConfiguration() { ui->finger_box->setValue(Settings::values.touchscreen.finger); ui->diameter_x_box->setValue(Settings::values.touchscreen.diameter_x); ui->diameter_y_box->setValue(Settings::values.touchscreen.diameter_y); ui->angle_box->setValue(Settings::values.touchscreen.rotation_angle); } -void ConfigureTouchscreenAdvanced::restoreDefaults() { +void ConfigureTouchscreenAdvanced::RestoreDefaults() { ui->finger_box->setValue(0); ui->diameter_x_box->setValue(15); ui->diameter_y_box->setValue(15); diff --git a/src/yuzu/configuration/configure_touchscreen_advanced.h b/src/yuzu/configuration/configure_touchscreen_advanced.h index 3d0772c87..94edd85b1 100644 --- a/src/yuzu/configuration/configure_touchscreen_advanced.h +++ b/src/yuzu/configuration/configure_touchscreen_advanced.h @@ -18,13 +18,13 @@ public: explicit ConfigureTouchscreenAdvanced(QWidget* parent); ~ConfigureTouchscreenAdvanced() override; - void applyConfiguration(); + void ApplyConfiguration(); private: /// Load configuration settings. - void loadConfiguration(); + void LoadConfiguration(); /// Restore all buttons to their default values. - void restoreDefaults(); + void RestoreDefaults(); std::unique_ptr<Ui::ConfigureTouchscreenAdvanced> ui; }; diff --git a/src/yuzu/configuration/configure_web.cpp b/src/yuzu/configuration/configure_web.cpp index 9dc34412d..8cacb75f3 100644 --- a/src/yuzu/configuration/configure_web.cpp +++ b/src/yuzu/configuration/configure_web.cpp @@ -22,12 +22,12 @@ ConfigureWeb::ConfigureWeb(QWidget* parent) #ifndef USE_DISCORD_PRESENCE ui->discord_group->setVisible(false); #endif - this->setConfiguration(); + SetConfiguration(); } ConfigureWeb::~ConfigureWeb() = default; -void ConfigureWeb::setConfiguration() { +void ConfigureWeb::SetConfiguration() { ui->web_credentials_disclaimer->setWordWrap(true); ui->telemetry_learn_more->setOpenExternalLinks(true); ui->telemetry_learn_more->setText( @@ -56,7 +56,7 @@ void ConfigureWeb::setConfiguration() { ui->toggle_discordrpc->setChecked(UISettings::values.enable_discord_presence); } -void ConfigureWeb::applyConfiguration() { +void ConfigureWeb::ApplyConfiguration() { Settings::values.enable_telemetry = ui->toggle_telemetry->isChecked(); UISettings::values.enable_discord_presence = ui->toggle_discordrpc->isChecked(); if (user_verified) { @@ -121,6 +121,6 @@ void ConfigureWeb::OnLoginVerified() { } } -void ConfigureWeb::retranslateUi() { +void ConfigureWeb::RetranslateUI() { ui->retranslateUi(this); } diff --git a/src/yuzu/configuration/configure_web.h b/src/yuzu/configuration/configure_web.h index 7752ae4a1..49bee171b 100644 --- a/src/yuzu/configuration/configure_web.h +++ b/src/yuzu/configuration/configure_web.h @@ -19,8 +19,8 @@ public: explicit ConfigureWeb(QWidget* parent = nullptr); ~ConfigureWeb() override; - void applyConfiguration(); - void retranslateUi(); + void ApplyConfiguration(); + void RetranslateUI(); private: void RefreshTelemetryID(); @@ -28,7 +28,7 @@ private: void VerifyLogin(); void OnLoginVerified(); - void setConfiguration(); + void SetConfiguration(); bool user_verified = true; QFutureWatcher<bool> verify_watcher; diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp index 4d951a4e7..4f30e9147 100644 --- a/src/yuzu/game_list_worker.cpp +++ b/src/yuzu/game_list_worker.cpp @@ -8,6 +8,7 @@ #include <vector> #include <QDir> +#include <QFile> #include <QFileInfo> #include <QSettings> @@ -32,11 +33,6 @@ namespace { -template <typename T> -T GetGameListCachedObject(const std::string& filename, const std::string& ext, - const std::function<T()>& generator); - -template <> QString GetGameListCachedObject(const std::string& filename, const std::string& ext, const std::function<QString()>& generator) { if (!UISettings::values.cache_game_list || filename == "0000000000000000") { @@ -51,26 +47,22 @@ QString GetGameListCachedObject(const std::string& filename, const std::string& if (!FileUtil::Exists(path)) { const auto str = generator(); - std::ofstream stream(path); - if (stream) { - stream << str.toStdString(); + QFile file{QString::fromStdString(path)}; + if (file.open(QFile::WriteOnly)) { + file.write(str.toUtf8()); } return str; } - std::ifstream stream(path); - - if (stream) { - const std::string out(std::istreambuf_iterator<char>{stream}, - std::istreambuf_iterator<char>{}); - return QString::fromStdString(out); + QFile file{QString::fromStdString(path)}; + if (file.open(QFile::ReadOnly)) { + return QString::fromUtf8(file.readAll()); } return generator(); } -template <> std::pair<std::vector<u8>, std::string> GetGameListCachedObject( const std::string& filename, const std::string& ext, const std::function<std::pair<std::vector<u8>, std::string>()>& generator) { @@ -88,58 +80,56 @@ std::pair<std::vector<u8>, std::string> GetGameListCachedObject( if (!FileUtil::Exists(path1) || !FileUtil::Exists(path2)) { const auto [icon, nacp] = generator(); - FileUtil::IOFile file1(path1, "wb"); - if (!file1.IsOpen()) { + QFile file1{QString::fromStdString(path1)}; + if (!file1.open(QFile::WriteOnly)) { LOG_ERROR(Frontend, "Failed to open cache file."); return generator(); } - if (!file1.Resize(icon.size())) { + if (!file1.resize(icon.size())) { LOG_ERROR(Frontend, "Failed to resize cache file to necessary size."); return generator(); } - if (file1.WriteBytes(icon.data(), icon.size()) != icon.size()) { + if (file1.write(reinterpret_cast<const char*>(icon.data()), icon.size()) != icon.size()) { LOG_ERROR(Frontend, "Failed to write data to cache file."); return generator(); } - std::ofstream stream2(path2, std::ios::out); - if (stream2) { - stream2 << nacp; + QFile file2{QString::fromStdString(path2)}; + if (file2.open(QFile::WriteOnly)) { + file2.write(nacp.data(), nacp.size()); } return std::make_pair(icon, nacp); } - FileUtil::IOFile file1(path1, "rb"); - std::ifstream stream2(path2); + QFile file1(QString::fromStdString(path1)); + QFile file2(QString::fromStdString(path2)); - if (!file1.IsOpen()) { + if (!file1.open(QFile::ReadOnly)) { LOG_ERROR(Frontend, "Failed to open cache file for reading."); return generator(); } - if (!stream2) { + if (!file2.open(QFile::ReadOnly)) { LOG_ERROR(Frontend, "Failed to open cache file for reading."); return generator(); } - std::vector<u8> vec(file1.GetSize()); - file1.ReadBytes(vec.data(), vec.size()); - - if (stream2 && !vec.empty()) { - const std::string out(std::istreambuf_iterator<char>{stream2}, - std::istreambuf_iterator<char>{}); - return std::make_pair(vec, out); + std::vector<u8> vec(file1.size()); + if (file1.read(reinterpret_cast<char*>(vec.data()), vec.size()) != + static_cast<s64>(vec.size())) { + return generator(); } - return generator(); + const auto data = file2.readAll(); + return std::make_pair(vec, data.toStdString()); } void GetMetadataFromControlNCA(const FileSys::PatchManager& patch_manager, const FileSys::NCA& nca, std::vector<u8>& icon, std::string& name) { - std::tie(icon, name) = GetGameListCachedObject<std::pair<std::vector<u8>, std::string>>( + std::tie(icon, name) = GetGameListCachedObject( fmt::format("{:016X}", patch_manager.GetTitleID()), {}, [&patch_manager, &nca] { const auto [nacp, icon_f] = patch_manager.ParseControlNCA(nca); return std::make_pair(icon_f->ReadAllBytes(), nacp->GetApplicationName()); @@ -221,7 +211,7 @@ QList<QStandardItem*> MakeGameListEntry(const std::string& path, const std::stri }; if (UISettings::values.show_add_ons) { - const auto patch_versions = GetGameListCachedObject<QString>( + const auto patch_versions = GetGameListCachedObject( fmt::format("{:016X}", patch.GetTitleID()), "pv.txt", [&patch, &loader] { return FormatPatchNameVersions(patch, loader, loader.IsRomFSUpdatable()); }); diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index f8a0daebd..cd32623b4 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -238,15 +238,13 @@ void GMainWindow::ProfileSelectorSelectProfile() { dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint); dialog.setWindowModality(Qt::WindowModal); - dialog.exec(); - - if (!dialog.GetStatus()) { + if (dialog.exec() == QDialog::Rejected) { emit ProfileSelectorFinishedSelection(std::nullopt); return; } Service::Account::ProfileManager manager; - const auto uuid = manager.GetUser(dialog.GetIndex()); + const auto uuid = manager.GetUser(static_cast<std::size_t>(dialog.GetIndex())); if (!uuid.has_value()) { emit ProfileSelectorFinishedSelection(std::nullopt); return; @@ -261,9 +259,8 @@ void GMainWindow::SoftwareKeyboardGetText( dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint); dialog.setWindowModality(Qt::WindowModal); - dialog.exec(); - if (!dialog.GetStatus()) { + if (dialog.exec() == QDialog::Rejected) { emit SoftwareKeyboardFinishedText(std::nullopt); return; } @@ -850,11 +847,6 @@ bool GMainWindow::LoadROM(const QString& filename) { QMessageBox::critical(this, tr("Error while loading ROM!"), tr("The ROM format is not supported.")); break; - case Core::System::ResultStatus::ErrorSystemMode: - LOG_CRITICAL(Frontend, "Failed to load ROM!"); - QMessageBox::critical(this, tr("Error while loading ROM!"), - tr("Could not determine the system mode.")); - break; case Core::System::ResultStatus::ErrorVideoCore: QMessageBox::critical( this, tr("An error occurred initializing the video core."), @@ -901,11 +893,12 @@ void GMainWindow::SelectAndSetCurrentUser() { dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint); dialog.setWindowModality(Qt::WindowModal); - dialog.exec(); - if (dialog.GetStatus()) { - Settings::values.current_user = static_cast<s32>(dialog.GetIndex()); + if (dialog.exec() == QDialog::Rejected) { + return; } + + Settings::values.current_user = dialog.GetIndex(); } void GMainWindow::BootGame(const QString& filename) { @@ -1055,14 +1048,13 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target const std::string nand_dir = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir); ASSERT(program_id != 0); - const auto select_profile = [this]() -> s32 { + const auto select_profile = [this] { QtProfileSelectionDialog dialog(this); dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint); dialog.setWindowModality(Qt::WindowModal); - dialog.exec(); - if (!dialog.GetStatus()) { + if (dialog.exec() == QDialog::Rejected) { return -1; } @@ -1070,11 +1062,12 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target }; const auto index = select_profile(); - if (index == -1) + if (index == -1) { return; + } Service::Account::ProfileManager manager; - const auto user_id = manager.GetUser(index); + const auto user_id = manager.GetUser(static_cast<std::size_t>(index)); ASSERT(user_id); path = nand_dir + FileSys::SaveDataFactory::GetFullPath(FileSys::SaveDataSpaceId::NandUser, FileSys::SaveDataType::SaveData, @@ -1296,10 +1289,10 @@ void GMainWindow::OnGameListOpenPerGameProperties(const std::string& file) { } ConfigurePerGameGeneral dialog(this, title_id); - dialog.loadFromFile(v_file); + dialog.LoadFromFile(v_file); auto result = dialog.exec(); if (result == QDialog::Accepted) { - dialog.applyConfiguration(); + dialog.ApplyConfiguration(); const auto reload = UISettings::values.is_game_list_reload_pending.exchange(false); if (reload) { @@ -1690,26 +1683,31 @@ void GMainWindow::ToggleWindowMode() { } void GMainWindow::OnConfigure() { - ConfigureDialog configureDialog(this, hotkey_registry); - auto old_theme = UISettings::values.theme; + const auto old_theme = UISettings::values.theme; const bool old_discord_presence = UISettings::values.enable_discord_presence; - auto result = configureDialog.exec(); - if (result == QDialog::Accepted) { - configureDialog.applyConfiguration(); - InitializeHotkeys(); - if (UISettings::values.theme != old_theme) - UpdateUITheme(); - if (UISettings::values.enable_discord_presence != old_discord_presence) - SetDiscordEnabled(UISettings::values.enable_discord_presence); - const auto reload = UISettings::values.is_game_list_reload_pending.exchange(false); - if (reload) { - game_list->PopulateAsync(UISettings::values.game_directory_path, - UISettings::values.game_directory_deepscan); - } + ConfigureDialog configure_dialog(this, hotkey_registry); + const auto result = configure_dialog.exec(); + if (result != QDialog::Accepted) { + return; + } - config->Save(); + configure_dialog.ApplyConfiguration(); + InitializeHotkeys(); + if (UISettings::values.theme != old_theme) { + UpdateUITheme(); + } + if (UISettings::values.enable_discord_presence != old_discord_presence) { + SetDiscordEnabled(UISettings::values.enable_discord_presence); } + + const auto reload = UISettings::values.is_game_list_reload_pending.exchange(false); + if (reload) { + game_list->PopulateAsync(UISettings::values.game_directory_path, + UISettings::values.game_directory_deepscan); + } + + config->Save(); } void GMainWindow::OnLoadAmiibo() { diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index 5d9442646..129d8ca73 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp @@ -192,7 +192,7 @@ int main(int argc, char** argv) { switch (load_result) { case Core::System::ResultStatus::ErrorGetLoader: - LOG_CRITICAL(Frontend, "Failed to obtain loader for %s!", filepath.c_str()); + LOG_CRITICAL(Frontend, "Failed to obtain loader for {}!", filepath); return -1; case Core::System::ResultStatus::ErrorLoader: LOG_CRITICAL(Frontend, "Failed to load ROM!"); @@ -200,9 +200,6 @@ int main(int argc, char** argv) { case Core::System::ResultStatus::ErrorNotInitialized: LOG_CRITICAL(Frontend, "CPUCore not initialized"); return -1; - case Core::System::ResultStatus::ErrorSystemMode: - LOG_CRITICAL(Frontend, "Failed to determine system mode!"); - return -1; case Core::System::ResultStatus::ErrorVideoCore: LOG_CRITICAL(Frontend, "Failed to initialize VideoCore!"); return -1; |