From 23cae6079ad3a25c28cffa21e0e60e8e4da9942c Mon Sep 17 00:00:00 2001 From: pineappleEA Date: Wed, 23 Jun 2021 14:35:57 +0200 Subject: [PATCH] early-access version 1814 --- README.md | 2 +- src/common/detached_tasks.cpp | 2 + src/common/fs/file.cpp | 4 +- src/common/fs/file.h | 12 +- src/common/fs/fs.cpp | 5 +- src/common/fs/fs.h | 30 +-- src/common/logging/backend.cpp | 4 +- src/core/CMakeLists.txt | 3 + src/core/file_sys/patch_manager.cpp | 18 +- src/core/file_sys/sdmc_factory.cpp | 8 + src/core/file_sys/sdmc_factory.h | 1 + .../system_archive/system_version.cpp | 48 ++-- src/core/file_sys/vfs_real.cpp | 7 +- src/core/hle/api_version.h | 38 +++ src/core/hle/service/bcat/backend/boxcat.cpp | 4 +- .../hle/service/filesystem/filesystem.cpp | 10 + src/core/hle/service/filesystem/filesystem.h | 1 + src/core/hle/service/hid/controllers/npad.cpp | 4 + src/core/hle/service/hid/controllers/npad.h | 4 + src/core/hle/service/spl/csrng.cpp | 2 +- src/core/hle/service/spl/module.cpp | 124 +++++++++- src/core/hle/service/spl/module.h | 13 +- src/core/hle/service/spl/spl.cpp | 84 +++---- src/core/hle/service/spl/spl_results.h | 29 +++ src/core/hle/service/spl/spl_types.h | 230 ++++++++++++++++++ .../time/time_zone_content_manager.cpp | 2 +- src/input_common/mouse/mouse_input.cpp | 16 +- src/input_common/mouse/mouse_input.h | 6 +- src/video_core/rasterizer_interface.h | 4 +- src/video_core/renderer_base.h | 2 + src/video_core/renderer_opengl/gl_device.cpp | 58 ++++- src/video_core/renderer_opengl/gl_device.h | 3 + .../renderer_opengl/gl_rasterizer.cpp | 2 +- .../renderer_opengl/gl_rasterizer.h | 2 +- .../renderer_opengl/gl_shader_cache.cpp | 6 +- .../renderer_opengl/gl_shader_cache.h | 2 +- .../renderer_opengl/renderer_opengl.h | 4 + .../renderer_vulkan/renderer_vulkan.h | 4 + src/video_core/texture_cache/texture_cache.h | 5 +- .../nsight_aftermath_tracker.cpp | 2 +- .../vulkan_common/vulkan_device.cpp | 21 ++ src/video_core/vulkan_common/vulkan_device.h | 3 + src/yuzu/bootmanager.cpp | 12 +- src/yuzu/bootmanager.h | 6 +- src/yuzu/configuration/configure_per_game.cpp | 2 + src/yuzu/configuration/configure_per_game.ui | 7 +- .../configure_per_game_addons.cpp | 4 +- src/yuzu/game_list.cpp | 12 +- src/yuzu/game_list.h | 7 +- src/yuzu/main.cpp | 43 ++-- src/yuzu/main.h | 7 +- src/yuzu_cmd/yuzu.cpp | 2 +- 52 files changed, 752 insertions(+), 179 deletions(-) create mode 100755 src/core/hle/api_version.h create mode 100755 src/core/hle/service/spl/spl_results.h create mode 100755 src/core/hle/service/spl/spl_types.h diff --git a/README.md b/README.md index 6bc9fb186..a14b5de78 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 1805. +This is the source code for early-access 1814. ## Legal Notice diff --git a/src/common/detached_tasks.cpp b/src/common/detached_tasks.cpp index f2b4939df..c1362631e 100755 --- a/src/common/detached_tasks.cpp +++ b/src/common/detached_tasks.cpp @@ -21,6 +21,8 @@ void DetachedTasks::WaitForAllTasks() { } DetachedTasks::~DetachedTasks() { + WaitForAllTasks(); + std::unique_lock lock{mutex}; ASSERT(count == 0); instance = nullptr; diff --git a/src/common/fs/file.cpp b/src/common/fs/file.cpp index 710e88b39..077f34995 100755 --- a/src/common/fs/file.cpp +++ b/src/common/fs/file.cpp @@ -172,7 +172,7 @@ std::string ReadStringFromFile(const std::filesystem::path& path, FileType type) size_t WriteStringToFile(const std::filesystem::path& path, FileType type, std::string_view string) { - if (!IsFile(path)) { + if (Exists(path) && !IsFile(path)) { return 0; } @@ -183,7 +183,7 @@ size_t WriteStringToFile(const std::filesystem::path& path, FileType type, size_t AppendStringToFile(const std::filesystem::path& path, FileType type, std::string_view string) { - if (!IsFile(path)) { + if (Exists(path) && !IsFile(path)) { return 0; } diff --git a/src/common/fs/file.h b/src/common/fs/file.h index 0f10b6003..588fe619d 100755 --- a/src/common/fs/file.h +++ b/src/common/fs/file.h @@ -49,7 +49,7 @@ void OpenFileStream(FileStream& file_stream, const Path& path, std::ios_base::op /** * Reads an entire file at path and returns a string of the contents read from the file. - * If the filesystem object at path is not a file, this function returns an empty string. + * If the filesystem object at path is not a regular file, this function returns an empty string. * * @param path Filesystem path * @param type File type @@ -72,7 +72,8 @@ template /** * Writes a string to a file at path and returns the number of characters successfully written. * If a file already exists at path, its contents will be erased. - * If the filesystem object at path is not a file, this function returns 0. + * If a file does not exist at path, it creates and opens a new empty file for writing. + * If the filesystem object at path exists and is not a regular file, this function returns 0. * * @param path Filesystem path * @param type File type @@ -95,7 +96,8 @@ template /** * Appends a string to a file at path and returns the number of characters successfully written. - * If the filesystem object at path is not a file, this function returns 0. + * If a file does not exist at path, it creates and opens a new empty file for appending. + * If the filesystem object at path exists and is not a regular file, this function returns 0. * * @param path Filesystem path * @param type File type @@ -394,11 +396,11 @@ public: [[nodiscard]] size_t WriteString(std::span string) const; /** - * Flushes any unwritten buffered data into the file. + * Attempts to flush any unwritten buffered data into the file and flush the file into the disk. * * @returns True if the flush was successful, false otherwise. */ - [[nodiscard]] bool Flush() const; + bool Flush() const; /** * Resizes the file to a given size. diff --git a/src/common/fs/fs.cpp b/src/common/fs/fs.cpp index d3159e908..9089cad67 100755 --- a/src/common/fs/fs.cpp +++ b/src/common/fs/fs.cpp @@ -135,8 +135,9 @@ std::shared_ptr FileOpen(const fs::path& path, FileAccessMode mode, File return nullptr; } - if (!IsFile(path)) { - LOG_ERROR(Common_Filesystem, "Filesystem object at path={} is not a file", + if (Exists(path) && !IsFile(path)) { + LOG_ERROR(Common_Filesystem, + "Filesystem object at path={} exists and is not a regular file", PathToUTF8String(path)); return nullptr; } diff --git a/src/common/fs/fs.h b/src/common/fs/fs.h index f6f256349..183126de3 100755 --- a/src/common/fs/fs.h +++ b/src/common/fs/fs.h @@ -48,18 +48,18 @@ template * * Failures occur when: * - Input path is not valid - * - Filesystem object at path is not a file + * - Filesystem object at path is not a regular file * - Filesystem at path is read only * * @param path Filesystem path * * @returns True if file removal succeeds or file does not exist, false otherwise. */ -[[nodiscard]] bool RemoveFile(const std::filesystem::path& path); +bool RemoveFile(const std::filesystem::path& path); #ifdef _WIN32 template -[[nodiscard]] bool RemoveFile(const Path& path) { +bool RemoveFile(const Path& path) { if constexpr (IsChar) { return RemoveFile(ToU8String(path)); } else { @@ -74,7 +74,7 @@ template * Failures occur when: * - One or both input path(s) is not valid * - Filesystem object at old_path does not exist - * - Filesystem object at old_path is not a file + * - Filesystem object at old_path is not a regular file * - Filesystem object at new_path exists * - Filesystem at either path is read only * @@ -110,8 +110,8 @@ template * * Failures occur when: * - Input path is not valid - * - Filesystem object at path is not a file - * - The file is not opened + * - Filesystem object at path exists and is not a regular file + * - The file is not open * * @param path Filesystem path * @param mode File access mode @@ -251,11 +251,11 @@ template * * @returns True if directory removal succeeds or directory does not exist, false otherwise. */ -[[nodiscard]] bool RemoveDir(const std::filesystem::path& path); +bool RemoveDir(const std::filesystem::path& path); #ifdef _WIN32 template -[[nodiscard]] bool RemoveDir(const Path& path) { +bool RemoveDir(const Path& path) { if constexpr (IsChar) { return RemoveDir(ToU8String(path)); } else { @@ -276,11 +276,11 @@ template * * @returns True if the directory and all of its contents are removed successfully, false otherwise. */ -[[nodiscard]] bool RemoveDirRecursively(const std::filesystem::path& path); +bool RemoveDirRecursively(const std::filesystem::path& path); #ifdef _WIN32 template -[[nodiscard]] bool RemoveDirRecursively(const Path& path) { +bool RemoveDirRecursively(const Path& path) { if constexpr (IsChar) { return RemoveDirRecursively(ToU8String(path)); } else { @@ -301,11 +301,11 @@ template * * @returns True if all of the directory's contents are removed successfully, false otherwise. */ -[[nodiscard]] bool RemoveDirContentsRecursively(const std::filesystem::path& path); +bool RemoveDirContentsRecursively(const std::filesystem::path& path); #ifdef _WIN32 template -[[nodiscard]] bool RemoveDirContentsRecursively(const Path& path) { +bool RemoveDirContentsRecursively(const Path& path) { if constexpr (IsChar) { return RemoveDirContentsRecursively(ToU8String(path)); } else { @@ -435,11 +435,13 @@ template #endif /** - * Returns whether a filesystem object at path is a file. + * Returns whether a filesystem object at path is a regular file. + * A regular file is a file that stores text or binary data. + * It is not a directory, symlink, FIFO, socket, block device, or character device. * * @param path Filesystem path * - * @returns True if a filesystem object at path is a file, false otherwise. + * @returns True if a filesystem object at path is a regular file, false otherwise. */ [[nodiscard]] bool IsFile(const std::filesystem::path& path); diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index d5cff400f..47ce06478 100755 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp @@ -159,7 +159,7 @@ FileBackend::FileBackend(const std::filesystem::path& filename) { // Existence checks are done within the functions themselves. // We don't particularly care if these succeed or not. - void(FS::RemoveFile(old_filename)); + FS::RemoveFile(old_filename); void(FS::RenameFile(filename, old_filename)); file = @@ -186,7 +186,7 @@ void FileBackend::Write(const Entry& entry) { bytes_written += file->WriteString(FormatLogMessage(entry).append(1, '\n')); if (entry.log_level >= Level::Error) { - void(file->Flush()); + file->Flush(); } } diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index efb851f5a..83b5b7676 100755 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -139,6 +139,7 @@ add_library(core STATIC frontend/input.h hardware_interrupt_manager.cpp hardware_interrupt_manager.h + hle/api_version.h hle/ipc.h hle/ipc_helpers.h hle/kernel/board/nintendo/nx/k_system_control.cpp @@ -550,6 +551,8 @@ add_library(core STATIC hle/service/spl/module.h hle/service/spl/spl.cpp hle/service/spl/spl.h + hle/service/spl/spl_results.h + hle/service/spl/spl_types.h hle/service/ssl/ssl.cpp hle/service/ssl/ssl.h hle/service/time/clock_types.h diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index 53b8b7ca0..13d294ad8 100755 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp @@ -345,8 +345,10 @@ std::vector PatchManager::CreateCheatList( static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, ContentRecordType type, const Service::FileSystem::FileSystemController& fs_controller) { const auto load_dir = fs_controller.GetModificationLoadRoot(title_id); + const auto sdmc_load_dir = fs_controller.GetSDMCModificationLoadRoot(title_id); if ((type != ContentRecordType::Program && type != ContentRecordType::Data) || - load_dir == nullptr || load_dir->GetSize() <= 0) { + ((load_dir == nullptr || load_dir->GetSize() <= 0) && + (sdmc_load_dir == nullptr || sdmc_load_dir->GetSize() <= 0))) { return; } @@ -356,7 +358,10 @@ static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, ContentRecordType t } const auto& disabled = Settings::values.disabled_addons[title_id]; - auto patch_dirs = load_dir->GetSubdirectories(); + std::vector patch_dirs = load_dir->GetSubdirectories(); + if (std::find(disabled.cbegin(), disabled.cend(), "SDMC") == disabled.cend()) { + patch_dirs.push_back(sdmc_load_dir); + } std::sort(patch_dirs.begin(), patch_dirs.end(), [](const VirtualDir& l, const VirtualDir& r) { return l->GetName() < r->GetName(); }); @@ -524,6 +529,15 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u } } + // SDMC mod directory (RomFS LayeredFS) + const auto sdmc_mod_dir = fs_controller.GetSDMCModificationLoadRoot(title_id); + if (sdmc_mod_dir != nullptr && sdmc_mod_dir->GetSize() > 0 && + IsDirValidAndNonEmpty(FindSubdirectoryCaseless(sdmc_mod_dir, "romfs"))) { + const auto mod_disabled = + std::find(disabled.begin(), disabled.end(), "SDMC") != disabled.end(); + out.insert_or_assign(mod_disabled ? "[D] SDMC" : "SDMC", "LayeredFS"); + } + // DLC const auto dlc_entries = content_provider.ListEntriesFilter(TitleType::AOC, ContentRecordType::Data); diff --git a/src/core/file_sys/sdmc_factory.cpp b/src/core/file_sys/sdmc_factory.cpp index cb56d8f2d..7e878123c 100755 --- a/src/core/file_sys/sdmc_factory.cpp +++ b/src/core/file_sys/sdmc_factory.cpp @@ -27,6 +27,14 @@ ResultVal SDMCFactory::Open() const { return MakeResult(dir); } +VirtualDir SDMCFactory::GetSDMCModificationLoadRoot(u64 title_id) const { + // LayeredFS doesn't work on updates and title id-less homebrew + if (title_id == 0 || (title_id & 0xFFF) == 0x800) { + return nullptr; + } + return GetOrCreateDirectoryRelative(dir, fmt::format("/atmosphere/contents/{:016X}", title_id)); +} + VirtualDir SDMCFactory::GetSDMCContentDirectory() const { return GetOrCreateDirectoryRelative(dir, "/Nintendo/Contents"); } diff --git a/src/core/file_sys/sdmc_factory.h b/src/core/file_sys/sdmc_factory.h index 2bb92ba93..c57514938 100755 --- a/src/core/file_sys/sdmc_factory.h +++ b/src/core/file_sys/sdmc_factory.h @@ -21,6 +21,7 @@ public: ResultVal Open() const; + VirtualDir GetSDMCModificationLoadRoot(u64 title_id) const; VirtualDir GetSDMCContentDirectory() const; RegisteredCache* GetSDMCContents() const; diff --git a/src/core/file_sys/system_archive/system_version.cpp b/src/core/file_sys/system_archive/system_version.cpp index 54704105b..9b76d007e 100755 --- a/src/core/file_sys/system_archive/system_version.cpp +++ b/src/core/file_sys/system_archive/system_version.cpp @@ -4,47 +4,29 @@ #include "core/file_sys/system_archive/system_version.h" #include "core/file_sys/vfs_vector.h" +#include "core/hle/api_version.h" namespace FileSys::SystemArchive { -namespace SystemVersionData { - -// This section should reflect the best system version to describe yuzu's HLE api. -// TODO(DarkLordZach): Update when HLE gets better. - -constexpr u8 VERSION_MAJOR = 11; -constexpr u8 VERSION_MINOR = 0; -constexpr u8 VERSION_MICRO = 1; - -constexpr u8 REVISION_MAJOR = 1; -constexpr u8 REVISION_MINOR = 0; - -constexpr char PLATFORM_STRING[] = "NX"; -constexpr char VERSION_HASH[] = "69103fcb2004dace877094c2f8c29e6113be5dbf"; -constexpr char DISPLAY_VERSION[] = "11.0.1"; -constexpr char DISPLAY_TITLE[] = "NintendoSDK Firmware for NX 11.0.1-1.0"; - -} // namespace SystemVersionData - std::string GetLongDisplayVersion() { - return SystemVersionData::DISPLAY_TITLE; + return HLE::ApiVersion::DISPLAY_TITLE; } VirtualDir SystemVersion() { VirtualFile file = std::make_shared(std::vector(0x100), "file"); - file->WriteObject(SystemVersionData::VERSION_MAJOR, 0); - file->WriteObject(SystemVersionData::VERSION_MINOR, 1); - file->WriteObject(SystemVersionData::VERSION_MICRO, 2); - file->WriteObject(SystemVersionData::REVISION_MAJOR, 4); - file->WriteObject(SystemVersionData::REVISION_MINOR, 5); - file->WriteArray(SystemVersionData::PLATFORM_STRING, - std::min(sizeof(SystemVersionData::PLATFORM_STRING), 0x20ULL), 0x8); - file->WriteArray(SystemVersionData::VERSION_HASH, - std::min(sizeof(SystemVersionData::VERSION_HASH), 0x40ULL), 0x28); - file->WriteArray(SystemVersionData::DISPLAY_VERSION, - std::min(sizeof(SystemVersionData::DISPLAY_VERSION), 0x18ULL), 0x68); - file->WriteArray(SystemVersionData::DISPLAY_TITLE, - std::min(sizeof(SystemVersionData::DISPLAY_TITLE), 0x80ULL), 0x80); + file->WriteObject(HLE::ApiVersion::HOS_VERSION_MAJOR, 0); + file->WriteObject(HLE::ApiVersion::HOS_VERSION_MINOR, 1); + file->WriteObject(HLE::ApiVersion::HOS_VERSION_MICRO, 2); + file->WriteObject(HLE::ApiVersion::SDK_REVISION_MAJOR, 4); + file->WriteObject(HLE::ApiVersion::SDK_REVISION_MINOR, 5); + file->WriteArray(HLE::ApiVersion::PLATFORM_STRING, + std::min(sizeof(HLE::ApiVersion::PLATFORM_STRING), 0x20ULL), 0x8); + file->WriteArray(HLE::ApiVersion::VERSION_HASH, + std::min(sizeof(HLE::ApiVersion::VERSION_HASH), 0x40ULL), 0x28); + file->WriteArray(HLE::ApiVersion::DISPLAY_VERSION, + std::min(sizeof(HLE::ApiVersion::DISPLAY_VERSION), 0x18ULL), 0x68); + file->WriteArray(HLE::ApiVersion::DISPLAY_TITLE, + std::min(sizeof(HLE::ApiVersion::DISPLAY_TITLE), 0x80ULL), 0x80); return std::make_shared(std::vector{file}, std::vector{}, "data"); } diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp index d0b8fd046..3dad54f49 100755 --- a/src/core/file_sys/vfs_real.cpp +++ b/src/core/file_sys/vfs_real.cpp @@ -24,17 +24,12 @@ constexpr FS::FileAccessMode ModeFlagsToFileAccessMode(Mode mode) { case Mode::Read: return FS::FileAccessMode::Read; case Mode::Write: - return FS::FileAccessMode::Write; case Mode::ReadWrite: - return FS::FileAccessMode::ReadWrite; case Mode::Append: - return FS::FileAccessMode::Append; case Mode::ReadAppend: - return FS::FileAccessMode::ReadAppend; case Mode::WriteAppend: - return FS::FileAccessMode::Append; case Mode::All: - return FS::FileAccessMode::ReadAppend; + return FS::FileAccessMode::ReadWrite; default: return {}; } diff --git a/src/core/hle/api_version.h b/src/core/hle/api_version.h new file mode 100755 index 000000000..811732179 --- /dev/null +++ b/src/core/hle/api_version.h @@ -0,0 +1,38 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/common_types.h" + +// This file contains yuzu's HLE API version constants. + +namespace HLE::ApiVersion { + +// Horizon OS version constants. + +constexpr u8 HOS_VERSION_MAJOR = 11; +constexpr u8 HOS_VERSION_MINOR = 0; +constexpr u8 HOS_VERSION_MICRO = 1; + +// NintendoSDK version constants. + +constexpr u8 SDK_REVISION_MAJOR = 1; +constexpr u8 SDK_REVISION_MINOR = 0; + +constexpr char PLATFORM_STRING[] = "NX"; +constexpr char VERSION_HASH[] = "69103fcb2004dace877094c2f8c29e6113be5dbf"; +constexpr char DISPLAY_VERSION[] = "11.0.1"; +constexpr char DISPLAY_TITLE[] = "NintendoSDK Firmware for NX 11.0.1-1.0"; + +// Atmosphere version constants. + +constexpr u8 ATMOSPHERE_RELEASE_VERSION_MAJOR = 0; +constexpr u8 ATMOSPHERE_RELEASE_VERSION_MINOR = 19; +constexpr u8 ATMOSPHERE_RELEASE_VERSION_MICRO = 4; + +constexpr u32 GetTargetFirmware() { + return u32{HOS_VERSION_MAJOR} << 24 | u32{HOS_VERSION_MINOR} << 16 | + u32{HOS_VERSION_MICRO} << 8 | 0U; +} + +} // namespace HLE::ApiVersion diff --git a/src/core/hle/service/bcat/backend/boxcat.cpp b/src/core/hle/service/bcat/backend/boxcat.cpp index a2844ea8c..dc15cf58b 100755 --- a/src/core/hle/service/bcat/backend/boxcat.cpp +++ b/src/core/hle/service/bcat/backend/boxcat.cpp @@ -313,7 +313,7 @@ void SynchronizeInternal(AM::Applets::AppletManager& applet_manager, DirectoryGe LOG_ERROR(Service_BCAT, "Boxcat synchronization failed with error '{}'!", res); if (res == DownloadResult::NoMatchBuildId || res == DownloadResult::NoMatchTitleId) { - void(Common::FS::RemoveFile(zip_path)); + Common::FS::RemoveFile(zip_path); } HandleDownloadDisplayResult(applet_manager, res); @@ -445,7 +445,7 @@ std::optional> Boxcat::GetLaunchParameter(TitleIDVersion title) LOG_ERROR(Service_BCAT, "Boxcat synchronization failed with error '{}'!", res); if (res == DownloadResult::NoMatchBuildId || res == DownloadResult::NoMatchTitleId) { - void(Common::FS::RemoveFile(bin_file_path)); + Common::FS::RemoveFile(bin_file_path); } HandleDownloadDisplayResult(applet_manager, res); diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index 3c16fe6c7..d66e74d3a 100755 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -703,6 +703,16 @@ FileSys::VirtualDir FileSystemController::GetModificationLoadRoot(u64 title_id) return bis_factory->GetModificationLoadRoot(title_id); } +FileSys::VirtualDir FileSystemController::GetSDMCModificationLoadRoot(u64 title_id) const { + LOG_TRACE(Service_FS, "Opening SDMC mod load root for tid={:016X}", title_id); + + if (sdmc_factory == nullptr) { + return nullptr; + } + + return sdmc_factory->GetSDMCModificationLoadRoot(title_id); +} + FileSys::VirtualDir FileSystemController::GetModificationDumpRoot(u64 title_id) const { LOG_TRACE(Service_FS, "Opening mod dump root for tid={:016X}", title_id); diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h index b6b1b9220..d387af3cb 100755 --- a/src/core/hle/service/filesystem/filesystem.h +++ b/src/core/hle/service/filesystem/filesystem.h @@ -115,6 +115,7 @@ public: FileSys::VirtualDir GetContentDirectory(ContentStorageId id) const; FileSys::VirtualDir GetImageDirectory(ImageDirectoryId id) const; + FileSys::VirtualDir GetSDMCModificationLoadRoot(u64 title_id) const; FileSys::VirtualDir GetModificationLoadRoot(u64 title_id) const; FileSys::VirtualDir GetModificationDumpRoot(u64 title_id) const; diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 7acad3798..1eb02aee2 100755 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -314,6 +314,8 @@ void Controller_NPad::OnInit() { void Controller_NPad::OnLoadInputDevices() { const auto& players = Settings::values.players.GetValue(); + + std::lock_guard lock{mutex}; for (std::size_t i = 0; i < players.size(); ++i) { std::transform(players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_END, @@ -348,6 +350,8 @@ void Controller_NPad::OnRelease() { } void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { + std::lock_guard lock{mutex}; + const auto controller_idx = NPadIdToIndex(npad_id); const auto controller_type = connected_controllers[controller_idx].type; if (!connected_controllers[controller_idx].is_connected) { diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index c050c9a44..1409d82a2 100755 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -6,6 +6,8 @@ #include #include +#include + #include "common/bit_field.h" #include "common/common_types.h" #include "common/quaternion.h" @@ -563,6 +565,8 @@ private: using MotionArray = std::array< std::array, Settings::NativeMotion::NUM_MOTIONS_HID>, 10>; + + std::mutex mutex; ButtonArray buttons; StickArray sticks; VibrationArray vibrations; diff --git a/src/core/hle/service/spl/csrng.cpp b/src/core/hle/service/spl/csrng.cpp index 1beca417c..9c7f89475 100755 --- a/src/core/hle/service/spl/csrng.cpp +++ b/src/core/hle/service/spl/csrng.cpp @@ -9,7 +9,7 @@ namespace Service::SPL { CSRNG::CSRNG(Core::System& system_, std::shared_ptr module_) : Interface(system_, std::move(module_), "csrng") { static const FunctionInfo functions[] = { - {0, &CSRNG::GetRandomBytes, "GetRandomBytes"}, + {0, &CSRNG::GenerateRandomBytes, "GenerateRandomBytes"}, }; RegisterHandlers(functions); } diff --git a/src/core/hle/service/spl/module.cpp b/src/core/hle/service/spl/module.cpp index 0b5e2b7c3..ebb179aa8 100755 --- a/src/core/hle/service/spl/module.cpp +++ b/src/core/hle/service/spl/module.cpp @@ -10,6 +10,7 @@ #include #include "common/logging/log.h" #include "common/settings.h" +#include "core/hle/api_version.h" #include "core/hle/ipc_helpers.h" #include "core/hle/service/spl/csrng.h" #include "core/hle/service/spl/module.h" @@ -24,7 +25,46 @@ Module::Interface::Interface(Core::System& system_, std::shared_ptr modu Module::Interface::~Interface() = default; -void Module::Interface::GetRandomBytes(Kernel::HLERequestContext& ctx) { +void Module::Interface::GetConfig(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto config_item = rp.PopEnum(); + + // This should call svcCallSecureMonitor with the appropriate args. + // Since we do not have it implemented yet, we will use this for now. + const auto smc_result = GetConfigImpl(config_item); + const auto result_code = smc_result.Code(); + + if (smc_result.Failed()) { + LOG_ERROR(Service_SPL, "called, config_item={}, result_code={}", config_item, + result_code.raw); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result_code); + } + + LOG_DEBUG(Service_SPL, "called, config_item={}, result_code={}, smc_result={}", config_item, + result_code.raw, *smc_result); + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(result_code); + rb.Push(*smc_result); +} + +void Module::Interface::ModularExponentiate(Kernel::HLERequestContext& ctx) { + UNIMPLEMENTED_MSG("ModularExponentiate is not implemented!"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSecureMonitorNotImplemented); +} + +void Module::Interface::SetConfig(Kernel::HLERequestContext& ctx) { + UNIMPLEMENTED_MSG("SetConfig is not implemented!"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSecureMonitorNotImplemented); +} + +void Module::Interface::GenerateRandomBytes(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_SPL, "called"); const std::size_t size = ctx.GetWriteBufferSize(); @@ -39,6 +79,88 @@ void Module::Interface::GetRandomBytes(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } +void Module::Interface::IsDevelopment(Kernel::HLERequestContext& ctx) { + UNIMPLEMENTED_MSG("IsDevelopment is not implemented!"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSecureMonitorNotImplemented); +} + +void Module::Interface::SetBootReason(Kernel::HLERequestContext& ctx) { + UNIMPLEMENTED_MSG("SetBootReason is not implemented!"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSecureMonitorNotImplemented); +} + +void Module::Interface::GetBootReason(Kernel::HLERequestContext& ctx) { + UNIMPLEMENTED_MSG("GetBootReason is not implemented!"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSecureMonitorNotImplemented); +} + +ResultVal Module::Interface::GetConfigImpl(ConfigItem config_item) const { + switch (config_item) { + case ConfigItem::DisableProgramVerification: + case ConfigItem::DramId: + case ConfigItem::SecurityEngineInterruptNumber: + case ConfigItem::FuseVersion: + case ConfigItem::HardwareType: + case ConfigItem::HardwareState: + case ConfigItem::IsRecoveryBoot: + case ConfigItem::DeviceId: + case ConfigItem::BootReason: + case ConfigItem::MemoryMode: + case ConfigItem::IsDevelopmentFunctionEnabled: + case ConfigItem::KernelConfiguration: + case ConfigItem::IsChargerHiZModeEnabled: + case ConfigItem::QuestState: + case ConfigItem::RegulatorType: + case ConfigItem::DeviceUniqueKeyGeneration: + case ConfigItem::Package2Hash: + return ResultSecureMonitorNotImplemented; + case ConfigItem::ExosphereApiVersion: + // Get information about the current exosphere version. + return MakeResult((u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MAJOR} << 56) | + (u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MINOR} << 48) | + (u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MICRO} << 40) | + (static_cast(HLE::ApiVersion::GetTargetFirmware()))); + case ConfigItem::ExosphereNeedsReboot: + // We are executing, so we aren't in the process of rebooting. + return MakeResult(u64{0}); + case ConfigItem::ExosphereNeedsShutdown: + // We are executing, so we aren't in the process of shutting down. + return MakeResult(u64{0}); + case ConfigItem::ExosphereGitCommitHash: + // Get information about the current exosphere git commit hash. + return MakeResult(u64{0}); + case ConfigItem::ExosphereHasRcmBugPatch: + // Get information about whether this unit has the RCM bug patched. + return MakeResult(u64{0}); + case ConfigItem::ExosphereBlankProdInfo: + // Get whether this unit should simulate a "blanked" PRODINFO. + return MakeResult(u64{0}); + case ConfigItem::ExosphereAllowCalWrites: + // Get whether this unit should allow writing to the calibration partition. + return MakeResult(u64{0}); + case ConfigItem::ExosphereEmummcType: + // Get what kind of emummc this unit has active. + return MakeResult(u64{0}); + case ConfigItem::ExospherePayloadAddress: + // Gets the physical address of the reboot payload buffer, if one exists. + return ResultSecureMonitorNotInitialized; + case ConfigItem::ExosphereLogConfiguration: + // Get the log configuration. + return MakeResult(u64{0}); + case ConfigItem::ExosphereForceEnableUsb30: + // Get whether usb 3.0 should be force-enabled. + return MakeResult(u64{0}); + default: + return ResultSecureMonitorInvalidArgument; + } +} + void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { auto module = std::make_shared(); std::make_shared(system, module)->InstallAsService(service_manager); diff --git a/src/core/hle/service/spl/module.h b/src/core/hle/service/spl/module.h index 71855c1bf..61630df80 100755 --- a/src/core/hle/service/spl/module.h +++ b/src/core/hle/service/spl/module.h @@ -6,6 +6,8 @@ #include #include "core/hle/service/service.h" +#include "core/hle/service/spl/spl_results.h" +#include "core/hle/service/spl/spl_types.h" namespace Core { class System; @@ -21,12 +23,21 @@ public: const char* name); ~Interface() override; - void GetRandomBytes(Kernel::HLERequestContext& ctx); + // General + void GetConfig(Kernel::HLERequestContext& ctx); + void ModularExponentiate(Kernel::HLERequestContext& ctx); + void SetConfig(Kernel::HLERequestContext& ctx); + void GenerateRandomBytes(Kernel::HLERequestContext& ctx); + void IsDevelopment(Kernel::HLERequestContext& ctx); + void SetBootReason(Kernel::HLERequestContext& ctx); + void GetBootReason(Kernel::HLERequestContext& ctx); protected: std::shared_ptr module; private: + ResultVal GetConfigImpl(ConfigItem config_item) const; + std::mt19937 rng; }; }; diff --git a/src/core/hle/service/spl/spl.cpp b/src/core/hle/service/spl/spl.cpp index fff3f3c42..20384042f 100755 --- a/src/core/hle/service/spl/spl.cpp +++ b/src/core/hle/service/spl/spl.cpp @@ -10,13 +10,13 @@ SPL::SPL(Core::System& system_, std::shared_ptr module_) : Interface(system_, std::move(module_), "spl:") { // clang-format off static const FunctionInfo functions[] = { - {0, nullptr, "GetConfig"}, - {1, nullptr, "ModularExponentiate"}, - {5, nullptr, "SetConfig"}, - {7, &SPL::GetRandomBytes, "GetRandomBytes"}, - {11, nullptr, "IsDevelopment"}, - {24, nullptr, "SetBootReason"}, - {25, nullptr, "GetBootReason"}, + {0, &SPL::GetConfig, "GetConfig"}, + {1, &SPL::ModularExponentiate, "ModularExponentiate"}, + {5, &SPL::SetConfig, "SetConfig"}, + {7, &SPL::GenerateRandomBytes, "GenerateRandomBytes"}, + {11, &SPL::IsDevelopment, "IsDevelopment"}, + {24, &SPL::SetBootReason, "SetBootReason"}, + {25, &SPL::GetBootReason, "GetBootReason"}, }; // clang-format on @@ -27,22 +27,22 @@ SPL_MIG::SPL_MIG(Core::System& system_, std::shared_ptr module_) : Interface(system_, std::move(module_), "spl:mig") { // clang-format off static const FunctionInfo functions[] = { - {0, nullptr, "GetConfig"}, - {1, nullptr, "ModularExponentiate"}, + {0, &SPL::GetConfig, "GetConfig"}, + {1, &SPL::ModularExponentiate, "ModularExponentiate"}, {2, nullptr, "GenerateAesKek"}, {3, nullptr, "LoadAesKey"}, {4, nullptr, "GenerateAesKey"}, - {5, nullptr, "SetConfig"}, - {7, &SPL::GetRandomBytes, "GenerateRandomBytes"}, - {11, nullptr, "IsDevelopment"}, + {5, &SPL::SetConfig, "SetConfig"}, + {7, &SPL::GenerateRandomBytes, "GenerateRandomBytes"}, + {11, &SPL::IsDevelopment, "IsDevelopment"}, {14, nullptr, "DecryptAesKey"}, {15, nullptr, "CryptAesCtr"}, {16, nullptr, "ComputeCmac"}, {21, nullptr, "AllocateAesKeyslot"}, {22, nullptr, "DeallocateAesKeySlot"}, {23, nullptr, "GetAesKeyslotAvailableEvent"}, - {24, nullptr, "SetBootReason"}, - {25, nullptr, "GetBootReason"}, + {24, &SPL::SetBootReason, "SetBootReason"}, + {25, &SPL::GetBootReason, "GetBootReason"}, }; // clang-format on @@ -53,16 +53,16 @@ SPL_FS::SPL_FS(Core::System& system_, std::shared_ptr module_) : Interface(system_, std::move(module_), "spl:fs") { // clang-format off static const FunctionInfo functions[] = { - {0, nullptr, "GetConfig"}, - {1, nullptr, "ModularExponentiate"}, + {0, &SPL::GetConfig, "GetConfig"}, + {1, &SPL::ModularExponentiate, "ModularExponentiate"}, {2, nullptr, "GenerateAesKek"}, {3, nullptr, "LoadAesKey"}, {4, nullptr, "GenerateAesKey"}, - {5, nullptr, "SetConfig"}, - {7, &SPL::GetRandomBytes, "GenerateRandomBytes"}, + {5, &SPL::SetConfig, "SetConfig"}, + {7, &SPL::GenerateRandomBytes, "GenerateRandomBytes"}, {9, nullptr, "ImportLotusKey"}, {10, nullptr, "DecryptLotusMessage"}, - {11, nullptr, "IsDevelopment"}, + {11, &SPL::IsDevelopment, "IsDevelopment"}, {12, nullptr, "GenerateSpecificAesKey"}, {14, nullptr, "DecryptAesKey"}, {15, nullptr, "CryptAesCtr"}, @@ -71,8 +71,8 @@ SPL_FS::SPL_FS(Core::System& system_, std::shared_ptr module_) {21, nullptr, "AllocateAesKeyslot"}, {22, nullptr, "DeallocateAesKeySlot"}, {23, nullptr, "GetAesKeyslotAvailableEvent"}, - {24, nullptr, "SetBootReason"}, - {25, nullptr, "GetBootReason"}, + {24, &SPL::SetBootReason, "SetBootReason"}, + {25, &SPL::GetBootReason, "GetBootReason"}, {31, nullptr, "GetPackage2Hash"}, }; // clang-format on @@ -84,14 +84,14 @@ SPL_SSL::SPL_SSL(Core::System& system_, std::shared_ptr module_) : Interface(system_, std::move(module_), "spl:ssl") { // clang-format off static const FunctionInfo functions[] = { - {0, nullptr, "GetConfig"}, - {1, nullptr, "ModularExponentiate"}, + {0, &SPL::GetConfig, "GetConfig"}, + {1, &SPL::ModularExponentiate, "ModularExponentiate"}, {2, nullptr, "GenerateAesKek"}, {3, nullptr, "LoadAesKey"}, {4, nullptr, "GenerateAesKey"}, - {5, nullptr, "SetConfig"}, - {7, &SPL::GetRandomBytes, "GetRandomBytes"}, - {11, nullptr, "IsDevelopment"}, + {5, &SPL::SetConfig, "SetConfig"}, + {7, &SPL::GenerateRandomBytes, "GenerateRandomBytes"}, + {11, &SPL::IsDevelopment, "IsDevelopment"}, {13, nullptr, "DecryptDeviceUniqueData"}, {14, nullptr, "DecryptAesKey"}, {15, nullptr, "CryptAesCtr"}, @@ -99,8 +99,8 @@ SPL_SSL::SPL_SSL(Core::System& system_, std::shared_ptr module_) {21, nullptr, "AllocateAesKeyslot"}, {22, nullptr, "DeallocateAesKeySlot"}, {23, nullptr, "GetAesKeyslotAvailableEvent"}, - {24, nullptr, "SetBootReason"}, - {25, nullptr, "GetBootReason"}, + {24, &SPL::SetBootReason, "SetBootReason"}, + {25, &SPL::GetBootReason, "GetBootReason"}, {26, nullptr, "DecryptAndStoreSslClientCertKey"}, {27, nullptr, "ModularExponentiateWithSslClientCertKey"}, }; @@ -113,14 +113,14 @@ SPL_ES::SPL_ES(Core::System& system_, std::shared_ptr module_) : Interface(system_, std::move(module_), "spl:es") { // clang-format off static const FunctionInfo functions[] = { - {0, nullptr, "GetConfig"}, - {1, nullptr, "ModularExponentiate"}, + {0, &SPL::GetConfig, "GetConfig"}, + {1, &SPL::ModularExponentiate, "ModularExponentiate"}, {2, nullptr, "GenerateAesKek"}, {3, nullptr, "LoadAesKey"}, {4, nullptr, "GenerateAesKey"}, - {5, nullptr, "SetConfig"}, - {7, &SPL::GetRandomBytes, "GenerateRandomBytes"}, - {11, nullptr, "IsDevelopment"}, + {5, &SPL::SetConfig, "SetConfig"}, + {7, &SPL::GenerateRandomBytes, "GenerateRandomBytes"}, + {11, &SPL::IsDevelopment, "IsDevelopment"}, {13, nullptr, "DecryptDeviceUniqueData"}, {14, nullptr, "DecryptAesKey"}, {15, nullptr, "CryptAesCtr"}, @@ -131,8 +131,8 @@ SPL_ES::SPL_ES(Core::System& system_, std::shared_ptr module_) {21, nullptr, "AllocateAesKeyslot"}, {22, nullptr, "DeallocateAesKeySlot"}, {23, nullptr, "GetAesKeyslotAvailableEvent"}, - {24, nullptr, "SetBootReason"}, - {25, nullptr, "GetBootReason"}, + {24, &SPL::SetBootReason, "SetBootReason"}, + {25, &SPL::GetBootReason, "GetBootReason"}, {28, nullptr, "DecryptAndStoreDrmDeviceCertKey"}, {29, nullptr, "ModularExponentiateWithDrmDeviceCertKey"}, {31, nullptr, "PrepareEsArchiveKey"}, @@ -147,14 +147,14 @@ SPL_MANU::SPL_MANU(Core::System& system_, std::shared_ptr module_) : Interface(system_, std::move(module_), "spl:manu") { // clang-format off static const FunctionInfo functions[] = { - {0, nullptr, "GetConfig"}, - {1, nullptr, "ModularExponentiate"}, + {0, &SPL::GetConfig, "GetConfig"}, + {1, &SPL::ModularExponentiate, "ModularExponentiate"}, {2, nullptr, "GenerateAesKek"}, {3, nullptr, "LoadAesKey"}, {4, nullptr, "GenerateAesKey"}, - {5, nullptr, "SetConfig"}, - {7, &SPL::GetRandomBytes, "GetRandomBytes"}, - {11, nullptr, "IsDevelopment"}, + {5, &SPL::SetConfig, "SetConfig"}, + {7, &SPL::GenerateRandomBytes, "GenerateRandomBytes"}, + {11, &SPL::IsDevelopment, "IsDevelopment"}, {13, nullptr, "DecryptDeviceUniqueData"}, {14, nullptr, "DecryptAesKey"}, {15, nullptr, "CryptAesCtr"}, @@ -162,8 +162,8 @@ SPL_MANU::SPL_MANU(Core::System& system_, std::shared_ptr module_) {21, nullptr, "AllocateAesKeyslot"}, {22, nullptr, "DeallocateAesKeySlot"}, {23, nullptr, "GetAesKeyslotAvailableEvent"}, - {24, nullptr, "SetBootReason"}, - {25, nullptr, "GetBootReason"}, + {24, &SPL::SetBootReason, "SetBootReason"}, + {25, &SPL::GetBootReason, "GetBootReason"}, {30, nullptr, "ReencryptDeviceUniqueData"}, }; // clang-format on diff --git a/src/core/hle/service/spl/spl_results.h b/src/core/hle/service/spl/spl_results.h new file mode 100755 index 000000000..878fa91b7 --- /dev/null +++ b/src/core/hle/service/spl/spl_results.h @@ -0,0 +1,29 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/result.h" + +namespace Service::SPL { + +// Description 0 - 99 +constexpr ResultCode ResultSecureMonitorError{ErrorModule::SPL, 0}; +constexpr ResultCode ResultSecureMonitorNotImplemented{ErrorModule::SPL, 1}; +constexpr ResultCode ResultSecureMonitorInvalidArgument{ErrorModule::SPL, 2}; +constexpr ResultCode ResultSecureMonitorBusy{ErrorModule::SPL, 3}; +constexpr ResultCode ResultSecureMonitorNoAsyncOperation{ErrorModule::SPL, 4}; +constexpr ResultCode ResultSecureMonitorInvalidAsyncOperation{ErrorModule::SPL, 5}; +constexpr ResultCode ResultSecureMonitorNotPermitted{ErrorModule::SPL, 6}; +constexpr ResultCode ResultSecureMonitorNotInitialized{ErrorModule::SPL, 7}; + +constexpr ResultCode ResultInvalidSize{ErrorModule::SPL, 100}; +constexpr ResultCode ResultUnknownSecureMonitorError{ErrorModule::SPL, 101}; +constexpr ResultCode ResultDecryptionFailed{ErrorModule::SPL, 102}; + +constexpr ResultCode ResultOutOfKeySlots{ErrorModule::SPL, 104}; +constexpr ResultCode ResultInvalidKeySlot{ErrorModule::SPL, 105}; +constexpr ResultCode ResultBootReasonAlreadySet{ErrorModule::SPL, 106}; +constexpr ResultCode ResultBootReasonNotSet{ErrorModule::SPL, 107}; +constexpr ResultCode ResultInvalidArgument{ErrorModule::SPL, 108}; + +} // namespace Service::SPL diff --git a/src/core/hle/service/spl/spl_types.h b/src/core/hle/service/spl/spl_types.h new file mode 100755 index 000000000..23c39f7ed --- /dev/null +++ b/src/core/hle/service/spl/spl_types.h @@ -0,0 +1,230 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include + +#include "common/bit_field.h" +#include "common/common_types.h" + +namespace Service::SPL { + +constexpr size_t AES_128_KEY_SIZE = 0x10; + +namespace Smc { + +enum class FunctionId : u32 { + SetConfig = 0xC3000401, + GetConfig = 0xC3000002, + GetResult = 0xC3000003, + GetResultData = 0xC3000404, + ModularExponentiate = 0xC3000E05, + GenerateRandomBytes = 0xC3000006, + GenerateAesKek = 0xC3000007, + LoadAesKey = 0xC3000008, + ComputeAes = 0xC3000009, + GenerateSpecificAesKey = 0xC300000A, + ComputeCmac = 0xC300040B, + ReencryptDeviceUniqueData = 0xC300D60C, + DecryptDeviceUniqueData = 0xC300100D, + + ModularExponentiateWithStorageKey = 0xC300060F, + PrepareEsDeviceUniqueKey = 0xC3000610, + LoadPreparedAesKey = 0xC3000011, + PrepareCommonEsTitleKey = 0xC3000012, + + // Deprecated functions. + LoadEsDeviceKey = 0xC300100C, + DecryptAndStoreGcKey = 0xC300100E, + + // Atmosphere functions. + AtmosphereIramCopy = 0xF0000201, + AtmosphereReadWriteRegister = 0xF0000002, + + AtmosphereGetEmummcConfig = 0xF0000404, +}; + +enum class CipherMode { + CbcEncrypt = 0, + CbcDecrypt = 1, + Ctr = 2, +}; + +enum class DeviceUniqueDataMode { + DecryptDeviceUniqueData = 0, + DecryptAndStoreGcKey = 1, + DecryptAndStoreEsDeviceKey = 2, + DecryptAndStoreSslKey = 3, + DecryptAndStoreDrmDeviceCertKey = 4, +}; + +enum class ModularExponentiateWithStorageKeyMode { + Gc = 0, + Ssl = 1, + DrmDeviceCert = 2, +}; + +enum class EsCommonKeyType { + TitleKey = 0, + ArchiveKey = 1, +}; + +struct AsyncOperationKey { + u64 value; +}; + +} // namespace Smc + +enum class HardwareType { + Icosa = 0, + Copper = 1, + Hoag = 2, + Iowa = 3, + Calcio = 4, + Aula = 5, +}; + +enum class SocType { + Erista = 0, + Mariko = 1, +}; + +enum class HardwareState { + Development = 0, + Production = 1, +}; + +enum class MemoryArrangement { + Standard = 0, + StandardForAppletDev = 1, + StandardForSystemDev = 2, + Expanded = 3, + ExpandedForAppletDev = 4, + + // Note: Dynamic is not official. + // Atmosphere uses it to maintain compatibility with firmwares prior to 6.0.0, + // which removed the explicit retrieval of memory arrangement from PM. + Dynamic = 5, + Count, +}; + +enum class BootReason { + Unknown = 0, + AcOk = 1, + OnKey = 2, + RtcAlarm1 = 3, + RtcAlarm2 = 4, +}; + +struct BootReasonValue { + union { + u32 value{}; + + BitField<0, 8, u32> power_intr; + BitField<8, 8, u32> rtc_intr; + BitField<16, 8, u32> nv_erc; + BitField<24, 8, u32> boot_reason; + }; +}; +static_assert(sizeof(BootReasonValue) == sizeof(u32), "BootReasonValue definition!"); + +struct AesKey { + std::array data64{}; + + std::span AsBytes() { + return std::span{reinterpret_cast(data64.data()), AES_128_KEY_SIZE}; + } + + std::span AsBytes() const { + return std::span{reinterpret_cast(data64.data()), AES_128_KEY_SIZE}; + } +}; +static_assert(sizeof(AesKey) == AES_128_KEY_SIZE, "AesKey definition!"); + +struct IvCtr { + std::array data64{}; + + std::span AsBytes() { + return std::span{reinterpret_cast(data64.data()), AES_128_KEY_SIZE}; + } + + std::span AsBytes() const { + return std::span{reinterpret_cast(data64.data()), AES_128_KEY_SIZE}; + } +}; +static_assert(sizeof(AesKey) == AES_128_KEY_SIZE, "IvCtr definition!"); + +struct Cmac { + std::array data64{}; + + std::span AsBytes() { + return std::span{reinterpret_cast(data64.data()), AES_128_KEY_SIZE}; + } + + std::span AsBytes() const { + return std::span{reinterpret_cast(data64.data()), AES_128_KEY_SIZE}; + } +}; +static_assert(sizeof(AesKey) == AES_128_KEY_SIZE, "Cmac definition!"); + +struct AccessKey { + std::array data64{}; + + std::span AsBytes() { + return std::span{reinterpret_cast(data64.data()), AES_128_KEY_SIZE}; + } + + std::span AsBytes() const { + return std::span{reinterpret_cast(data64.data()), AES_128_KEY_SIZE}; + } +}; +static_assert(sizeof(AesKey) == AES_128_KEY_SIZE, "AccessKey definition!"); + +struct KeySource { + std::array data64{}; + + std::span AsBytes() { + return std::span{reinterpret_cast(data64.data()), AES_128_KEY_SIZE}; + } + + std::span AsBytes() const { + return std::span{reinterpret_cast(data64.data()), AES_128_KEY_SIZE}; + } +}; +static_assert(sizeof(AesKey) == AES_128_KEY_SIZE, "KeySource definition!"); + +enum class ConfigItem : u32 { + // Standard config items. + DisableProgramVerification = 1, + DramId = 2, + SecurityEngineInterruptNumber = 3, + FuseVersion = 4, + HardwareType = 5, + HardwareState = 6, + IsRecoveryBoot = 7, + DeviceId = 8, + BootReason = 9, + MemoryMode = 10, + IsDevelopmentFunctionEnabled = 11, + KernelConfiguration = 12, + IsChargerHiZModeEnabled = 13, + QuestState = 14, + RegulatorType = 15, + DeviceUniqueKeyGeneration = 16, + Package2Hash = 17, + + // Extension config items for exosphere. + ExosphereApiVersion = 65000, + ExosphereNeedsReboot = 65001, + ExosphereNeedsShutdown = 65002, + ExosphereGitCommitHash = 65003, + ExosphereHasRcmBugPatch = 65004, + ExosphereBlankProdInfo = 65005, + ExosphereAllowCalWrites = 65006, + ExosphereEmummcType = 65007, + ExospherePayloadAddress = 65008, + ExosphereLogConfiguration = 65009, + ExosphereForceEnableUsb30 = 65010, +}; + +} // namespace Service::SPL diff --git a/src/core/hle/service/time/time_zone_content_manager.cpp b/src/core/hle/service/time/time_zone_content_manager.cpp index bf4402308..c634b6abd 100755 --- a/src/core/hle/service/time/time_zone_content_manager.cpp +++ b/src/core/hle/service/time/time_zone_content_manager.cpp @@ -125,7 +125,7 @@ ResultCode TimeZoneContentManager::GetTimeZoneInfoFile(const std::string& locati return ERROR_TIME_NOT_FOUND; } - vfs_file = zoneinfo_dir->GetFile(location_name); + vfs_file = zoneinfo_dir->GetFileRelative(location_name); if (!vfs_file) { LOG_ERROR(Service_Time, "{:016X} has no file \"{}\"! Using default timezone.", time_zone_binary_titleid, location_name); diff --git a/src/input_common/mouse/mouse_input.cpp b/src/input_common/mouse/mouse_input.cpp index a335e6da1..3b052ffb2 100755 --- a/src/input_common/mouse/mouse_input.cpp +++ b/src/input_common/mouse/mouse_input.cpp @@ -2,25 +2,23 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. +#include +#include + #include "common/settings.h" #include "input_common/mouse/mouse_input.h" namespace MouseInput { Mouse::Mouse() { - update_thread = std::thread(&Mouse::UpdateThread, this); + update_thread = std::jthread([this](std::stop_token stop_token) { UpdateThread(stop_token); }); } -Mouse::~Mouse() { - update_thread_running = false; - if (update_thread.joinable()) { - update_thread.join(); - } -} +Mouse::~Mouse() = default; -void Mouse::UpdateThread() { +void Mouse::UpdateThread(std::stop_token stop_token) { constexpr int update_time = 10; - while (update_thread_running) { + while (!stop_token.stop_requested()) { for (MouseInfo& info : mouse_info) { const Common::Vec3f angular_direction{ -info.tilt_direction.y, diff --git a/src/input_common/mouse/mouse_input.h b/src/input_common/mouse/mouse_input.h index 5a971ad67..c8bae99c1 100755 --- a/src/input_common/mouse/mouse_input.h +++ b/src/input_common/mouse/mouse_input.h @@ -6,6 +6,7 @@ #include #include +#include #include #include "common/common_types.h" @@ -85,7 +86,7 @@ public: [[nodiscard]] const MouseData& GetMouseState(std::size_t button) const; private: - void UpdateThread(); + void UpdateThread(std::stop_token stop_token); void UpdateYuzuSettings(); void StopPanning(); @@ -105,12 +106,11 @@ private: u16 buttons{}; u16 toggle_buttons{}; u16 lock_buttons{}; - std::thread update_thread; + std::jthread update_thread; MouseButton last_button{MouseButton::Undefined}; std::array mouse_info; Common::SPSCQueue mouse_queue; bool configuring{false}; - bool update_thread_running{true}; int mouse_panning_timout{}; }; } // namespace MouseInput diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h index 082eb9371..0922533ac 100755 --- a/src/video_core/rasterizer_interface.h +++ b/src/video_core/rasterizer_interface.h @@ -4,10 +4,10 @@ #pragma once -#include #include #include #include +#include #include "common/common_types.h" #include "video_core/engines/fermi_2d.h" #include "video_core/gpu.h" @@ -129,7 +129,7 @@ public: virtual void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {} /// Initialize disk cached resources for the game being emulated - virtual void LoadDiskResources(u64 title_id, const std::atomic_bool& stop_loading, + virtual void LoadDiskResources(u64 title_id, std::stop_token stop_loading, const DiskResourceLoadCallback& callback) {} /// Grant access to the Guest Driver Profile for recording/obtaining info on the guest driver. diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h index 320ee8d30..63d8ad42a 100755 --- a/src/video_core/renderer_base.h +++ b/src/video_core/renderer_base.h @@ -42,6 +42,8 @@ public: [[nodiscard]] virtual RasterizerInterface* ReadRasterizer() = 0; + [[nodiscard]] virtual std::string GetDeviceVendor() const = 0; + // Getter/setter functions: // ------------------------ diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp index 3f4532ca7..3b00614e7 100755 --- a/src/video_core/renderer_opengl/gl_device.cpp +++ b/src/video_core/renderer_opengl/gl_device.cpp @@ -202,13 +202,13 @@ Device::Device() { LOG_ERROR(Render_OpenGL, "OpenGL 4.6 is not available"); throw std::runtime_error{"Insufficient version"}; } - const std::string_view vendor = reinterpret_cast(glGetString(GL_VENDOR)); + vendor_name = reinterpret_cast(glGetString(GL_VENDOR)); const std::string_view version = reinterpret_cast(glGetString(GL_VERSION)); const std::vector extensions = GetExtensions(); - const bool is_nvidia = vendor == "NVIDIA Corporation"; - const bool is_amd = vendor == "ATI Technologies Inc."; - const bool is_intel = vendor == "Intel"; + const bool is_nvidia = vendor_name == "NVIDIA Corporation"; + const bool is_amd = vendor_name == "ATI Technologies Inc."; + const bool is_intel = vendor_name == "Intel"; #ifdef __unix__ const bool is_linux = true; @@ -275,6 +275,56 @@ Device::Device() { } } +std::string Device::GetVendorName() const { + if (vendor_name == "NVIDIA Corporation") { + return "NVIDIA"; + } + if (vendor_name == "ATI Technologies Inc.") { + return "AMD"; + } + if (vendor_name == "Intel") { + // For Mesa, `Intel` is an overloaded vendor string that could mean crocus or iris. + // Simply return `INTEL` for those as well as the Windows driver. + return "INTEL"; + } + if (vendor_name == "Intel Open Source Technology Center") { + return "I965"; + } + if (vendor_name == "Mesa Project") { + return "I915"; + } + if (vendor_name == "Mesa/X.org") { + // This vendor string is overloaded between llvmpipe, softpipe, and virgl, so just return + // MESA instead of one of those driver names. + return "MESA"; + } + if (vendor_name == "AMD") { + return "RADEONSI"; + } + if (vendor_name == "nouveau") { + return "NOUVEAU"; + } + if (vendor_name == "X.Org") { + return "R600"; + } + if (vendor_name == "Collabora Ltd") { + return "ZINK"; + } + if (vendor_name == "Intel Corporation") { + return "OPENSWR"; + } + if (vendor_name == "Microsoft Corporation") { + return "D3D12"; + } + if (vendor_name == "NVIDIA") { + // Mesa's tegra driver reports `NVIDIA`. Only present in this list because the default + // strategy would have returned `NVIDIA` here for this driver, the same result as the + // proprietary driver. + return "TEGRA"; + } + return vendor_name; +} + Device::Device(std::nullptr_t) { max_uniform_buffers.fill(std::numeric_limits::max()); uniform_buffer_alignment = 4; diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h index f24bd0c7b..2c2b13767 100755 --- a/src/video_core/renderer_opengl/gl_device.h +++ b/src/video_core/renderer_opengl/gl_device.h @@ -22,6 +22,8 @@ public: explicit Device(); explicit Device(std::nullptr_t); + [[nodiscard]] std::string GetVendorName() const; + u32 GetMaxUniformBuffers(Tegra::Engines::ShaderType shader_type) const noexcept { return max_uniform_buffers[static_cast(shader_type)]; } @@ -130,6 +132,7 @@ private: static bool TestVariableAoffi(); static bool TestPreciseBug(); + std::string vendor_name; std::array max_uniform_buffers{}; std::array base_bindings{}; size_t uniform_buffer_alignment{}; diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 69e50a275..24c4914de 100755 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -351,7 +351,7 @@ void RasterizerOpenGL::SetupShaders(bool is_indexed) { } } -void RasterizerOpenGL::LoadDiskResources(u64 title_id, const std::atomic_bool& stop_loading, +void RasterizerOpenGL::LoadDiskResources(u64 title_id, std::stop_token stop_loading, const VideoCore::DiskResourceLoadCallback& callback) { shader_cache.LoadDiskCache(title_id, stop_loading, callback); } diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index f73addb19..6ceee14ab 100755 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -96,7 +96,7 @@ public: const Tegra::Engines::Fermi2D::Config& copy_config) override; bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr, u32 pixel_stride) override; - void LoadDiskResources(u64 title_id, const std::atomic_bool& stop_loading, + void LoadDiskResources(u64 title_id, std::stop_token stop_loading, const VideoCore::DiskResourceLoadCallback& callback) override; /// Returns true when there are commands queued to the OpenGL server. diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 5cf7cd151..5a01c59ec 100755 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -331,7 +331,7 @@ ShaderCacheOpenGL::ShaderCacheOpenGL(RasterizerOpenGL& rasterizer_, ShaderCacheOpenGL::~ShaderCacheOpenGL() = default; -void ShaderCacheOpenGL::LoadDiskCache(u64 title_id, const std::atomic_bool& stop_loading, +void ShaderCacheOpenGL::LoadDiskCache(u64 title_id, std::stop_token stop_loading, const VideoCore::DiskResourceLoadCallback& callback) { disk_cache.BindTitleID(title_id); const std::optional transferable = disk_cache.LoadTransferable(); @@ -372,7 +372,7 @@ void ShaderCacheOpenGL::LoadDiskCache(u64 title_id, const std::atomic_bool& stop const auto scope = context->Acquire(); for (std::size_t i = begin; i < end; ++i) { - if (stop_loading) { + if (stop_loading.stop_requested()) { return; } const auto& entry = (*transferable)[i]; @@ -435,7 +435,7 @@ void ShaderCacheOpenGL::LoadDiskCache(u64 title_id, const std::atomic_bool& stop precompiled_cache_altered = true; return; } - if (stop_loading) { + if (stop_loading.stop_requested()) { return; } diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h index 2aed0697e..b30308b6f 100755 --- a/src/video_core/renderer_opengl/gl_shader_cache.h +++ b/src/video_core/renderer_opengl/gl_shader_cache.h @@ -127,7 +127,7 @@ public: ~ShaderCacheOpenGL() override; /// Loads disk cache for the current game - void LoadDiskCache(u64 title_id, const std::atomic_bool& stop_loading, + void LoadDiskCache(u64 title_id, std::stop_token stop_loading, const VideoCore::DiskResourceLoadCallback& callback); /// Gets the current specified shader stage program diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index cc19a110f..0b66f8332 100755 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h @@ -70,6 +70,10 @@ public: return &rasterizer; } + [[nodiscard]] std::string GetDeviceVendor() const override { + return device.GetVendorName(); + } + private: /// Initializes the OpenGL state and creates persistent objects. void InitOpenGLObjects(); diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h index 72071316c..d7d17e110 100755 --- a/src/video_core/renderer_vulkan/renderer_vulkan.h +++ b/src/video_core/renderer_vulkan/renderer_vulkan.h @@ -47,6 +47,10 @@ public: return &rasterizer; } + [[nodiscard]] std::string GetDeviceVendor() const override { + return device.GetDriverName(); + } + private: void Report() const; diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 6ee654dc1..e7f8478b4 100755 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -344,6 +344,7 @@ private: bool has_deleted_images = false; u64 total_used_memory = 0; + u64 minimum_memory; u64 expected_memory; u64 critical_memory; @@ -396,10 +397,12 @@ TextureCache

