diff options
Diffstat (limited to '')
33 files changed, 362 insertions, 137 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index c33910ade..30d2f7df6 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -627,8 +627,8 @@ add_library(core STATIC hle/service/nfp/nfp_interface.h hle/service/nfp/nfp_result.h hle/service/nfp/nfp_types.h - hle/service/ngct/ngct.cpp - hle/service/ngct/ngct.h + hle/service/ngc/ngc.cpp + hle/service/ngc/ngc.h hle/service/nifm/nifm.cpp hle/service/nifm/nifm.h hle/service/nim/nim.cpp @@ -864,6 +864,8 @@ add_library(core STATIC telemetry_session.h tools/freezer.cpp tools/freezer.h + tools/renderdoc.cpp + tools/renderdoc.h ) if (MSVC) @@ -879,6 +881,7 @@ else() -Werror=conversion -Wno-sign-conversion + -Wno-cast-function-type $<$<CXX_COMPILER_ID:Clang>:-fsized-deallocation> ) @@ -887,7 +890,7 @@ endif() create_target_directory_groups(core) target_link_libraries(core PUBLIC common PRIVATE audio_core network video_core nx_tzdb) -target_link_libraries(core PUBLIC Boost::headers PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls Opus::opus) +target_link_libraries(core PUBLIC Boost::headers PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls Opus::opus renderdoc) if (MINGW) target_link_libraries(core PRIVATE ${MSWSOCK_LIBRARY}) endif() diff --git a/src/core/core.cpp b/src/core/core.cpp index 2d6e61398..e8300cd05 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -51,6 +51,7 @@ #include "core/reporter.h" #include "core/telemetry_session.h" #include "core/tools/freezer.h" +#include "core/tools/renderdoc.h" #include "network/network.h" #include "video_core/host1x/host1x.h" #include "video_core/renderer_base.h" @@ -281,6 +282,10 @@ struct System::Impl { microprofile_cpu[2] = MICROPROFILE_TOKEN(ARM_CPU2); microprofile_cpu[3] = MICROPROFILE_TOKEN(ARM_CPU3); + if (Settings::values.enable_renderdoc_hotkey) { + renderdoc_api = std::make_unique<Tools::RenderdocAPI>(); + } + LOG_DEBUG(Core, "Initialized OK"); return SystemResultStatus::Success; @@ -521,6 +526,8 @@ struct System::Impl { std::unique_ptr<Tools::Freezer> memory_freezer; std::array<u8, 0x20> build_id{}; + std::unique_ptr<Tools::RenderdocAPI> renderdoc_api; + /// Frontend applets Service::AM::Applets::AppletManager applet_manager; @@ -1024,6 +1031,10 @@ const Network::RoomNetwork& System::GetRoomNetwork() const { return impl->room_network; } +Tools::RenderdocAPI& System::GetRenderdocAPI() { + return *impl->renderdoc_api; +} + void System::RunServer(std::unique_ptr<Service::ServerManager>&& server_manager) { return impl->kernel.RunServer(std::move(server_manager)); } diff --git a/src/core/core.h b/src/core/core.h index fba312125..df20f26f3 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -102,6 +102,10 @@ namespace Network { class RoomNetwork; } +namespace Tools { +class RenderdocAPI; +} + namespace Core { class ARM_Interface; @@ -413,6 +417,8 @@ public: /// Gets an immutable reference to the Room Network. [[nodiscard]] const Network::RoomNetwork& GetRoomNetwork() const; + [[nodiscard]] Tools::RenderdocAPI& GetRenderdocAPI(); + void SetExitLocked(bool locked); bool GetExitLocked() const; diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp index e13c5cdc7..43a3c5ffd 100644 --- a/src/core/crypto/key_manager.cpp +++ b/src/core/crypto/key_manager.cpp @@ -724,14 +724,14 @@ void KeyManager::LoadFromFile(const std::filesystem::path& file_path, bool is_ti continue; } - const auto index = std::stoul(out[0].substr(8, 2), nullptr, 16); + const auto index = std::strtoul(out[0].substr(8, 2).c_str(), nullptr, 16); keyblobs[index] = Common::HexStringToArray<0x90>(out[1]); } else if (out[0].compare(0, 18, "encrypted_keyblob_") == 0) { if (!ValidCryptoRevisionString(out[0], 18, 2)) { continue; } - const auto index = std::stoul(out[0].substr(18, 2), nullptr, 16); + const auto index = std::strtoul(out[0].substr(18, 2).c_str(), nullptr, 16); encrypted_keyblobs[index] = Common::HexStringToArray<0xB0>(out[1]); } else if (out[0].compare(0, 20, "eticket_extended_kek") == 0) { eticket_extended_kek = Common::HexStringToArray<576>(out[1]); @@ -750,7 +750,7 @@ void KeyManager::LoadFromFile(const std::filesystem::path& file_path, bool is_ti } if (out[0].compare(0, kv.second.size(), kv.second) == 0) { const auto index = - std::stoul(out[0].substr(kv.second.size(), 2), nullptr, 16); + std::strtoul(out[0].substr(kv.second.size(), 2).c_str(), nullptr, 16); const auto sub = kv.first.second; if (sub == 0) { s128_keys[{kv.first.first, index, 0}] = @@ -770,7 +770,7 @@ void KeyManager::LoadFromFile(const std::filesystem::path& file_path, bool is_ti const auto& match = kak_names[j]; if (out[0].compare(0, std::strlen(match), match) == 0) { const auto index = - std::stoul(out[0].substr(std::strlen(match), 2), nullptr, 16); + std::strtoul(out[0].substr(std::strlen(match), 2).c_str(), nullptr, 16); s128_keys[{S128KeyType::KeyArea, index, j}] = Common::HexStringToArray<16>(out[1]); } diff --git a/src/core/file_sys/ips_layer.cpp b/src/core/file_sys/ips_layer.cpp index efdf18cee..7be1322cc 100644 --- a/src/core/file_sys/ips_layer.cpp +++ b/src/core/file_sys/ips_layer.cpp @@ -165,7 +165,7 @@ static std::string EscapeStringSequences(std::string in) { void IPSwitchCompiler::ParseFlag(const std::string& line) { if (StartsWith(line, "@flag offset_shift ")) { // Offset Shift Flag - offset_shift = std::stoll(line.substr(19), nullptr, 0); + offset_shift = std::strtoll(line.substr(19).c_str(), nullptr, 0); } else if (StartsWith(line, "@little-endian")) { // Set values to read as little endian is_little_endian = true; @@ -263,7 +263,7 @@ void IPSwitchCompiler::Parse() { // 11 - 8 hex digit offset + space + minimum two digit overwrite val if (patch_line.length() < 11) break; - auto offset = std::stoul(patch_line.substr(0, 8), nullptr, 16); + auto offset = std::strtoul(patch_line.substr(0, 8).c_str(), nullptr, 16); offset += static_cast<unsigned long>(offset_shift); std::vector<u8> replace; diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index a4baddb15..8e475f25a 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp @@ -294,11 +294,11 @@ std::vector<u8> PatchManager::PatchNSO(const std::vector<u8>& nso, const std::st return out; } -bool PatchManager::HasNSOPatch(const BuildID& build_id_) const { +bool PatchManager::HasNSOPatch(const BuildID& build_id_, std::string_view name) const { const auto build_id_raw = Common::HexToString(build_id_); const auto build_id = build_id_raw.substr(0, build_id_raw.find_last_not_of('0') + 1); - LOG_INFO(Loader, "Querying NSO patch existence for build_id={}", build_id); + LOG_INFO(Loader, "Querying NSO patch existence for build_id={}, name={}", build_id, name); const auto load_dir = fs_controller.GetModificationLoadRoot(title_id); if (load_dir == nullptr) { diff --git a/src/core/file_sys/patch_manager.h b/src/core/file_sys/patch_manager.h index adcde7b7d..03e9c7301 100644 --- a/src/core/file_sys/patch_manager.h +++ b/src/core/file_sys/patch_manager.h @@ -52,7 +52,7 @@ public: // Checks to see if PatchNSO() will have any effect given the NSO's build ID. // Used to prevent expensive copies in NSO loader. - [[nodiscard]] bool HasNSOPatch(const BuildID& build_id) const; + [[nodiscard]] bool HasNSOPatch(const BuildID& build_id, std::string_view name) const; // Creates a CheatList object with all [[nodiscard]] std::vector<Core::Memory::CheatEntry> CreateCheatList( diff --git a/src/core/hid/hid_core.cpp b/src/core/hid/hid_core.cpp index 7d6373414..cf53c04d9 100644 --- a/src/core/hid/hid_core.cpp +++ b/src/core/hid/hid_core.cpp @@ -154,6 +154,14 @@ NpadIdType HIDCore::GetFirstDisconnectedNpadId() const { return NpadIdType::Player1; } +void HIDCore::SetLastActiveController(NpadIdType npad_id) { + last_active_controller = npad_id; +} + +NpadIdType HIDCore::GetLastActiveController() const { + return last_active_controller; +} + void HIDCore::EnableAllControllerConfiguration() { player_1->EnableConfiguration(); player_2->EnableConfiguration(); diff --git a/src/core/hid/hid_core.h b/src/core/hid/hid_core.h index 5fe36551e..80abab18b 100644 --- a/src/core/hid/hid_core.h +++ b/src/core/hid/hid_core.h @@ -48,6 +48,12 @@ public: /// Returns the first disconnected npad id NpadIdType GetFirstDisconnectedNpadId() const; + /// Sets the npad id of the last active controller + void SetLastActiveController(NpadIdType npad_id); + + /// Returns the npad id of the last controller that pushed a button + NpadIdType GetLastActiveController() const; + /// Sets all emulated controllers into configuring mode. void EnableAllControllerConfiguration(); @@ -77,6 +83,7 @@ private: std::unique_ptr<EmulatedConsole> console; std::unique_ptr<EmulatedDevices> devices; NpadStyleTag supported_style_tag{NpadStyleSet::All}; + NpadIdType last_active_controller{NpadIdType::Handheld}; }; } // namespace Core::HID diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index 703049ede..4a099286b 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp @@ -96,6 +96,7 @@ Result KProcess::Initialize(KProcess* process, Core::System& system, std::string process->m_is_suspended = false; process->m_schedule_count = 0; process->m_is_handle_table_initialized = false; + process->m_is_hbl = false; // Open a reference to the resource limit. process->m_resource_limit->Open(); @@ -351,12 +352,14 @@ Result KProcess::SetActivity(ProcessActivity activity) { R_SUCCEED(); } -Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size) { +Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size, + bool is_hbl) { m_program_id = metadata.GetTitleID(); m_ideal_core = metadata.GetMainThreadCore(); m_is_64bit_process = metadata.Is64BitProgram(); m_system_resource_size = metadata.GetSystemResourceSize(); m_image_size = code_size; + m_is_hbl = is_hbl; if (metadata.GetAddressSpaceType() == FileSys::ProgramAddressSpaceType::Is39Bit) { // For 39-bit processes, the ASLR region starts at 0x800'0000 and is ~512GiB large. diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h index 4fdeaf11a..146e07a57 100644 --- a/src/core/hle/kernel/k_process.h +++ b/src/core/hle/kernel/k_process.h @@ -338,7 +338,8 @@ public: * @returns ResultSuccess if all relevant metadata was able to be * loaded and parsed. Otherwise, an error code is returned. */ - Result LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size); + Result LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size, + bool is_hbl); /** * Starts the main application thread for this process. @@ -368,6 +369,10 @@ public: return GetProcessId(); } + bool IsHbl() const { + return m_is_hbl; + } + bool IsSignaled() const override; void DoWorkerTaskImpl(); @@ -525,6 +530,7 @@ private: bool m_is_immortal{}; bool m_is_handle_table_initialized{}; bool m_is_initialized{}; + bool m_is_hbl{}; std::atomic<u16> m_num_running_threads{}; diff --git a/src/core/hle/kernel/svc/svc_debug_string.cpp b/src/core/hle/kernel/svc/svc_debug_string.cpp index 4c14ce668..00b65429b 100644 --- a/src/core/hle/kernel/svc/svc_debug_string.cpp +++ b/src/core/hle/kernel/svc/svc_debug_string.cpp @@ -14,7 +14,7 @@ Result OutputDebugString(Core::System& system, u64 address, u64 len) { std::string str(len, '\0'); GetCurrentMemory(system.Kernel()).ReadBlock(address, str.data(), str.size()); - LOG_DEBUG(Debug_Emulated, "{}", str); + LOG_INFO(Debug_Emulated, "{}", str); R_SUCCEED(); } diff --git a/src/core/hle/kernel/svc/svc_exception.cpp b/src/core/hle/kernel/svc/svc_exception.cpp index 580cf2f75..c581c086b 100644 --- a/src/core/hle/kernel/svc/svc_exception.cpp +++ b/src/core/hle/kernel/svc/svc_exception.cpp @@ -3,6 +3,7 @@ #include "core/core.h" #include "core/debugger/debugger.h" +#include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/svc.h" #include "core/hle/kernel/svc_types.h" @@ -107,7 +108,10 @@ void Break(Core::System& system, BreakReason reason, u64 info1, u64 info2) { system.ArmInterface(static_cast<std::size_t>(thread_processor_id)).LogBacktrace(); } - if (system.DebuggerEnabled()) { + const bool is_hbl = GetCurrentProcess(system.Kernel()).IsHbl(); + const bool should_break = is_hbl || !notification_only; + + if (system.DebuggerEnabled() && should_break) { auto* thread = system.Kernel().GetCurrentEmuThread(); system.GetDebugger().NotifyThreadStopped(thread); thread->RequestSuspend(Kernel::SuspendType::Debug); diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index f9c4f9678..8ffdd19e7 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -1386,7 +1386,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_) {25, &IApplicationFunctions::ExtendSaveData, "ExtendSaveData"}, {26, &IApplicationFunctions::GetSaveDataSize, "GetSaveDataSize"}, {27, &IApplicationFunctions::CreateCacheStorage, "CreateCacheStorage"}, - {28, nullptr, "GetSaveDataSizeMax"}, + {28, &IApplicationFunctions::GetSaveDataSizeMax, "GetSaveDataSizeMax"}, {29, nullptr, "GetCacheStorageMax"}, {30, &IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed, "BeginBlockingHomeButtonShortAndLongPressed"}, {31, &IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed, "EndBlockingHomeButtonShortAndLongPressed"}, @@ -1821,6 +1821,18 @@ void IApplicationFunctions::CreateCacheStorage(HLERequestContext& ctx) { rb.PushRaw(resp); } +void IApplicationFunctions::GetSaveDataSizeMax(HLERequestContext& ctx) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + constexpr u64 size_max_normal = 0xFFFFFFF; + constexpr u64 size_max_journal = 0xFFFFFFF; + + IPC::ResponseBuilder rb{ctx, 6}; + rb.Push(ResultSuccess); + rb.Push(size_max_normal); + rb.Push(size_max_journal); +} + void IApplicationFunctions::QueryApplicationPlayStatistics(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index f75a665b2..f86841c60 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h @@ -316,6 +316,7 @@ private: void ExtendSaveData(HLERequestContext& ctx); void GetSaveDataSize(HLERequestContext& ctx); void CreateCacheStorage(HLERequestContext& ctx); + void GetSaveDataSizeMax(HLERequestContext& ctx); void BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx); void EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx); void BeginBlockingHomeButton(HLERequestContext& ctx); diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index c744b0f87..146bb486d 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -193,7 +193,7 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { shared_memory->system_properties.use_minus.Assign(1); shared_memory->system_properties.is_charging_joy_dual.Assign( battery_level.dual.is_charging); - shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::SwitchProController; + shared_memory->applet_footer_type = AppletFooterUiType::SwitchProController; shared_memory->sixaxis_fullkey_properties.is_newly_assigned.Assign(1); break; case Core::HID::NpadStyleIndex::Handheld: @@ -216,8 +216,7 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { shared_memory->system_properties.is_charging_joy_right.Assign( battery_level.right.is_charging); shared_memory->assignment_mode = NpadJoyAssignmentMode::Dual; - shared_memory->applet_nfc_xcd.applet_footer.type = - AppletFooterUiType::HandheldJoyConLeftJoyConRight; + shared_memory->applet_footer_type = AppletFooterUiType::HandheldJoyConLeftJoyConRight; shared_memory->sixaxis_handheld_properties.is_newly_assigned.Assign(1); break; case Core::HID::NpadStyleIndex::JoyconDual: @@ -247,19 +246,19 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { shared_memory->assignment_mode = NpadJoyAssignmentMode::Dual; if (controller.is_dual_left_connected && controller.is_dual_right_connected) { - shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyDual; + shared_memory->applet_footer_type = AppletFooterUiType::JoyDual; shared_memory->fullkey_color.fullkey = body_colors.left; shared_memory->battery_level_dual = battery_level.left.battery_level; shared_memory->system_properties.is_charging_joy_dual.Assign( battery_level.left.is_charging); } else if (controller.is_dual_left_connected) { - shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyDualLeftOnly; + shared_memory->applet_footer_type = AppletFooterUiType::JoyDualLeftOnly; shared_memory->fullkey_color.fullkey = body_colors.left; shared_memory->battery_level_dual = battery_level.left.battery_level; shared_memory->system_properties.is_charging_joy_dual.Assign( battery_level.left.is_charging); } else { - shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyDualRightOnly; + shared_memory->applet_footer_type = AppletFooterUiType::JoyDualRightOnly; shared_memory->fullkey_color.fullkey = body_colors.right; shared_memory->battery_level_dual = battery_level.right.battery_level; shared_memory->system_properties.is_charging_joy_dual.Assign( @@ -278,7 +277,7 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { shared_memory->system_properties.use_minus.Assign(1); shared_memory->system_properties.is_charging_joy_left.Assign( battery_level.left.is_charging); - shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyLeftHorizontal; + shared_memory->applet_footer_type = AppletFooterUiType::JoyLeftHorizontal; shared_memory->sixaxis_left_properties.is_newly_assigned.Assign(1); break; case Core::HID::NpadStyleIndex::JoyconRight: @@ -293,7 +292,7 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { shared_memory->system_properties.use_plus.Assign(1); shared_memory->system_properties.is_charging_joy_right.Assign( battery_level.right.is_charging); - shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyRightHorizontal; + shared_memory->applet_footer_type = AppletFooterUiType::JoyRightHorizontal; shared_memory->sixaxis_right_properties.is_newly_assigned.Assign(1); break; case Core::HID::NpadStyleIndex::GameCube: @@ -314,12 +313,12 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { case Core::HID::NpadStyleIndex::SNES: shared_memory->style_tag.lucia.Assign(1); shared_memory->device_type.fullkey.Assign(1); - shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::Lucia; + shared_memory->applet_footer_type = AppletFooterUiType::Lucia; break; case Core::HID::NpadStyleIndex::N64: shared_memory->style_tag.lagoon.Assign(1); shared_memory->device_type.fullkey.Assign(1); - shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::Lagon; + shared_memory->applet_footer_type = AppletFooterUiType::Lagon; break; case Core::HID::NpadStyleIndex::SegaGenesis: shared_memory->style_tag.lager.Assign(1); @@ -419,9 +418,17 @@ void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) { std::scoped_lock lock{mutex}; auto& controller = GetControllerFromNpadIdType(npad_id); const auto controller_type = controller.device->GetNpadStyleIndex(); + + if (!controller.device->IsConnected() && controller.is_connected) { + DisconnectNpad(npad_id); + return; + } if (!controller.device->IsConnected()) { return; } + if (controller.device->IsConnected() && !controller.is_connected) { + InitNewlyAddedController(npad_id); + } // This function is unique to yuzu for the turbo buttons and motion to work properly controller.device->StatusUpdate(); @@ -468,6 +475,10 @@ void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) { pad_entry.npad_buttons.l.Assign(button_state.zl); pad_entry.npad_buttons.r.Assign(button_state.zr); } + + if (pad_entry.npad_buttons.raw != Core::HID::NpadButton::None) { + hid_core.SetLastActiveController(npad_id); + } } void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) { @@ -736,14 +747,6 @@ void Controller_NPad::SetSupportedStyleSet(Core::HID::NpadStyleTag style_set) { // Once SetSupportedStyleSet is called controllers are fully initialized is_controller_initialized = true; - - // Connect all active controllers - for (auto& controller : controller_data) { - const auto& device = controller.device; - if (device->IsConnected()) { - AddNewControllerAt(device->GetNpadStyleIndex(), device->GetNpadIdType()); - } - } } Core::HID::NpadStyleTag Controller_NPad::GetSupportedStyleSet() const { @@ -1116,7 +1119,7 @@ Result Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) { .left = {}, .right = {}, }; - shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::None; + shared_memory->applet_footer_type = AppletFooterUiType::None; controller.is_dual_left_connected = true; controller.is_dual_right_connected = true; diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 0e9f899a4..949e58a4c 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -362,7 +362,7 @@ private: enum class AppletFooterUiType : u8 { None = 0, HandheldNone = 1, - HandheldJoyConLeftOnly = 1, + HandheldJoyConLeftOnly = 2, HandheldJoyConRightOnly = 3, HandheldJoyConLeftJoyConRight = 4, JoyDual = 5, @@ -384,13 +384,6 @@ private: Lagon = 21, }; - struct AppletFooterUi { - AppletFooterUiAttributes attributes{}; - AppletFooterUiType type{AppletFooterUiType::None}; - INSERT_PADDING_BYTES(0x5B); // Reserved - }; - static_assert(sizeof(AppletFooterUi) == 0x60, "AppletFooterUi is an invalid size"); - // This is nn::hid::NpadLarkType enum class NpadLarkType : u32 { Invalid, @@ -421,13 +414,6 @@ private: U, }; - struct AppletNfcXcd { - union { - AppletFooterUi applet_footer{}; - Lifo<NfcXcdDeviceHandleStateImpl, 0x2> nfc_xcd_device_lifo; - }; - }; - // This is nn::hid::detail::NpadInternalState struct NpadInternalState { Core::HID::NpadStyleTag style_tag{Core::HID::NpadStyleSet::None}; @@ -454,7 +440,9 @@ private: Core::HID::NpadBatteryLevel battery_level_dual{}; Core::HID::NpadBatteryLevel battery_level_left{}; Core::HID::NpadBatteryLevel battery_level_right{}; - AppletNfcXcd applet_nfc_xcd{}; + AppletFooterUiAttributes applet_footer_attributes{}; + AppletFooterUiType applet_footer_type{AppletFooterUiType::None}; + INSERT_PADDING_BYTES(0x5B); // Reserved INSERT_PADDING_BYTES(0x20); // Unknown Lifo<NpadGcTriggerState, hid_entry_count> gc_trigger_lifo{}; NpadLarkType lark_type_l_and_main{}; diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 6f711c0da..4d70006c1 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -2774,7 +2774,7 @@ private: IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.PushEnum(Core::HID::NpadIdType::Handheld); + rb.PushEnum(system.HIDCore().GetLastActiveController()); } void GetUniquePadsFromNpad(HLERequestContext& ctx) { diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp index 5dda12343..674d2e4b2 100644 --- a/src/core/hle/service/nfc/common/device.cpp +++ b/src/core/hle/service/nfc/common/device.cpp @@ -874,17 +874,19 @@ Result NfcDevice::RestoreAmiibo() { } Result NfcDevice::Format() { - auto result1 = DeleteApplicationArea(); - auto result2 = DeleteRegisterInfo(); + Result result = ResultSuccess; - if (result1.IsError()) { - return result1; + if (device_state == DeviceState::TagFound) { + result = Mount(NFP::ModelType::Amiibo, NFP::MountTarget::All); } - if (result2.IsError()) { - return result2; + if (result.IsError()) { + return result; } + DeleteApplicationArea(); + DeleteRegisterInfo(); + return Flush(); } diff --git a/src/core/hle/service/ngc/ngc.cpp b/src/core/hle/service/ngc/ngc.cpp new file mode 100644 index 000000000..c26019ec0 --- /dev/null +++ b/src/core/hle/service/ngc/ngc.cpp @@ -0,0 +1,150 @@ +// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/string_util.h" +#include "core/core.h" +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/ngc/ngc.h" +#include "core/hle/service/server_manager.h" +#include "core/hle/service/service.h" + +namespace Service::NGC { + +class NgctServiceImpl final : public ServiceFramework<NgctServiceImpl> { +public: + explicit NgctServiceImpl(Core::System& system_) : ServiceFramework{system_, "ngct:u"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, &NgctServiceImpl::Match, "Match"}, + {1, &NgctServiceImpl::Filter, "Filter"}, + }; + // clang-format on + + RegisterHandlers(functions); + } + +private: + void Match(HLERequestContext& ctx) { + const auto buffer = ctx.ReadBuffer(); + const auto text = Common::StringFromFixedZeroTerminatedBuffer( + reinterpret_cast<const char*>(buffer.data()), buffer.size()); + + LOG_WARNING(Service_NGC, "(STUBBED) called, text={}", text); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + // Return false since we don't censor anything + rb.Push(false); + } + + void Filter(HLERequestContext& ctx) { + const auto buffer = ctx.ReadBuffer(); + const auto text = Common::StringFromFixedZeroTerminatedBuffer( + reinterpret_cast<const char*>(buffer.data()), buffer.size()); + + LOG_WARNING(Service_NGC, "(STUBBED) called, text={}", text); + + // Return the same string since we don't censor anything + ctx.WriteBuffer(buffer); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); + } +}; + +class NgcServiceImpl final : public ServiceFramework<NgcServiceImpl> { +public: + explicit NgcServiceImpl(Core::System& system_) : ServiceFramework(system_, "ngc:u") { + // clang-format off + static const FunctionInfo functions[] = { + {0, &NgcServiceImpl::GetContentVersion, "GetContentVersion"}, + {1, &NgcServiceImpl::Check, "Check"}, + {2, &NgcServiceImpl::Mask, "Mask"}, + {3, &NgcServiceImpl::Reload, "Reload"}, + }; + // clang-format on + + RegisterHandlers(functions); + } + +private: + static constexpr u32 NgcContentVersion = 1; + + // This is nn::ngc::detail::ProfanityFilterOption + struct ProfanityFilterOption { + INSERT_PADDING_BYTES_NOINIT(0x20); + }; + static_assert(sizeof(ProfanityFilterOption) == 0x20, + "ProfanityFilterOption has incorrect size"); + + void GetContentVersion(HLERequestContext& ctx) { + LOG_INFO(Service_NGC, "(STUBBED) called"); + + // This calls nn::ngc::ProfanityFilter::GetContentVersion + const u32 version = NgcContentVersion; + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(version); + } + + void Check(HLERequestContext& ctx) { + LOG_INFO(Service_NGC, "(STUBBED) called"); + + struct InputParameters { + u32 flags; + ProfanityFilterOption option; + }; + + IPC::RequestParser rp{ctx}; + [[maybe_unused]] const auto params = rp.PopRaw<InputParameters>(); + [[maybe_unused]] const auto input = ctx.ReadBuffer(0); + + // This calls nn::ngc::ProfanityFilter::CheckProfanityWords + const u32 out_flags = 0; + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(out_flags); + } + + void Mask(HLERequestContext& ctx) { + LOG_INFO(Service_NGC, "(STUBBED) called"); + + struct InputParameters { + u32 flags; + ProfanityFilterOption option; + }; + + IPC::RequestParser rp{ctx}; + [[maybe_unused]] const auto params = rp.PopRaw<InputParameters>(); + const auto input = ctx.ReadBuffer(0); + + // This calls nn::ngc::ProfanityFilter::MaskProfanityWordsInText + const u32 out_flags = 0; + ctx.WriteBuffer(input); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(out_flags); + } + + void Reload(HLERequestContext& ctx) { + LOG_INFO(Service_NGC, "(STUBBED) called"); + + // This reloads the database. + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); + } +}; + +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("ngct:u", std::make_shared<NgctServiceImpl>(system)); + server_manager->RegisterNamedService("ngc:u", std::make_shared<NgcServiceImpl>(system)); + ServerManager::RunServer(std::move(server_manager)); +} + +} // namespace Service::NGC diff --git a/src/core/hle/service/ngct/ngct.h b/src/core/hle/service/ngc/ngc.h index 27c34dad4..823b1aa81 100644 --- a/src/core/hle/service/ngct/ngct.h +++ b/src/core/hle/service/ngc/ngc.h @@ -7,8 +7,8 @@ namespace Core { class System; } -namespace Service::NGCT { +namespace Service::NGC { void LoopProcess(Core::System& system); -} // namespace Service::NGCT +} // namespace Service::NGC diff --git a/src/core/hle/service/ngct/ngct.cpp b/src/core/hle/service/ngct/ngct.cpp deleted file mode 100644 index 493c80ed2..000000000 --- a/src/core/hle/service/ngct/ngct.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/string_util.h" -#include "core/core.h" -#include "core/hle/service/ipc_helpers.h" -#include "core/hle/service/ngct/ngct.h" -#include "core/hle/service/server_manager.h" -#include "core/hle/service/service.h" - -namespace Service::NGCT { - -class IService final : public ServiceFramework<IService> { -public: - explicit IService(Core::System& system_) : ServiceFramework{system_, "ngct:u"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, &IService::Match, "Match"}, - {1, &IService::Filter, "Filter"}, - }; - // clang-format on - - RegisterHandlers(functions); - } - -private: - void Match(HLERequestContext& ctx) { - const auto buffer = ctx.ReadBuffer(); - const auto text = Common::StringFromFixedZeroTerminatedBuffer( - reinterpret_cast<const char*>(buffer.data()), buffer.size()); - - LOG_WARNING(Service_NGCT, "(STUBBED) called, text={}", text); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - // Return false since we don't censor anything - rb.Push(false); - } - - void Filter(HLERequestContext& ctx) { - const auto buffer = ctx.ReadBuffer(); - const auto text = Common::StringFromFixedZeroTerminatedBuffer( - reinterpret_cast<const char*>(buffer.data()), buffer.size()); - - LOG_WARNING(Service_NGCT, "(STUBBED) called, text={}", text); - - // Return the same string since we don't censor anything - ctx.WriteBuffer(buffer); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } -}; - -void LoopProcess(Core::System& system) { - auto server_manager = std::make_unique<ServerManager>(system); - - server_manager->RegisterNamedService("ngct:u", std::make_shared<IService>(system)); - ServerManager::RunServer(std::move(server_manager)); -} - -} // namespace Service::NGCT diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 69cdb5918..0ad607391 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -43,7 +43,7 @@ #include "core/hle/service/ncm/ncm.h" #include "core/hle/service/nfc/nfc.h" #include "core/hle/service/nfp/nfp.h" -#include "core/hle/service/ngct/ngct.h" +#include "core/hle/service/ngc/ngc.h" #include "core/hle/service/nifm/nifm.h" #include "core/hle/service/nim/nim.h" #include "core/hle/service/npns/npns.h" @@ -257,7 +257,7 @@ Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system kernel.RunOnGuestCoreProcess("NCM", [&] { NCM::LoopProcess(system); }); kernel.RunOnGuestCoreProcess("nfc", [&] { NFC::LoopProcess(system); }); kernel.RunOnGuestCoreProcess("nfp", [&] { NFP::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("ngct", [&] { NGCT::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("ngc", [&] { NGC::LoopProcess(system); }); kernel.RunOnGuestCoreProcess("nifm", [&] { NIFM::LoopProcess(system); }); kernel.RunOnGuestCoreProcess("nim", [&] { NIM::LoopProcess(system); }); kernel.RunOnGuestCoreProcess("npns", [&] { NPNS::LoopProcess(system); }); diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp index d8509c1dd..85849d5f3 100644 --- a/src/core/hle/service/sockets/bsd.cpp +++ b/src/core/hle/service/sockets/bsd.cpp @@ -170,7 +170,7 @@ void BSD::Socket(HLERequestContext& ctx) { } void BSD::Select(HLERequestContext& ctx) { - LOG_WARNING(Service, "(STUBBED) called"); + LOG_DEBUG(Service, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 4}; diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index f4eaf3331..5a42dea48 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp @@ -18,7 +18,7 @@ namespace Loader { AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile file_, bool override_update_) - : AppLoader(std::move(file_)), override_update(override_update_) { + : AppLoader(std::move(file_)), override_update(override_update_), is_hbl(false) { const auto file_dir = file->GetContainingDirectory(); // Title ID @@ -69,9 +69,9 @@ AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys } AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory( - FileSys::VirtualDir directory, bool override_update_) + FileSys::VirtualDir directory, bool override_update_, bool is_hbl_) : AppLoader(directory->GetFile("main")), dir(std::move(directory)), - override_update(override_update_) {} + override_update(override_update_), is_hbl(is_hbl_) {} FileType AppLoader_DeconstructedRomDirectory::IdentifyType(const FileSys::VirtualFile& dir_file) { if (FileSys::IsDirectoryExeFS(dir_file->GetContainingDirectory())) { @@ -147,7 +147,7 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect } // Setup the process code layout - if (process.LoadFromMetadata(metadata, code_size).IsError()) { + if (process.LoadFromMetadata(metadata, code_size, is_hbl).IsError()) { return {ResultStatus::ErrorUnableToParseKernelMetadata, {}}; } diff --git a/src/core/loader/deconstructed_rom_directory.h b/src/core/loader/deconstructed_rom_directory.h index f7702225e..1e9f765c9 100644 --- a/src/core/loader/deconstructed_rom_directory.h +++ b/src/core/loader/deconstructed_rom_directory.h @@ -27,7 +27,8 @@ public: // Overload to accept exefs directory. Must contain 'main' and 'main.npdm' explicit AppLoader_DeconstructedRomDirectory(FileSys::VirtualDir directory, - bool override_update_ = false); + bool override_update_ = false, + bool is_hbl_ = false); /** * Identifies whether or not the given file is a deconstructed ROM directory. @@ -62,6 +63,7 @@ private: std::string name; u64 title_id{}; bool override_update; + bool is_hbl; Modules modules; }; diff --git a/src/core/loader/kip.cpp b/src/core/loader/kip.cpp index d722459c6..bf56a08b4 100644 --- a/src/core/loader/kip.cpp +++ b/src/core/loader/kip.cpp @@ -90,7 +90,8 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::KProcess& process, codeset.DataSegment().size += kip->GetBSSSize(); // Setup the process code layout - if (process.LoadFromMetadata(FileSys::ProgramMetadata::GetDefault(), program_image.size()) + if (process + .LoadFromMetadata(FileSys::ProgramMetadata::GetDefault(), program_image.size(), false) .IsError()) { return {ResultStatus::ErrorNotInitialized, {}}; } diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp index d7562b4bc..69f1a54ed 100644 --- a/src/core/loader/nro.cpp +++ b/src/core/loader/nro.cpp @@ -196,7 +196,8 @@ static bool LoadNroImpl(Kernel::KProcess& process, const std::vector<u8>& data) program_image.resize(static_cast<u32>(program_image.size()) + bss_size); // Setup the process code layout - if (process.LoadFromMetadata(FileSys::ProgramMetadata::GetDefault(), program_image.size()) + if (process + .LoadFromMetadata(FileSys::ProgramMetadata::GetDefault(), program_image.size(), false) .IsError()) { return false; } diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index 549822506..1350da8dc 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp @@ -127,13 +127,14 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::KProcess& process, Core:: } // Apply patches if necessary - if (pm && (pm->HasNSOPatch(nso_header.build_id) || Settings::values.dump_nso)) { + const auto name = nso_file.GetName(); + if (pm && (pm->HasNSOPatch(nso_header.build_id, name) || Settings::values.dump_nso)) { std::vector<u8> pi_header(sizeof(NSOHeader) + program_image.size()); std::memcpy(pi_header.data(), &nso_header, sizeof(NSOHeader)); std::memcpy(pi_header.data() + sizeof(NSOHeader), program_image.data(), program_image.size()); - pi_header = pm->PatchNSO(pi_header, nso_file.GetName()); + pi_header = pm->PatchNSO(pi_header, name); std::copy(pi_header.begin() + sizeof(NSOHeader), pi_header.end(), program_image.data()); } diff --git a/src/core/loader/nsp.cpp b/src/core/loader/nsp.cpp index fe2af1ae6..f4ab75b77 100644 --- a/src/core/loader/nsp.cpp +++ b/src/core/loader/nsp.cpp @@ -30,7 +30,8 @@ AppLoader_NSP::AppLoader_NSP(FileSys::VirtualFile file_, } if (nsp->IsExtractedType()) { - secondary_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(nsp->GetExeFS()); + secondary_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>( + nsp->GetExeFS(), false, file->GetName() == "hbl.nsp"); } else { const auto control_nca = nsp->GetNCA(nsp->GetProgramTitleID(), FileSys::ContentRecordType::Control); diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp index 7b52f61a7..a06e99166 100644 --- a/src/core/memory/cheat_engine.cpp +++ b/src/core/memory/cheat_engine.cpp @@ -154,7 +154,7 @@ std::vector<CheatEntry> TextCheatParser::Parse(std::string_view data) const { return {}; } - const auto value = static_cast<u32>(std::stoul(hex, nullptr, 0x10)); + const auto value = static_cast<u32>(std::strtoul(hex.c_str(), nullptr, 0x10)); out[*current_entry].definition.opcodes[out[*current_entry].definition.num_opcodes++] = value; diff --git a/src/core/tools/renderdoc.cpp b/src/core/tools/renderdoc.cpp new file mode 100644 index 000000000..44d24822a --- /dev/null +++ b/src/core/tools/renderdoc.cpp @@ -0,0 +1,55 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include <renderdoc_app.h> + +#include "common/assert.h" +#include "common/dynamic_library.h" +#include "core/tools/renderdoc.h" + +#ifdef WIN32 +#include <windows.h> +#else +#include <dlfcn.h> +#endif + +namespace Tools { + +RenderdocAPI::RenderdocAPI() { +#ifdef WIN32 + if (HMODULE mod = GetModuleHandleA("renderdoc.dll")) { + const auto RENDERDOC_GetAPI = + reinterpret_cast<pRENDERDOC_GetAPI>(GetProcAddress(mod, "RENDERDOC_GetAPI")); + const s32 ret = RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_6_0, (void**)&rdoc_api); + ASSERT(ret == 1); + } +#else +#ifdef ANDROID + static constexpr const char RENDERDOC_LIB[] = "libVkLayer_GLES_RenderDoc.so"; +#else + static constexpr const char RENDERDOC_LIB[] = "librenderdoc.so"; +#endif + if (void* mod = dlopen(RENDERDOC_LIB, RTLD_NOW | RTLD_NOLOAD)) { + const auto RENDERDOC_GetAPI = + reinterpret_cast<pRENDERDOC_GetAPI>(dlsym(mod, "RENDERDOC_GetAPI")); + const s32 ret = RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_6_0, (void**)&rdoc_api); + ASSERT(ret == 1); + } +#endif +} + +RenderdocAPI::~RenderdocAPI() = default; + +void RenderdocAPI::ToggleCapture() { + if (!rdoc_api) [[unlikely]] { + return; + } + if (!is_capturing) { + rdoc_api->StartFrameCapture(NULL, NULL); + } else { + rdoc_api->EndFrameCapture(NULL, NULL); + } + is_capturing = !is_capturing; +} + +} // namespace Tools diff --git a/src/core/tools/renderdoc.h b/src/core/tools/renderdoc.h new file mode 100644 index 000000000..0e5e43da5 --- /dev/null +++ b/src/core/tools/renderdoc.h @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +struct RENDERDOC_API_1_6_0; + +namespace Tools { + +class RenderdocAPI { +public: + explicit RenderdocAPI(); + ~RenderdocAPI(); + + void ToggleCapture(); + +private: + RENDERDOC_API_1_6_0* rdoc_api{}; + bool is_capturing{false}; +}; + +} // namespace Tools |