::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface& const u64 possible_critical_memory = (device_memory * 6) / 10; expected_memory = std::max(possible_expected_memory, DEFAULT_EXPECTED_MEMORY); critical_memory = std::max(possible_critical_memory, DEFAULT_CRITICAL_MEMORY); + minimum_memory = 0; } else { // on OGL we can be more conservatives as the driver takes care. expected_memory = DEFAULT_EXPECTED_MEMORY + Common::Size_512_MB; critical_memory = DEFAULT_CRITICAL_MEMORY + Common::Size_1_GB; + minimum_memory = expected_memory; } } @@ -470,7 +473,7 @@ void TextureCache

::RunGarbageCollector() { template void TextureCache

::TickFrame() { - if (Settings::values.use_caches_gc.GetValue()) { + if (Settings::values.use_caches_gc.GetValue() && total_used_memory > minimum_memory) { RunGarbageCollector(); } sentenced_images.Tick(); diff --git a/src/video_core/vulkan_common/nsight_aftermath_tracker.cpp b/src/video_core/vulkan_common/nsight_aftermath_tracker.cpp index f0ee76519..758c038ba 100755 --- a/src/video_core/vulkan_common/nsight_aftermath_tracker.cpp +++ b/src/video_core/vulkan_common/nsight_aftermath_tracker.cpp @@ -50,7 +50,7 @@ NsightAftermathTracker::NsightAftermathTracker() { } dump_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::LogDir) / "gpucrash"; - void(Common::FS::RemoveDirRecursively(dump_dir)); + Common::FS::RemoveDirRecursively(dump_dir); if (!Common::FS::CreateDir(dump_dir)) { LOG_ERROR(Render_Vulkan, "Failed to create Nsight Aftermath dump directory"); return; diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 707a8b8fb..16a2d68e8 100755 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -532,6 +532,27 @@ bool Device::IsFormatSupported(VkFormat wanted_format, VkFormatFeatureFlags want return (supported_usage & wanted_usage) == wanted_usage; } +std::string Device::GetDriverName() const { + switch (driver_id) { + case VK_DRIVER_ID_AMD_PROPRIETARY: + return "AMD"; + case VK_DRIVER_ID_AMD_OPEN_SOURCE: + return "AMDVLK"; + case VK_DRIVER_ID_MESA_RADV: + return "RADV"; + case VK_DRIVER_ID_NVIDIA_PROPRIETARY: + return "NVIDIA"; + case VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS: + return "INTEL"; + case VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA: + return "ANV"; + case VK_DRIVER_ID_MESA_LLVMPIPE: + return "LAVAPIPE"; + default: + return vendor_name; + } +} + void Device::CheckSuitability(bool requires_swapchain) const { std::bitset available_extensions; bool has_swapchain = false; diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index a1aba973b..705c07e3e 100755 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -45,6 +45,9 @@ public: /// Reports a shader to Nsight Aftermath. void SaveShader(const std::vector& spirv) const; + /// Returns the name of the VkDriverId reported from Vulkan. + std::string GetDriverName() const; + /// Returns the dispatch loader with direct function pointers of the device. const vk::DeviceDispatch& GetDispatchLoader() const { return dld; diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 86495803e..7524e3c40 100755 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -51,11 +51,11 @@ void EmuThread::run() { Common::SetCurrentThreadName(name.c_str()); auto& system = Core::System::GetInstance(); + auto& gpu = system.GPU(); + auto stop_token = stop_source.get_token(); system.RegisterHostThread(); - auto& gpu = system.GPU(); - // Main process has been loaded. Make the context current to this thread and begin GPU and CPU // execution. gpu.Start(); @@ -65,7 +65,7 @@ void EmuThread::run() { emit LoadProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0); system.Renderer().ReadRasterizer()->LoadDiskResources( - system.CurrentProcess()->GetTitleID(), stop_run, + system.CurrentProcess()->GetTitleID(), stop_token, [this](VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total) { emit LoadProgress(stage, value, total); }); @@ -78,7 +78,7 @@ void EmuThread::run() { // so that the DebugModeLeft signal can be emitted before the // next execution step bool was_active = false; - while (!stop_run) { + while (!stop_token.stop_requested()) { if (running) { if (was_active) { emit DebugModeLeft(); @@ -100,7 +100,7 @@ void EmuThread::run() { } running_guard = false; - if (!stop_run) { + if (!stop_token.stop_requested()) { was_active = true; emit DebugModeEntered(); } @@ -108,7 +108,7 @@ void EmuThread::run() { UNIMPLEMENTED(); } else { std::unique_lock lock{running_mutex}; - running_cv.wait(lock, [this] { return IsRunning() || exec_step || stop_run; }); + running_cv.wait(lock, stop_token, [this] { return IsRunning() || exec_step; }); } } diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h index acfe2bc8c..402dd2ee1 100755 --- a/src/yuzu/bootmanager.h +++ b/src/yuzu/bootmanager.h @@ -89,16 +89,16 @@ public: * Requests for the emulation thread to stop running */ void RequestStop() { - stop_run = true; + stop_source.request_stop(); SetRunning(false); } private: bool exec_step = false; bool running = false; - std::atomic_bool stop_run{false}; + std::stop_source stop_source; std::mutex running_mutex; - std::condition_variable running_cv; + std::condition_variable_any running_cv; Common::Event running_wait{}; std::atomic_bool running_guard{false}; diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp index a1d434aca..8c00eec59 100755 --- a/src/yuzu/configuration/configure_per_game.cpp +++ b/src/yuzu/configuration/configure_per_game.cpp @@ -47,6 +47,8 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id, const std::str ui->setupUi(this); setFocusPolicy(Qt::ClickFocus); setWindowTitle(tr("Properties")); + // remove Help question mark button from the title bar + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); ui->addonsTab->SetTitleId(title_id); diff --git a/src/yuzu/configuration/configure_per_game.ui b/src/yuzu/configuration/configure_per_game.ui index adf6d0b39..7da14146b 100755 --- a/src/yuzu/configuration/configure_per_game.ui +++ b/src/yuzu/configuration/configure_per_game.ui @@ -6,10 +6,15 @@ 0 0 - 800 + 900 600 + + + 900 + + Dialog diff --git a/src/yuzu/configuration/configure_per_game_addons.cpp b/src/yuzu/configuration/configure_per_game_addons.cpp index 9b709d405..ebb0f411c 100755 --- a/src/yuzu/configuration/configure_per_game_addons.cpp +++ b/src/yuzu/configuration/configure_per_game_addons.cpp @@ -79,8 +79,8 @@ void ConfigurePerGameAddons::ApplyConfiguration() { std::sort(disabled_addons.begin(), disabled_addons.end()); std::sort(current.begin(), current.end()); if (disabled_addons != current) { - void(Common::FS::RemoveFile(Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) / - "game_list" / fmt::format("{:016X}.pv.txt", title_id))); + Common::FS::RemoveFile(Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) / + "game_list" / fmt::format("{:016X}.pv.txt", title_id)); } Settings::values.disabled_addons[title_id] = disabled_addons; diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index da956c99b..e44907be8 100755 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp @@ -521,7 +521,9 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri QAction* remove_custom_config = remove_menu->addAction(tr("Remove Custom Configuration")); remove_menu->addSeparator(); QAction* remove_all_content = remove_menu->addAction(tr("Remove All Installed Contents")); - QAction* dump_romfs = context_menu.addAction(tr("Dump RomFS")); + QMenu* dump_romfs_menu = context_menu.addMenu(tr("Dump RomFS")); + QAction* dump_romfs = dump_romfs_menu->addAction(tr("Dump RomFS")); + QAction* dump_romfs_sdmc = dump_romfs_menu->addAction(tr("Dump RomFS to SDMC")); QAction* copy_tid = context_menu.addAction(tr("Copy Title ID to Clipboard")); QAction* navigate_to_gamedb_entry = context_menu.addAction(tr("Navigate to GameDB entry")); context_menu.addSeparator(); @@ -570,8 +572,12 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri connect(remove_custom_config, &QAction::triggered, [this, program_id, path]() { emit RemoveFileRequested(program_id, GameListRemoveTarget::CustomConfiguration, path); }); - connect(dump_romfs, &QAction::triggered, - [this, program_id, path]() { emit DumpRomFSRequested(program_id, path); }); + connect(dump_romfs, &QAction::triggered, [this, program_id, path]() { + emit DumpRomFSRequested(program_id, path, DumpRomFSTarget::Normal); + }); + connect(dump_romfs_sdmc, &QAction::triggered, [this, program_id, path]() { + emit DumpRomFSRequested(program_id, path, DumpRomFSTarget::SDMC); + }); connect(copy_tid, &QAction::triggered, [this, program_id]() { emit CopyTIDRequested(program_id); }); connect(navigate_to_gamedb_entry, &QAction::triggered, [this, program_id]() { diff --git a/src/yuzu/game_list.h b/src/yuzu/game_list.h index b630e34ff..50402da51 100755 --- a/src/yuzu/game_list.h +++ b/src/yuzu/game_list.h @@ -45,6 +45,11 @@ enum class GameListRemoveTarget { CustomConfiguration, }; +enum class DumpRomFSTarget { + Normal, + SDMC, +}; + enum class InstalledEntryType { Game, Update, @@ -92,7 +97,7 @@ signals: void RemoveInstalledEntryRequested(u64 program_id, InstalledEntryType type); void RemoveFileRequested(u64 program_id, GameListRemoveTarget target, const std::string& game_path); - void DumpRomFSRequested(u64 program_id, const std::string& game_path); + void DumpRomFSRequested(u64 program_id, const std::string& game_path, DumpRomFSTarget target); void CopyTIDRequested(u64 program_id); void NavigateToGamedbEntryRequested(u64 program_id, const CompatibilityList& compatibility_list); diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index d4c7d2c0b..46496c2de 100755 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -104,6 +104,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual #include "input_common/main.h" #include "util/overlay_dialog.h" #include "video_core/gpu.h" +#include "video_core/renderer_base.h" #include "video_core/shader_notify.h" #include "yuzu/about_dialog.h" #include "yuzu/bootmanager.h" @@ -194,10 +195,10 @@ static void RemoveCachedContents() { const auto offline_legal_information = cache_dir / "offline_web_applet_legal_information"; const auto offline_system_data = cache_dir / "offline_web_applet_system_data"; - void(Common::FS::RemoveDirRecursively(offline_fonts)); - void(Common::FS::RemoveDirRecursively(offline_manual)); - void(Common::FS::RemoveDirRecursively(offline_legal_information)); - void(Common::FS::RemoveDirRecursively(offline_system_data)); + Common::FS::RemoveDirRecursively(offline_fonts); + Common::FS::RemoveDirRecursively(offline_manual); + Common::FS::RemoveDirRecursively(offline_legal_information); + Common::FS::RemoveDirRecursively(offline_system_data); } GMainWindow::GMainWindow() @@ -1422,7 +1423,8 @@ void GMainWindow::BootGame(const QString& filename, std::size_t program_index, S std::filesystem::path{filename.toStdU16String()}.filename()); } LOG_INFO(Frontend, "Booting game: {:016X} | {} | {}", title_id, title_name, title_version); - UpdateWindowTitle(title_name, title_version); + const auto gpu_vendor = system.GPU().Renderer().GetDeviceVendor(); + UpdateWindowTitle(title_name, title_version, gpu_vendor); loading_screen->Prepare(system.GetAppLoader()); loading_screen->show(); @@ -1743,8 +1745,8 @@ void GMainWindow::OnGameListRemoveInstalledEntry(u64 program_id, InstalledEntryT RemoveAddOnContent(program_id, entry_type); break; } - void(Common::FS::RemoveDirRecursively(Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) / - "game_list")); + Common::FS::RemoveDirRecursively(Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) / + "game_list"); game_list->PopulateAsync(UISettings::values.game_dirs); } @@ -1876,7 +1878,8 @@ void GMainWindow::RemoveCustomConfiguration(u64 program_id, const std::string& g } } -void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_path) { +void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_path, + DumpRomFSTarget target) { const auto failed = [this] { QMessageBox::warning(this, tr("RomFS Extraction Failed!"), tr("There was an error copying the RomFS files or the user " @@ -1904,7 +1907,10 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa return; } - const auto dump_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::DumpDir); + const auto dump_dir = + target == DumpRomFSTarget::Normal + ? Common::FS::GetYuzuPath(Common::FS::YuzuPath::DumpDir) + : Common::FS::GetYuzuPath(Common::FS::YuzuPath::SDMCDir) / "atmosphere" / "contents"; const auto romfs_dir = fmt::format("{:016X}/romfs", *romfs_title_id); const auto path = Common::FS::PathToUTF8String(dump_dir / romfs_dir); @@ -2213,8 +2219,8 @@ void GMainWindow::OnMenuInstallToNAND() { : tr("%n file(s) failed to install\n", "", failed_files.size())); QMessageBox::information(this, tr("Install Results"), install_results); - void(Common::FS::RemoveDirRecursively(Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) / - "game_list")); + Common::FS::RemoveDirRecursively(Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) / + "game_list"); game_list->PopulateAsync(UISettings::values.game_dirs); ui.action_Install_File_NAND->setEnabled(true); } @@ -2846,13 +2852,13 @@ void GMainWindow::MigrateConfigFiles() { LOG_INFO(Frontend, "Migrating config file from {} to {}", origin, destination); if (!Common::FS::RenameFile(origin, destination)) { // Delete the old config file if one already exists in the new location. - void(Common::FS::RemoveFile(origin)); + Common::FS::RemoveFile(origin); } } } -void GMainWindow::UpdateWindowTitle(const std::string& title_name, - const std::string& title_version) { +void GMainWindow::UpdateWindowTitle(std::string_view title_name, std::string_view title_version, + std::string_view gpu_vendor) { const auto branch_name = std::string(Common::g_scm_branch); const auto description = std::string(Common::g_scm_desc); const auto build_id = std::string(Common::g_build_id); @@ -2864,7 +2870,8 @@ void GMainWindow::UpdateWindowTitle(const std::string& title_name, if (title_name.empty()) { setWindowTitle(QString::fromStdString(window_title)); } else { - const auto run_title = fmt::format("{} | {} | {}", window_title, title_name, title_version); + const auto run_title = + fmt::format("{} | {} | {} | {}", window_title, title_name, title_version, gpu_vendor); setWindowTitle(QString::fromStdString(run_title)); } } @@ -3040,9 +3047,9 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) { const auto keys_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::KeysDir); - void(Common::FS::RemoveFile(keys_dir / "prod.keys_autogenerated")); - void(Common::FS::RemoveFile(keys_dir / "console.keys_autogenerated")); - void(Common::FS::RemoveFile(keys_dir / "title.keys_autogenerated")); + Common::FS::RemoveFile(keys_dir / "prod.keys_autogenerated"); + Common::FS::RemoveFile(keys_dir / "console.keys_autogenerated"); + Common::FS::RemoveFile(keys_dir / "title.keys_autogenerated"); } Core::Crypto::KeyManager& keys = Core::Crypto::KeyManager::Instance(); diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 11f152cbe..45c8310e1 100755 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -34,6 +34,7 @@ class QProgressDialog; class WaitTreeWidget; enum class GameListOpenTarget; enum class GameListRemoveTarget; +enum class DumpRomFSTarget; enum class InstalledEntryType; class GameListPlaceholder; @@ -244,7 +245,7 @@ private slots: void OnGameListRemoveInstalledEntry(u64 program_id, InstalledEntryType type); void OnGameListRemoveFile(u64 program_id, GameListRemoveTarget target, const std::string& game_path); - void OnGameListDumpRomFS(u64 program_id, const std::string& game_path); + void OnGameListDumpRomFS(u64 program_id, const std::string& game_path, DumpRomFSTarget target); void OnGameListCopyTID(u64 program_id); void OnGameListNavigateToGamedbEntry(u64 program_id, const CompatibilityList& compatibility_list); @@ -287,8 +288,8 @@ private: InstallResult InstallNSPXCI(const QString& filename); InstallResult InstallNCA(const QString& filename); void MigrateConfigFiles(); - void UpdateWindowTitle(const std::string& title_name = {}, - const std::string& title_version = {}); + void UpdateWindowTitle(std::string_view title_name = {}, std::string_view title_version = {}, + std::string_view gpu_vendor = {}); void UpdateStatusBar(); void UpdateStatusButtons(); void UpdateUISettings(); diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index 584967f5c..50e388312 100755 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp @@ -219,7 +219,7 @@ int main(int argc, char** argv) { system.GPU().Start(); system.Renderer().ReadRasterizer()->LoadDiskResources( - system.CurrentProcess()->GetTitleID(), false, + system.CurrentProcess()->GetTitleID(), std::stop_token{}, [](VideoCore::LoadCallbackStage, size_t value, size_t total) {}); void(system.Run());