diff options
Diffstat (limited to 'src/core')
66 files changed, 2133 insertions, 936 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 9dbe5bdca..405a2f993 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -2,18 +2,8 @@ | |||
| 2 | # SPDX-License-Identifier: GPL-2.0-or-later | 2 | # SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | add_library(core STATIC | 4 | add_library(core STATIC |
| 5 | announce_multiplayer_session.cpp | ||
| 6 | announce_multiplayer_session.h | ||
| 7 | arm/arm_interface.h | 5 | arm/arm_interface.h |
| 8 | arm/arm_interface.cpp | 6 | arm/arm_interface.cpp |
| 9 | arm/cpu_interrupt_handler.cpp | ||
| 10 | arm/cpu_interrupt_handler.h | ||
| 11 | arm/dynarmic/arm_dynarmic_32.cpp | ||
| 12 | arm/dynarmic/arm_dynarmic_32.h | ||
| 13 | arm/dynarmic/arm_dynarmic_64.cpp | ||
| 14 | arm/dynarmic/arm_dynarmic_64.h | ||
| 15 | arm/dynarmic/arm_dynarmic_cp15.cpp | ||
| 16 | arm/dynarmic/arm_dynarmic_cp15.h | ||
| 17 | arm/dynarmic/arm_exclusive_monitor.cpp | 7 | arm/dynarmic/arm_exclusive_monitor.cpp |
| 18 | arm/dynarmic/arm_exclusive_monitor.h | 8 | arm/dynarmic/arm_exclusive_monitor.h |
| 19 | arm/exclusive_monitor.cpp | 9 | arm/exclusive_monitor.cpp |
| @@ -504,9 +494,10 @@ add_library(core STATIC | |||
| 504 | hle/service/jit/jit.h | 494 | hle/service/jit/jit.h |
| 505 | hle/service/lbl/lbl.cpp | 495 | hle/service/lbl/lbl.cpp |
| 506 | hle/service/lbl/lbl.h | 496 | hle/service/lbl/lbl.h |
| 507 | hle/service/ldn/errors.h | 497 | hle/service/ldn/ldn_results.h |
| 508 | hle/service/ldn/ldn.cpp | 498 | hle/service/ldn/ldn.cpp |
| 509 | hle/service/ldn/ldn.h | 499 | hle/service/ldn/ldn.h |
| 500 | hle/service/ldn/ldn_types.h | ||
| 510 | hle/service/ldr/ldr.cpp | 501 | hle/service/ldr/ldr.cpp |
| 511 | hle/service/ldr/ldr.h | 502 | hle/service/ldr/ldr.h |
| 512 | hle/service/lm/lm.cpp | 503 | hle/service/lm/lm.cpp |
| @@ -541,14 +532,14 @@ add_library(core STATIC | |||
| 541 | hle/service/npns/npns.cpp | 532 | hle/service/npns/npns.cpp |
| 542 | hle/service/npns/npns.h | 533 | hle/service/npns/npns.h |
| 543 | hle/service/ns/errors.h | 534 | hle/service/ns/errors.h |
| 535 | hle/service/ns/iplatform_service_manager.cpp | ||
| 536 | hle/service/ns/iplatform_service_manager.h | ||
| 544 | hle/service/ns/language.cpp | 537 | hle/service/ns/language.cpp |
| 545 | hle/service/ns/language.h | 538 | hle/service/ns/language.h |
| 546 | hle/service/ns/ns.cpp | 539 | hle/service/ns/ns.cpp |
| 547 | hle/service/ns/ns.h | 540 | hle/service/ns/ns.h |
| 548 | hle/service/ns/pdm_qry.cpp | 541 | hle/service/ns/pdm_qry.cpp |
| 549 | hle/service/ns/pdm_qry.h | 542 | hle/service/ns/pdm_qry.h |
| 550 | hle/service/ns/pl_u.cpp | ||
| 551 | hle/service/ns/pl_u.h | ||
| 552 | hle/service/nvdrv/devices/nvdevice.h | 543 | hle/service/nvdrv/devices/nvdevice.h |
| 553 | hle/service/nvdrv/devices/nvdisp_disp0.cpp | 544 | hle/service/nvdrv/devices/nvdisp_disp0.cpp |
| 554 | hle/service/nvdrv/devices/nvdisp_disp0.h | 545 | hle/service/nvdrv/devices/nvdisp_disp0.h |
| @@ -725,6 +716,8 @@ add_library(core STATIC | |||
| 725 | internal_network/network_interface.cpp | 716 | internal_network/network_interface.cpp |
| 726 | internal_network/network_interface.h | 717 | internal_network/network_interface.h |
| 727 | internal_network/sockets.h | 718 | internal_network/sockets.h |
| 719 | internal_network/socket_proxy.cpp | ||
| 720 | internal_network/socket_proxy.h | ||
| 728 | loader/deconstructed_rom_directory.cpp | 721 | loader/deconstructed_rom_directory.cpp |
| 729 | loader/deconstructed_rom_directory.h | 722 | loader/deconstructed_rom_directory.h |
| 730 | loader/kip.cpp | 723 | loader/kip.cpp |
| @@ -785,7 +778,7 @@ endif() | |||
| 785 | create_target_directory_groups(core) | 778 | create_target_directory_groups(core) |
| 786 | 779 | ||
| 787 | target_link_libraries(core PUBLIC common PRIVATE audio_core network video_core) | 780 | target_link_libraries(core PUBLIC common PRIVATE audio_core network video_core) |
| 788 | target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls Opus::Opus) | 781 | target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls Opus::opus) |
| 789 | if (MINGW) | 782 | if (MINGW) |
| 790 | target_link_libraries(core PRIVATE ${MSWSOCK_LIBRARY}) | 783 | target_link_libraries(core PRIVATE ${MSWSOCK_LIBRARY}) |
| 791 | endif() | 784 | endif() |
diff --git a/src/core/announce_multiplayer_session.cpp b/src/core/announce_multiplayer_session.cpp deleted file mode 100644 index d73a488cf..000000000 --- a/src/core/announce_multiplayer_session.cpp +++ /dev/null | |||
| @@ -1,164 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2017 Citra Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include <chrono> | ||
| 5 | #include <future> | ||
| 6 | #include <vector> | ||
| 7 | #include "announce_multiplayer_session.h" | ||
| 8 | #include "common/announce_multiplayer_room.h" | ||
| 9 | #include "common/assert.h" | ||
| 10 | #include "common/settings.h" | ||
| 11 | #include "network/network.h" | ||
| 12 | |||
| 13 | #ifdef ENABLE_WEB_SERVICE | ||
| 14 | #include "web_service/announce_room_json.h" | ||
| 15 | #endif | ||
| 16 | |||
| 17 | namespace Core { | ||
| 18 | |||
| 19 | // Time between room is announced to web_service | ||
| 20 | static constexpr std::chrono::seconds announce_time_interval(15); | ||
| 21 | |||
| 22 | AnnounceMultiplayerSession::AnnounceMultiplayerSession(Network::RoomNetwork& room_network_) | ||
| 23 | : room_network{room_network_} { | ||
| 24 | #ifdef ENABLE_WEB_SERVICE | ||
| 25 | backend = std::make_unique<WebService::RoomJson>(Settings::values.web_api_url.GetValue(), | ||
| 26 | Settings::values.yuzu_username.GetValue(), | ||
| 27 | Settings::values.yuzu_token.GetValue()); | ||
| 28 | #else | ||
| 29 | backend = std::make_unique<AnnounceMultiplayerRoom::NullBackend>(); | ||
| 30 | #endif | ||
| 31 | } | ||
| 32 | |||
| 33 | WebService::WebResult AnnounceMultiplayerSession::Register() { | ||
| 34 | std::shared_ptr<Network::Room> room = room_network.GetRoom().lock(); | ||
| 35 | if (!room) { | ||
| 36 | return WebService::WebResult{WebService::WebResult::Code::LibError, | ||
| 37 | "Network is not initialized", ""}; | ||
| 38 | } | ||
| 39 | if (room->GetState() != Network::Room::State::Open) { | ||
| 40 | return WebService::WebResult{WebService::WebResult::Code::LibError, "Room is not open", ""}; | ||
| 41 | } | ||
| 42 | UpdateBackendData(room); | ||
| 43 | WebService::WebResult result = backend->Register(); | ||
| 44 | if (result.result_code != WebService::WebResult::Code::Success) { | ||
| 45 | return result; | ||
| 46 | } | ||
| 47 | LOG_INFO(WebService, "Room has been registered"); | ||
| 48 | room->SetVerifyUID(result.returned_data); | ||
| 49 | registered = true; | ||
| 50 | return WebService::WebResult{WebService::WebResult::Code::Success, "", ""}; | ||
| 51 | } | ||
| 52 | |||
| 53 | void AnnounceMultiplayerSession::Start() { | ||
| 54 | if (announce_multiplayer_thread) { | ||
| 55 | Stop(); | ||
| 56 | } | ||
| 57 | shutdown_event.Reset(); | ||
| 58 | announce_multiplayer_thread = | ||
| 59 | std::make_unique<std::thread>(&AnnounceMultiplayerSession::AnnounceMultiplayerLoop, this); | ||
| 60 | } | ||
| 61 | |||
| 62 | void AnnounceMultiplayerSession::Stop() { | ||
| 63 | if (announce_multiplayer_thread) { | ||
| 64 | shutdown_event.Set(); | ||
| 65 | announce_multiplayer_thread->join(); | ||
| 66 | announce_multiplayer_thread.reset(); | ||
| 67 | backend->Delete(); | ||
| 68 | registered = false; | ||
| 69 | } | ||
| 70 | } | ||
| 71 | |||
| 72 | AnnounceMultiplayerSession::CallbackHandle AnnounceMultiplayerSession::BindErrorCallback( | ||
| 73 | std::function<void(const WebService::WebResult&)> function) { | ||
| 74 | std::lock_guard lock(callback_mutex); | ||
| 75 | auto handle = std::make_shared<std::function<void(const WebService::WebResult&)>>(function); | ||
| 76 | error_callbacks.insert(handle); | ||
| 77 | return handle; | ||
| 78 | } | ||
| 79 | |||
| 80 | void AnnounceMultiplayerSession::UnbindErrorCallback(CallbackHandle handle) { | ||
| 81 | std::lock_guard lock(callback_mutex); | ||
| 82 | error_callbacks.erase(handle); | ||
| 83 | } | ||
| 84 | |||
| 85 | AnnounceMultiplayerSession::~AnnounceMultiplayerSession() { | ||
| 86 | Stop(); | ||
| 87 | } | ||
| 88 | |||
| 89 | void AnnounceMultiplayerSession::UpdateBackendData(std::shared_ptr<Network::Room> room) { | ||
| 90 | Network::RoomInformation room_information = room->GetRoomInformation(); | ||
| 91 | std::vector<AnnounceMultiplayerRoom::Member> memberlist = room->GetRoomMemberList(); | ||
| 92 | backend->SetRoomInformation(room_information.name, room_information.description, | ||
| 93 | room_information.port, room_information.member_slots, | ||
| 94 | Network::network_version, room->HasPassword(), | ||
| 95 | room_information.preferred_game); | ||
| 96 | backend->ClearPlayers(); | ||
| 97 | for (const auto& member : memberlist) { | ||
| 98 | backend->AddPlayer(member); | ||
| 99 | } | ||
| 100 | } | ||
| 101 | |||
| 102 | void AnnounceMultiplayerSession::AnnounceMultiplayerLoop() { | ||
| 103 | // Invokes all current bound error callbacks. | ||
| 104 | const auto ErrorCallback = [this](WebService::WebResult result) { | ||
| 105 | std::lock_guard<std::mutex> lock(callback_mutex); | ||
| 106 | for (auto callback : error_callbacks) { | ||
| 107 | (*callback)(result); | ||
| 108 | } | ||
| 109 | }; | ||
| 110 | |||
| 111 | if (!registered) { | ||
| 112 | WebService::WebResult result = Register(); | ||
| 113 | if (result.result_code != WebService::WebResult::Code::Success) { | ||
| 114 | ErrorCallback(result); | ||
| 115 | return; | ||
| 116 | } | ||
| 117 | } | ||
| 118 | |||
| 119 | auto update_time = std::chrono::steady_clock::now(); | ||
| 120 | std::future<WebService::WebResult> future; | ||
| 121 | while (!shutdown_event.WaitUntil(update_time)) { | ||
| 122 | update_time += announce_time_interval; | ||
| 123 | std::shared_ptr<Network::Room> room = room_network.GetRoom().lock(); | ||
| 124 | if (!room) { | ||
| 125 | break; | ||
| 126 | } | ||
| 127 | if (room->GetState() != Network::Room::State::Open) { | ||
| 128 | break; | ||
| 129 | } | ||
| 130 | UpdateBackendData(room); | ||
| 131 | WebService::WebResult result = backend->Update(); | ||
| 132 | if (result.result_code != WebService::WebResult::Code::Success) { | ||
| 133 | ErrorCallback(result); | ||
| 134 | } | ||
| 135 | if (result.result_string == "404") { | ||
| 136 | registered = false; | ||
| 137 | // Needs to register the room again | ||
| 138 | WebService::WebResult register_result = Register(); | ||
| 139 | if (register_result.result_code != WebService::WebResult::Code::Success) { | ||
| 140 | ErrorCallback(register_result); | ||
| 141 | } | ||
| 142 | } | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 146 | AnnounceMultiplayerRoom::RoomList AnnounceMultiplayerSession::GetRoomList() { | ||
| 147 | return backend->GetRoomList(); | ||
| 148 | } | ||
| 149 | |||
| 150 | bool AnnounceMultiplayerSession::IsRunning() const { | ||
| 151 | return announce_multiplayer_thread != nullptr; | ||
| 152 | } | ||
| 153 | |||
| 154 | void AnnounceMultiplayerSession::UpdateCredentials() { | ||
| 155 | ASSERT_MSG(!IsRunning(), "Credentials can only be updated when session is not running"); | ||
| 156 | |||
| 157 | #ifdef ENABLE_WEB_SERVICE | ||
| 158 | backend = std::make_unique<WebService::RoomJson>(Settings::values.web_api_url.GetValue(), | ||
| 159 | Settings::values.yuzu_username.GetValue(), | ||
| 160 | Settings::values.yuzu_token.GetValue()); | ||
| 161 | #endif | ||
| 162 | } | ||
| 163 | |||
| 164 | } // namespace Core | ||
diff --git a/src/core/announce_multiplayer_session.h b/src/core/announce_multiplayer_session.h deleted file mode 100644 index db790f7d2..000000000 --- a/src/core/announce_multiplayer_session.h +++ /dev/null | |||
| @@ -1,98 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2017 Citra Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <atomic> | ||
| 7 | #include <functional> | ||
| 8 | #include <memory> | ||
| 9 | #include <mutex> | ||
| 10 | #include <set> | ||
| 11 | #include <thread> | ||
| 12 | #include "common/announce_multiplayer_room.h" | ||
| 13 | #include "common/common_types.h" | ||
| 14 | #include "common/thread.h" | ||
| 15 | |||
| 16 | namespace Network { | ||
| 17 | class Room; | ||
| 18 | class RoomNetwork; | ||
| 19 | } // namespace Network | ||
| 20 | |||
| 21 | namespace Core { | ||
| 22 | |||
| 23 | /** | ||
| 24 | * Instruments AnnounceMultiplayerRoom::Backend. | ||
| 25 | * Creates a thread that regularly updates the room information and submits them | ||
| 26 | * An async get of room information is also possible | ||
| 27 | */ | ||
| 28 | class AnnounceMultiplayerSession { | ||
| 29 | public: | ||
| 30 | using CallbackHandle = std::shared_ptr<std::function<void(const WebService::WebResult&)>>; | ||
| 31 | AnnounceMultiplayerSession(Network::RoomNetwork& room_network_); | ||
| 32 | ~AnnounceMultiplayerSession(); | ||
| 33 | |||
| 34 | /** | ||
| 35 | * Allows to bind a function that will get called if the announce encounters an error | ||
| 36 | * @param function The function that gets called | ||
| 37 | * @return A handle that can be used the unbind the function | ||
| 38 | */ | ||
| 39 | CallbackHandle BindErrorCallback(std::function<void(const WebService::WebResult&)> function); | ||
| 40 | |||
| 41 | /** | ||
| 42 | * Unbind a function from the error callbacks | ||
| 43 | * @param handle The handle for the function that should get unbind | ||
| 44 | */ | ||
| 45 | void UnbindErrorCallback(CallbackHandle handle); | ||
| 46 | |||
| 47 | /** | ||
| 48 | * Registers a room to web services | ||
| 49 | * @return The result of the registration attempt. | ||
| 50 | */ | ||
| 51 | WebService::WebResult Register(); | ||
| 52 | |||
| 53 | /** | ||
| 54 | * Starts the announce of a room to web services | ||
| 55 | */ | ||
| 56 | void Start(); | ||
| 57 | |||
| 58 | /** | ||
| 59 | * Stops the announce to web services | ||
| 60 | */ | ||
| 61 | void Stop(); | ||
| 62 | |||
| 63 | /** | ||
| 64 | * Returns a list of all room information the backend got | ||
| 65 | * @param func A function that gets executed when the async get finished, e.g. a signal | ||
| 66 | * @return a list of rooms received from the web service | ||
| 67 | */ | ||
| 68 | AnnounceMultiplayerRoom::RoomList GetRoomList(); | ||
| 69 | |||
| 70 | /** | ||
| 71 | * Whether the announce session is still running | ||
| 72 | */ | ||
| 73 | bool IsRunning() const; | ||
| 74 | |||
| 75 | /** | ||
| 76 | * Recreates the backend, updating the credentials. | ||
| 77 | * This can only be used when the announce session is not running. | ||
| 78 | */ | ||
| 79 | void UpdateCredentials(); | ||
| 80 | |||
| 81 | private: | ||
| 82 | void UpdateBackendData(std::shared_ptr<Network::Room> room); | ||
| 83 | void AnnounceMultiplayerLoop(); | ||
| 84 | |||
| 85 | Common::Event shutdown_event; | ||
| 86 | std::mutex callback_mutex; | ||
| 87 | std::set<CallbackHandle> error_callbacks; | ||
| 88 | std::unique_ptr<std::thread> announce_multiplayer_thread; | ||
| 89 | |||
| 90 | /// Backend interface that logs fields | ||
| 91 | std::unique_ptr<AnnounceMultiplayerRoom::Backend> backend; | ||
| 92 | |||
| 93 | std::atomic_bool registered = false; ///< Whether the room has been registered | ||
| 94 | |||
| 95 | Network::RoomNetwork& room_network; | ||
| 96 | }; | ||
| 97 | |||
| 98 | } // namespace Core | ||
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h index 73f259525..7d62d030e 100644 --- a/src/core/arm/arm_interface.h +++ b/src/core/arm/arm_interface.h | |||
| @@ -27,7 +27,6 @@ namespace Core { | |||
| 27 | class System; | 27 | class System; |
| 28 | class CPUInterruptHandler; | 28 | class CPUInterruptHandler; |
| 29 | 29 | ||
| 30 | using CPUInterrupts = std::array<CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>; | ||
| 31 | using WatchpointArray = std::array<Kernel::DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS>; | 30 | using WatchpointArray = std::array<Kernel::DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS>; |
| 32 | 31 | ||
| 33 | /// Generic ARMv8 CPU interface | 32 | /// Generic ARMv8 CPU interface |
| @@ -36,10 +35,8 @@ public: | |||
| 36 | YUZU_NON_COPYABLE(ARM_Interface); | 35 | YUZU_NON_COPYABLE(ARM_Interface); |
| 37 | YUZU_NON_MOVEABLE(ARM_Interface); | 36 | YUZU_NON_MOVEABLE(ARM_Interface); |
| 38 | 37 | ||
| 39 | explicit ARM_Interface(System& system_, CPUInterrupts& interrupt_handlers_, | 38 | explicit ARM_Interface(System& system_, bool uses_wall_clock_) |
| 40 | bool uses_wall_clock_) | 39 | : system{system_}, uses_wall_clock{uses_wall_clock_} {} |
| 41 | : system{system_}, interrupt_handlers{interrupt_handlers_}, uses_wall_clock{ | ||
| 42 | uses_wall_clock_} {} | ||
| 43 | virtual ~ARM_Interface() = default; | 40 | virtual ~ARM_Interface() = default; |
| 44 | 41 | ||
| 45 | struct ThreadContext32 { | 42 | struct ThreadContext32 { |
| @@ -181,6 +178,9 @@ public: | |||
| 181 | /// Signal an interrupt and ask the core to halt as soon as possible. | 178 | /// Signal an interrupt and ask the core to halt as soon as possible. |
| 182 | virtual void SignalInterrupt() = 0; | 179 | virtual void SignalInterrupt() = 0; |
| 183 | 180 | ||
| 181 | /// Clear a previous interrupt. | ||
| 182 | virtual void ClearInterrupt() = 0; | ||
| 183 | |||
| 184 | struct BacktraceEntry { | 184 | struct BacktraceEntry { |
| 185 | std::string module; | 185 | std::string module; |
| 186 | u64 address; | 186 | u64 address; |
| @@ -208,7 +208,6 @@ public: | |||
| 208 | protected: | 208 | protected: |
| 209 | /// System context that this ARM interface is running under. | 209 | /// System context that this ARM interface is running under. |
| 210 | System& system; | 210 | System& system; |
| 211 | CPUInterrupts& interrupt_handlers; | ||
| 212 | const WatchpointArray* watchpoints; | 211 | const WatchpointArray* watchpoints; |
| 213 | bool uses_wall_clock; | 212 | bool uses_wall_clock; |
| 214 | 213 | ||
diff --git a/src/core/arm/cpu_interrupt_handler.cpp b/src/core/arm/cpu_interrupt_handler.cpp deleted file mode 100644 index 77b6194d7..000000000 --- a/src/core/arm/cpu_interrupt_handler.cpp +++ /dev/null | |||
| @@ -1,24 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "common/thread.h" | ||
| 5 | #include "core/arm/cpu_interrupt_handler.h" | ||
| 6 | |||
| 7 | namespace Core { | ||
| 8 | |||
| 9 | CPUInterruptHandler::CPUInterruptHandler() : interrupt_event{std::make_unique<Common::Event>()} {} | ||
| 10 | |||
| 11 | CPUInterruptHandler::~CPUInterruptHandler() = default; | ||
| 12 | |||
| 13 | void CPUInterruptHandler::SetInterrupt(bool is_interrupted_) { | ||
| 14 | if (is_interrupted_) { | ||
| 15 | interrupt_event->Set(); | ||
| 16 | } | ||
| 17 | is_interrupted = is_interrupted_; | ||
| 18 | } | ||
| 19 | |||
| 20 | void CPUInterruptHandler::AwaitInterrupt() { | ||
| 21 | interrupt_event->Wait(); | ||
| 22 | } | ||
| 23 | |||
| 24 | } // namespace Core | ||
diff --git a/src/core/arm/cpu_interrupt_handler.h b/src/core/arm/cpu_interrupt_handler.h deleted file mode 100644 index 286e12e53..000000000 --- a/src/core/arm/cpu_interrupt_handler.h +++ /dev/null | |||
| @@ -1,39 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <atomic> | ||
| 7 | #include <memory> | ||
| 8 | |||
| 9 | namespace Common { | ||
| 10 | class Event; | ||
| 11 | } | ||
| 12 | |||
| 13 | namespace Core { | ||
| 14 | |||
| 15 | class CPUInterruptHandler { | ||
| 16 | public: | ||
| 17 | CPUInterruptHandler(); | ||
| 18 | ~CPUInterruptHandler(); | ||
| 19 | |||
| 20 | CPUInterruptHandler(const CPUInterruptHandler&) = delete; | ||
| 21 | CPUInterruptHandler& operator=(const CPUInterruptHandler&) = delete; | ||
| 22 | |||
| 23 | CPUInterruptHandler(CPUInterruptHandler&&) = delete; | ||
| 24 | CPUInterruptHandler& operator=(CPUInterruptHandler&&) = delete; | ||
| 25 | |||
| 26 | bool IsInterrupted() const { | ||
| 27 | return is_interrupted; | ||
| 28 | } | ||
| 29 | |||
| 30 | void SetInterrupt(bool is_interrupted); | ||
| 31 | |||
| 32 | void AwaitInterrupt(); | ||
| 33 | |||
| 34 | private: | ||
| 35 | std::unique_ptr<Common::Event> interrupt_event; | ||
| 36 | std::atomic_bool is_interrupted{false}; | ||
| 37 | }; | ||
| 38 | |||
| 39 | } // namespace Core | ||
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index b8d2ce224..d1e70f19d 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp | |||
| @@ -11,7 +11,6 @@ | |||
| 11 | #include "common/logging/log.h" | 11 | #include "common/logging/log.h" |
| 12 | #include "common/page_table.h" | 12 | #include "common/page_table.h" |
| 13 | #include "common/settings.h" | 13 | #include "common/settings.h" |
| 14 | #include "core/arm/cpu_interrupt_handler.h" | ||
| 15 | #include "core/arm/dynarmic/arm_dynarmic_32.h" | 14 | #include "core/arm/dynarmic/arm_dynarmic_32.h" |
| 16 | #include "core/arm/dynarmic/arm_dynarmic_cp15.h" | 15 | #include "core/arm/dynarmic/arm_dynarmic_cp15.h" |
| 17 | #include "core/arm/dynarmic/arm_exclusive_monitor.h" | 16 | #include "core/arm/dynarmic/arm_exclusive_monitor.h" |
| @@ -125,7 +124,9 @@ public: | |||
| 125 | } | 124 | } |
| 126 | 125 | ||
| 127 | void AddTicks(u64 ticks) override { | 126 | void AddTicks(u64 ticks) override { |
| 128 | ASSERT_MSG(!parent.uses_wall_clock, "This should never happen - dynarmic ticking disabled"); | 127 | if (parent.uses_wall_clock) { |
| 128 | return; | ||
| 129 | } | ||
| 129 | 130 | ||
| 130 | // Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a | 131 | // Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a |
| 131 | // rough approximation of the amount of executed ticks in the system, it may be thrown off | 132 | // rough approximation of the amount of executed ticks in the system, it may be thrown off |
| @@ -142,7 +143,12 @@ public: | |||
| 142 | } | 143 | } |
| 143 | 144 | ||
| 144 | u64 GetTicksRemaining() override { | 145 | u64 GetTicksRemaining() override { |
| 145 | ASSERT_MSG(!parent.uses_wall_clock, "This should never happen - dynarmic ticking disabled"); | 146 | if (parent.uses_wall_clock) { |
| 147 | if (!IsInterrupted()) { | ||
| 148 | return minimum_run_cycles; | ||
| 149 | } | ||
| 150 | return 0U; | ||
| 151 | } | ||
| 146 | 152 | ||
| 147 | return std::max<s64>(parent.system.CoreTiming().GetDowncount(), 0); | 153 | return std::max<s64>(parent.system.CoreTiming().GetDowncount(), 0); |
| 148 | } | 154 | } |
| @@ -168,11 +174,15 @@ public: | |||
| 168 | parent.jit.load()->HaltExecution(hr); | 174 | parent.jit.load()->HaltExecution(hr); |
| 169 | } | 175 | } |
| 170 | 176 | ||
| 177 | bool IsInterrupted() { | ||
| 178 | return parent.system.Kernel().PhysicalCore(parent.core_index).IsInterrupted(); | ||
| 179 | } | ||
| 180 | |||
| 171 | ARM_Dynarmic_32& parent; | 181 | ARM_Dynarmic_32& parent; |
| 172 | Core::Memory::Memory& memory; | 182 | Core::Memory::Memory& memory; |
| 173 | std::size_t num_interpreted_instructions{}; | 183 | std::size_t num_interpreted_instructions{}; |
| 174 | bool debugger_enabled{}; | 184 | bool debugger_enabled{}; |
| 175 | static constexpr u64 minimum_run_cycles = 1000U; | 185 | static constexpr u64 minimum_run_cycles = 10000U; |
| 176 | }; | 186 | }; |
| 177 | 187 | ||
| 178 | std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable* page_table) const { | 188 | std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable* page_table) const { |
| @@ -180,19 +190,21 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable* | |||
| 180 | config.callbacks = cb.get(); | 190 | config.callbacks = cb.get(); |
| 181 | config.coprocessors[15] = cp15; | 191 | config.coprocessors[15] = cp15; |
| 182 | config.define_unpredictable_behaviour = true; | 192 | config.define_unpredictable_behaviour = true; |
| 183 | static constexpr std::size_t PAGE_BITS = 12; | 193 | static constexpr std::size_t YUZU_PAGEBITS = 12; |
| 184 | static constexpr std::size_t NUM_PAGE_TABLE_ENTRIES = 1 << (32 - PAGE_BITS); | 194 | static constexpr std::size_t NUM_PAGE_TABLE_ENTRIES = 1 << (32 - YUZU_PAGEBITS); |
| 185 | if (page_table) { | 195 | if (page_table) { |
| 186 | config.page_table = reinterpret_cast<std::array<std::uint8_t*, NUM_PAGE_TABLE_ENTRIES>*>( | 196 | config.page_table = reinterpret_cast<std::array<std::uint8_t*, NUM_PAGE_TABLE_ENTRIES>*>( |
| 187 | page_table->pointers.data()); | 197 | page_table->pointers.data()); |
| 198 | config.absolute_offset_page_table = true; | ||
| 199 | config.page_table_pointer_mask_bits = Common::PageTable::ATTRIBUTE_BITS; | ||
| 200 | config.detect_misaligned_access_via_page_table = 16 | 32 | 64 | 128; | ||
| 201 | config.only_detect_misalignment_via_page_table_on_page_boundary = true; | ||
| 202 | |||
| 188 | config.fastmem_pointer = page_table->fastmem_arena; | 203 | config.fastmem_pointer = page_table->fastmem_arena; |
| 204 | |||
| 205 | config.fastmem_exclusive_access = config.fastmem_pointer != nullptr; | ||
| 206 | config.recompile_on_exclusive_fastmem_failure = true; | ||
| 189 | } | 207 | } |
| 190 | config.absolute_offset_page_table = true; | ||
| 191 | config.page_table_pointer_mask_bits = Common::PageTable::ATTRIBUTE_BITS; | ||
| 192 | config.detect_misaligned_access_via_page_table = 16 | 32 | 64 | 128; | ||
| 193 | config.only_detect_misalignment_via_page_table_on_page_boundary = true; | ||
| 194 | config.fastmem_exclusive_access = true; | ||
| 195 | config.recompile_on_exclusive_fastmem_failure = true; | ||
| 196 | 208 | ||
| 197 | // Multi-process state | 209 | // Multi-process state |
| 198 | config.processor_id = core_index; | 210 | config.processor_id = core_index; |
| @@ -200,7 +212,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable* | |||
| 200 | 212 | ||
| 201 | // Timing | 213 | // Timing |
| 202 | config.wall_clock_cntpct = uses_wall_clock; | 214 | config.wall_clock_cntpct = uses_wall_clock; |
| 203 | config.enable_cycle_counting = !uses_wall_clock; | 215 | config.enable_cycle_counting = true; |
| 204 | 216 | ||
| 205 | // Code cache size | 217 | // Code cache size |
| 206 | config.code_cache_size = 512_MiB; | 218 | config.code_cache_size = 512_MiB; |
| @@ -244,6 +256,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable* | |||
| 244 | } | 256 | } |
| 245 | if (!Settings::values.cpuopt_fastmem) { | 257 | if (!Settings::values.cpuopt_fastmem) { |
| 246 | config.fastmem_pointer = nullptr; | 258 | config.fastmem_pointer = nullptr; |
| 259 | config.fastmem_exclusive_access = false; | ||
| 247 | } | 260 | } |
| 248 | if (!Settings::values.cpuopt_fastmem_exclusives) { | 261 | if (!Settings::values.cpuopt_fastmem_exclusives) { |
| 249 | config.fastmem_exclusive_access = false; | 262 | config.fastmem_exclusive_access = false; |
| @@ -311,11 +324,9 @@ void ARM_Dynarmic_32::RewindBreakpointInstruction() { | |||
| 311 | LoadContext(breakpoint_context); | 324 | LoadContext(breakpoint_context); |
| 312 | } | 325 | } |
| 313 | 326 | ||
| 314 | ARM_Dynarmic_32::ARM_Dynarmic_32(System& system_, CPUInterrupts& interrupt_handlers_, | 327 | ARM_Dynarmic_32::ARM_Dynarmic_32(System& system_, bool uses_wall_clock_, |
| 315 | bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_, | 328 | ExclusiveMonitor& exclusive_monitor_, std::size_t core_index_) |
| 316 | std::size_t core_index_) | 329 | : ARM_Interface{system_, uses_wall_clock_}, cb(std::make_unique<DynarmicCallbacks32>(*this)), |
| 317 | : ARM_Interface{system_, interrupt_handlers_, uses_wall_clock_}, | ||
| 318 | cb(std::make_unique<DynarmicCallbacks32>(*this)), | ||
| 319 | cp15(std::make_shared<DynarmicCP15>(*this)), core_index{core_index_}, | 330 | cp15(std::make_shared<DynarmicCP15>(*this)), core_index{core_index_}, |
| 320 | exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor_)}, | 331 | exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor_)}, |
| 321 | null_jit{MakeJit(nullptr)}, jit{null_jit.get()} {} | 332 | null_jit{MakeJit(nullptr)}, jit{null_jit.get()} {} |
| @@ -394,6 +405,10 @@ void ARM_Dynarmic_32::SignalInterrupt() { | |||
| 394 | jit.load()->HaltExecution(break_loop); | 405 | jit.load()->HaltExecution(break_loop); |
| 395 | } | 406 | } |
| 396 | 407 | ||
| 408 | void ARM_Dynarmic_32::ClearInterrupt() { | ||
| 409 | jit.load()->ClearHalt(break_loop); | ||
| 410 | } | ||
| 411 | |||
| 397 | void ARM_Dynarmic_32::ClearInstructionCache() { | 412 | void ARM_Dynarmic_32::ClearInstructionCache() { |
| 398 | jit.load()->ClearCache(); | 413 | jit.load()->ClearCache(); |
| 399 | } | 414 | } |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h index 346e9abf8..d24ba2289 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.h +++ b/src/core/arm/dynarmic/arm_dynarmic_32.h | |||
| @@ -28,8 +28,8 @@ class System; | |||
| 28 | 28 | ||
| 29 | class ARM_Dynarmic_32 final : public ARM_Interface { | 29 | class ARM_Dynarmic_32 final : public ARM_Interface { |
| 30 | public: | 30 | public: |
| 31 | ARM_Dynarmic_32(System& system_, CPUInterrupts& interrupt_handlers_, bool uses_wall_clock_, | 31 | ARM_Dynarmic_32(System& system_, bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_, |
| 32 | ExclusiveMonitor& exclusive_monitor_, std::size_t core_index_); | 32 | std::size_t core_index_); |
| 33 | ~ARM_Dynarmic_32() override; | 33 | ~ARM_Dynarmic_32() override; |
| 34 | 34 | ||
| 35 | void SetPC(u64 pc) override; | 35 | void SetPC(u64 pc) override; |
| @@ -56,6 +56,7 @@ public: | |||
| 56 | void LoadContext(const ThreadContext64& ctx) override {} | 56 | void LoadContext(const ThreadContext64& ctx) override {} |
| 57 | 57 | ||
| 58 | void SignalInterrupt() override; | 58 | void SignalInterrupt() override; |
| 59 | void ClearInterrupt() override; | ||
| 59 | void ClearExclusiveState() override; | 60 | void ClearExclusiveState() override; |
| 60 | 61 | ||
| 61 | void ClearInstructionCache() override; | 62 | void ClearInstructionCache() override; |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 1a4d37cbc..1d46f6d40 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp | |||
| @@ -10,7 +10,6 @@ | |||
| 10 | #include "common/logging/log.h" | 10 | #include "common/logging/log.h" |
| 11 | #include "common/page_table.h" | 11 | #include "common/page_table.h" |
| 12 | #include "common/settings.h" | 12 | #include "common/settings.h" |
| 13 | #include "core/arm/cpu_interrupt_handler.h" | ||
| 14 | #include "core/arm/dynarmic/arm_dynarmic_64.h" | 13 | #include "core/arm/dynarmic/arm_dynarmic_64.h" |
| 15 | #include "core/arm/dynarmic/arm_exclusive_monitor.h" | 14 | #include "core/arm/dynarmic/arm_exclusive_monitor.h" |
| 16 | #include "core/core.h" | 15 | #include "core/core.h" |
| @@ -166,7 +165,9 @@ public: | |||
| 166 | } | 165 | } |
| 167 | 166 | ||
| 168 | void AddTicks(u64 ticks) override { | 167 | void AddTicks(u64 ticks) override { |
| 169 | ASSERT_MSG(!parent.uses_wall_clock, "This should never happen - dynarmic ticking disabled"); | 168 | if (parent.uses_wall_clock) { |
| 169 | return; | ||
| 170 | } | ||
| 170 | 171 | ||
| 171 | // Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a | 172 | // Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a |
| 172 | // rough approximation of the amount of executed ticks in the system, it may be thrown off | 173 | // rough approximation of the amount of executed ticks in the system, it may be thrown off |
| @@ -181,7 +182,12 @@ public: | |||
| 181 | } | 182 | } |
| 182 | 183 | ||
| 183 | u64 GetTicksRemaining() override { | 184 | u64 GetTicksRemaining() override { |
| 184 | ASSERT_MSG(!parent.uses_wall_clock, "This should never happen - dynarmic ticking disabled"); | 185 | if (parent.uses_wall_clock) { |
| 186 | if (!IsInterrupted()) { | ||
| 187 | return minimum_run_cycles; | ||
| 188 | } | ||
| 189 | return 0U; | ||
| 190 | } | ||
| 185 | 191 | ||
| 186 | return std::max<s64>(parent.system.CoreTiming().GetDowncount(), 0); | 192 | return std::max<s64>(parent.system.CoreTiming().GetDowncount(), 0); |
| 187 | } | 193 | } |
| @@ -211,12 +217,16 @@ public: | |||
| 211 | parent.jit.load()->HaltExecution(hr); | 217 | parent.jit.load()->HaltExecution(hr); |
| 212 | } | 218 | } |
| 213 | 219 | ||
| 220 | bool IsInterrupted() { | ||
| 221 | return parent.system.Kernel().PhysicalCore(parent.core_index).IsInterrupted(); | ||
| 222 | } | ||
| 223 | |||
| 214 | ARM_Dynarmic_64& parent; | 224 | ARM_Dynarmic_64& parent; |
| 215 | Core::Memory::Memory& memory; | 225 | Core::Memory::Memory& memory; |
| 216 | u64 tpidrro_el0 = 0; | 226 | u64 tpidrro_el0 = 0; |
| 217 | u64 tpidr_el0 = 0; | 227 | u64 tpidr_el0 = 0; |
| 218 | bool debugger_enabled{}; | 228 | bool debugger_enabled{}; |
| 219 | static constexpr u64 minimum_run_cycles = 1000U; | 229 | static constexpr u64 minimum_run_cycles = 10000U; |
| 220 | }; | 230 | }; |
| 221 | 231 | ||
| 222 | std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable* page_table, | 232 | std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable* page_table, |
| @@ -240,7 +250,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable* | |||
| 240 | config.fastmem_address_space_bits = address_space_bits; | 250 | config.fastmem_address_space_bits = address_space_bits; |
| 241 | config.silently_mirror_fastmem = false; | 251 | config.silently_mirror_fastmem = false; |
| 242 | 252 | ||
| 243 | config.fastmem_exclusive_access = true; | 253 | config.fastmem_exclusive_access = config.fastmem_pointer != nullptr; |
| 244 | config.recompile_on_exclusive_fastmem_failure = true; | 254 | config.recompile_on_exclusive_fastmem_failure = true; |
| 245 | } | 255 | } |
| 246 | 256 | ||
| @@ -260,7 +270,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable* | |||
| 260 | 270 | ||
| 261 | // Timing | 271 | // Timing |
| 262 | config.wall_clock_cntpct = uses_wall_clock; | 272 | config.wall_clock_cntpct = uses_wall_clock; |
| 263 | config.enable_cycle_counting = !uses_wall_clock; | 273 | config.enable_cycle_counting = true; |
| 264 | 274 | ||
| 265 | // Code cache size | 275 | // Code cache size |
| 266 | config.code_cache_size = 512_MiB; | 276 | config.code_cache_size = 512_MiB; |
| @@ -304,6 +314,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable* | |||
| 304 | } | 314 | } |
| 305 | if (!Settings::values.cpuopt_fastmem) { | 315 | if (!Settings::values.cpuopt_fastmem) { |
| 306 | config.fastmem_pointer = nullptr; | 316 | config.fastmem_pointer = nullptr; |
| 317 | config.fastmem_exclusive_access = false; | ||
| 307 | } | 318 | } |
| 308 | if (!Settings::values.cpuopt_fastmem_exclusives) { | 319 | if (!Settings::values.cpuopt_fastmem_exclusives) { |
| 309 | config.fastmem_exclusive_access = false; | 320 | config.fastmem_exclusive_access = false; |
| @@ -371,10 +382,9 @@ void ARM_Dynarmic_64::RewindBreakpointInstruction() { | |||
| 371 | LoadContext(breakpoint_context); | 382 | LoadContext(breakpoint_context); |
| 372 | } | 383 | } |
| 373 | 384 | ||
| 374 | ARM_Dynarmic_64::ARM_Dynarmic_64(System& system_, CPUInterrupts& interrupt_handlers_, | 385 | ARM_Dynarmic_64::ARM_Dynarmic_64(System& system_, bool uses_wall_clock_, |
| 375 | bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_, | 386 | ExclusiveMonitor& exclusive_monitor_, std::size_t core_index_) |
| 376 | std::size_t core_index_) | 387 | : ARM_Interface{system_, uses_wall_clock_}, |
| 377 | : ARM_Interface{system_, interrupt_handlers_, uses_wall_clock_}, | ||
| 378 | cb(std::make_unique<DynarmicCallbacks64>(*this)), core_index{core_index_}, | 388 | cb(std::make_unique<DynarmicCallbacks64>(*this)), core_index{core_index_}, |
| 379 | exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor_)}, | 389 | exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor_)}, |
| 380 | null_jit{MakeJit(nullptr, 48)}, jit{null_jit.get()} {} | 390 | null_jit{MakeJit(nullptr, 48)}, jit{null_jit.get()} {} |
| @@ -461,6 +471,10 @@ void ARM_Dynarmic_64::SignalInterrupt() { | |||
| 461 | jit.load()->HaltExecution(break_loop); | 471 | jit.load()->HaltExecution(break_loop); |
| 462 | } | 472 | } |
| 463 | 473 | ||
| 474 | void ARM_Dynarmic_64::ClearInterrupt() { | ||
| 475 | jit.load()->ClearHalt(break_loop); | ||
| 476 | } | ||
| 477 | |||
| 464 | void ARM_Dynarmic_64::ClearInstructionCache() { | 478 | void ARM_Dynarmic_64::ClearInstructionCache() { |
| 465 | jit.load()->ClearCache(); | 479 | jit.load()->ClearCache(); |
| 466 | } | 480 | } |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h index c77a83ad7..ed1a5eb96 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.h +++ b/src/core/arm/dynarmic/arm_dynarmic_64.h | |||
| @@ -20,14 +20,13 @@ class Memory; | |||
| 20 | namespace Core { | 20 | namespace Core { |
| 21 | 21 | ||
| 22 | class DynarmicCallbacks64; | 22 | class DynarmicCallbacks64; |
| 23 | class CPUInterruptHandler; | ||
| 24 | class DynarmicExclusiveMonitor; | 23 | class DynarmicExclusiveMonitor; |
| 25 | class System; | 24 | class System; |
| 26 | 25 | ||
| 27 | class ARM_Dynarmic_64 final : public ARM_Interface { | 26 | class ARM_Dynarmic_64 final : public ARM_Interface { |
| 28 | public: | 27 | public: |
| 29 | ARM_Dynarmic_64(System& system_, CPUInterrupts& interrupt_handlers_, bool uses_wall_clock_, | 28 | ARM_Dynarmic_64(System& system_, bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_, |
| 30 | ExclusiveMonitor& exclusive_monitor_, std::size_t core_index_); | 29 | std::size_t core_index_); |
| 31 | ~ARM_Dynarmic_64() override; | 30 | ~ARM_Dynarmic_64() override; |
| 32 | 31 | ||
| 33 | void SetPC(u64 pc) override; | 32 | void SetPC(u64 pc) override; |
| @@ -50,6 +49,7 @@ public: | |||
| 50 | void LoadContext(const ThreadContext64& ctx) override; | 49 | void LoadContext(const ThreadContext64& ctx) override; |
| 51 | 50 | ||
| 52 | void SignalInterrupt() override; | 51 | void SignalInterrupt() override; |
| 52 | void ClearInterrupt() override; | ||
| 53 | void ClearExclusiveState() override; | 53 | void ClearExclusiveState() override; |
| 54 | 54 | ||
| 55 | void ClearInstructionCache() override; | 55 | void ClearInstructionCache() override; |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp b/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp index e9123c13d..200efe4db 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp | |||
| @@ -8,6 +8,10 @@ | |||
| 8 | #include "core/core.h" | 8 | #include "core/core.h" |
| 9 | #include "core/core_timing.h" | 9 | #include "core/core_timing.h" |
| 10 | 10 | ||
| 11 | #ifdef _MSC_VER | ||
| 12 | #include <intrin.h> | ||
| 13 | #endif | ||
| 14 | |||
| 11 | using Callback = Dynarmic::A32::Coprocessor::Callback; | 15 | using Callback = Dynarmic::A32::Coprocessor::Callback; |
| 12 | using CallbackOrAccessOneWord = Dynarmic::A32::Coprocessor::CallbackOrAccessOneWord; | 16 | using CallbackOrAccessOneWord = Dynarmic::A32::Coprocessor::CallbackOrAccessOneWord; |
| 13 | using CallbackOrAccessTwoWords = Dynarmic::A32::Coprocessor::CallbackOrAccessTwoWords; | 17 | using CallbackOrAccessTwoWords = Dynarmic::A32::Coprocessor::CallbackOrAccessTwoWords; |
| @@ -47,12 +51,31 @@ CallbackOrAccessOneWord DynarmicCP15::CompileSendOneWord(bool two, unsigned opc1 | |||
| 47 | switch (opc2) { | 51 | switch (opc2) { |
| 48 | case 4: | 52 | case 4: |
| 49 | // CP15_DATA_SYNC_BARRIER | 53 | // CP15_DATA_SYNC_BARRIER |
| 50 | // This is a dummy write, we ignore the value written here. | 54 | return Callback{ |
| 51 | return &dummy_value; | 55 | [](Dynarmic::A32::Jit*, void*, std::uint32_t, std::uint32_t) -> std::uint64_t { |
| 56 | #ifdef _MSC_VER | ||
| 57 | _mm_mfence(); | ||
| 58 | _mm_lfence(); | ||
| 59 | #else | ||
| 60 | asm volatile("mfence\n\tlfence\n\t" : : : "memory"); | ||
| 61 | #endif | ||
| 62 | return 0; | ||
| 63 | }, | ||
| 64 | std::nullopt, | ||
| 65 | }; | ||
| 52 | case 5: | 66 | case 5: |
| 53 | // CP15_DATA_MEMORY_BARRIER | 67 | // CP15_DATA_MEMORY_BARRIER |
| 54 | // This is a dummy write, we ignore the value written here. | 68 | return Callback{ |
| 55 | return &dummy_value; | 69 | [](Dynarmic::A32::Jit*, void*, std::uint32_t, std::uint32_t) -> std::uint64_t { |
| 70 | #ifdef _MSC_VER | ||
| 71 | _mm_mfence(); | ||
| 72 | #else | ||
| 73 | asm volatile("mfence\n\t" : : : "memory"); | ||
| 74 | #endif | ||
| 75 | return 0; | ||
| 76 | }, | ||
| 77 | std::nullopt, | ||
| 78 | }; | ||
| 56 | } | 79 | } |
| 57 | } | 80 | } |
| 58 | 81 | ||
diff --git a/src/core/arm/dynarmic/arm_dynarmic_cp15.h b/src/core/arm/dynarmic/arm_dynarmic_cp15.h index 5b2a51636..d90b3e568 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_cp15.h +++ b/src/core/arm/dynarmic/arm_dynarmic_cp15.h | |||
| @@ -35,6 +35,8 @@ public: | |||
| 35 | ARM_Dynarmic_32& parent; | 35 | ARM_Dynarmic_32& parent; |
| 36 | u32 uprw = 0; | 36 | u32 uprw = 0; |
| 37 | u32 uro = 0; | 37 | u32 uro = 0; |
| 38 | |||
| 39 | friend class ARM_Dynarmic_32; | ||
| 38 | }; | 40 | }; |
| 39 | 41 | ||
| 40 | } // namespace Core | 42 | } // namespace Core |
diff --git a/src/core/core.cpp b/src/core/core.cpp index ea32a4a8d..121092868 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -141,8 +141,6 @@ struct System::Impl { | |||
| 141 | core_timing.SyncPause(false); | 141 | core_timing.SyncPause(false); |
| 142 | is_paused = false; | 142 | is_paused = false; |
| 143 | 143 | ||
| 144 | audio_core->PauseSinks(false); | ||
| 145 | |||
| 146 | return status; | 144 | return status; |
| 147 | } | 145 | } |
| 148 | 146 | ||
| @@ -150,8 +148,6 @@ struct System::Impl { | |||
| 150 | std::unique_lock<std::mutex> lk(suspend_guard); | 148 | std::unique_lock<std::mutex> lk(suspend_guard); |
| 151 | status = SystemResultStatus::Success; | 149 | status = SystemResultStatus::Success; |
| 152 | 150 | ||
| 153 | audio_core->PauseSinks(true); | ||
| 154 | |||
| 155 | core_timing.SyncPause(true); | 151 | core_timing.SyncPause(true); |
| 156 | kernel.Suspend(true); | 152 | kernel.Suspend(true); |
| 157 | is_paused = true; | 153 | is_paused = true; |
| @@ -319,10 +315,19 @@ struct System::Impl { | |||
| 319 | if (app_loader->ReadTitle(name) != Loader::ResultStatus::Success) { | 315 | if (app_loader->ReadTitle(name) != Loader::ResultStatus::Success) { |
| 320 | LOG_ERROR(Core, "Failed to read title for ROM (Error {})", load_result); | 316 | LOG_ERROR(Core, "Failed to read title for ROM (Error {})", load_result); |
| 321 | } | 317 | } |
| 318 | |||
| 319 | std::string title_version; | ||
| 320 | const FileSys::PatchManager pm(program_id, system.GetFileSystemController(), | ||
| 321 | system.GetContentProvider()); | ||
| 322 | const auto metadata = pm.GetControlMetadata(); | ||
| 323 | if (metadata.first != nullptr) { | ||
| 324 | title_version = metadata.first->GetVersionString(); | ||
| 325 | } | ||
| 322 | if (auto room_member = room_network.GetRoomMember().lock()) { | 326 | if (auto room_member = room_network.GetRoomMember().lock()) { |
| 323 | Network::GameInfo game_info; | 327 | Network::GameInfo game_info; |
| 324 | game_info.name = name; | 328 | game_info.name = name; |
| 325 | game_info.id = program_id; | 329 | game_info.id = program_id; |
| 330 | game_info.version = title_version; | ||
| 326 | room_member->SendGameInfo(game_info); | 331 | room_member->SendGameInfo(game_info); |
| 327 | } | 332 | } |
| 328 | 333 | ||
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index 8d1ee3b51..f6c4567ba 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp | |||
| @@ -73,7 +73,6 @@ void CoreTiming::Shutdown() { | |||
| 73 | if (timer_thread) { | 73 | if (timer_thread) { |
| 74 | timer_thread->join(); | 74 | timer_thread->join(); |
| 75 | } | 75 | } |
| 76 | pause_callbacks.clear(); | ||
| 77 | ClearPendingEvents(); | 76 | ClearPendingEvents(); |
| 78 | timer_thread.reset(); | 77 | timer_thread.reset(); |
| 79 | has_started = false; | 78 | has_started = false; |
| @@ -86,10 +85,6 @@ void CoreTiming::Pause(bool is_paused) { | |||
| 86 | if (!is_paused) { | 85 | if (!is_paused) { |
| 87 | pause_end_time = GetGlobalTimeNs().count(); | 86 | pause_end_time = GetGlobalTimeNs().count(); |
| 88 | } | 87 | } |
| 89 | |||
| 90 | for (auto& cb : pause_callbacks) { | ||
| 91 | cb(is_paused); | ||
| 92 | } | ||
| 93 | } | 88 | } |
| 94 | 89 | ||
| 95 | void CoreTiming::SyncPause(bool is_paused) { | 90 | void CoreTiming::SyncPause(bool is_paused) { |
| @@ -110,10 +105,6 @@ void CoreTiming::SyncPause(bool is_paused) { | |||
| 110 | if (!is_paused) { | 105 | if (!is_paused) { |
| 111 | pause_end_time = GetGlobalTimeNs().count(); | 106 | pause_end_time = GetGlobalTimeNs().count(); |
| 112 | } | 107 | } |
| 113 | |||
| 114 | for (auto& cb : pause_callbacks) { | ||
| 115 | cb(is_paused); | ||
| 116 | } | ||
| 117 | } | 108 | } |
| 118 | 109 | ||
| 119 | bool CoreTiming::IsRunning() const { | 110 | bool CoreTiming::IsRunning() const { |
| @@ -223,11 +214,6 @@ void CoreTiming::RemoveEvent(const std::shared_ptr<EventType>& event_type) { | |||
| 223 | } | 214 | } |
| 224 | } | 215 | } |
| 225 | 216 | ||
| 226 | void CoreTiming::RegisterPauseCallback(PauseCallback&& callback) { | ||
| 227 | std::scoped_lock lock{basic_lock}; | ||
| 228 | pause_callbacks.emplace_back(std::move(callback)); | ||
| 229 | } | ||
| 230 | |||
| 231 | std::optional<s64> CoreTiming::Advance() { | 217 | std::optional<s64> CoreTiming::Advance() { |
| 232 | std::scoped_lock lock{advance_lock, basic_lock}; | 218 | std::scoped_lock lock{advance_lock, basic_lock}; |
| 233 | global_timer = GetGlobalTimeNs().count(); | 219 | global_timer = GetGlobalTimeNs().count(); |
diff --git a/src/core/core_timing.h b/src/core/core_timing.h index 6aa3ae923..3259397b2 100644 --- a/src/core/core_timing.h +++ b/src/core/core_timing.h | |||
| @@ -22,7 +22,6 @@ namespace Core::Timing { | |||
| 22 | /// A callback that may be scheduled for a particular core timing event. | 22 | /// A callback that may be scheduled for a particular core timing event. |
| 23 | using TimedCallback = std::function<std::optional<std::chrono::nanoseconds>( | 23 | using TimedCallback = std::function<std::optional<std::chrono::nanoseconds>( |
| 24 | std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late)>; | 24 | std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late)>; |
| 25 | using PauseCallback = std::function<void(bool paused)>; | ||
| 26 | 25 | ||
| 27 | /// Contains the characteristics of a particular event. | 26 | /// Contains the characteristics of a particular event. |
| 28 | struct EventType { | 27 | struct EventType { |
| @@ -134,9 +133,6 @@ public: | |||
| 134 | /// Checks for events manually and returns time in nanoseconds for next event, threadsafe. | 133 | /// Checks for events manually and returns time in nanoseconds for next event, threadsafe. |
| 135 | std::optional<s64> Advance(); | 134 | std::optional<s64> Advance(); |
| 136 | 135 | ||
| 137 | /// Register a callback function to be called when coretiming pauses. | ||
| 138 | void RegisterPauseCallback(PauseCallback&& callback); | ||
| 139 | |||
| 140 | private: | 136 | private: |
| 141 | struct Event; | 137 | struct Event; |
| 142 | 138 | ||
| @@ -176,8 +172,6 @@ private: | |||
| 176 | /// Cycle timing | 172 | /// Cycle timing |
| 177 | u64 ticks{}; | 173 | u64 ticks{}; |
| 178 | s64 downcount{}; | 174 | s64 downcount{}; |
| 179 | |||
| 180 | std::vector<PauseCallback> pause_callbacks{}; | ||
| 181 | }; | 175 | }; |
| 182 | 176 | ||
| 183 | /// Creates a core timing event with the given name and callback. | 177 | /// Creates a core timing event with the given name and callback. |
diff --git a/src/core/debugger/debugger.cpp b/src/core/debugger/debugger.cpp index ac64d2f9d..e42bdd17d 100644 --- a/src/core/debugger/debugger.cpp +++ b/src/core/debugger/debugger.cpp | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include "core/debugger/debugger_interface.h" | 15 | #include "core/debugger/debugger_interface.h" |
| 16 | #include "core/debugger/gdbstub.h" | 16 | #include "core/debugger/gdbstub.h" |
| 17 | #include "core/hle/kernel/global_scheduler_context.h" | 17 | #include "core/hle/kernel/global_scheduler_context.h" |
| 18 | #include "core/hle/kernel/k_scheduler.h" | ||
| 18 | 19 | ||
| 19 | template <typename Readable, typename Buffer, typename Callback> | 20 | template <typename Readable, typename Buffer, typename Callback> |
| 20 | static void AsyncReceiveInto(Readable& r, Buffer& buffer, Callback&& c) { | 21 | static void AsyncReceiveInto(Readable& r, Buffer& buffer, Callback&& c) { |
| @@ -230,13 +231,12 @@ private: | |||
| 230 | } | 231 | } |
| 231 | 232 | ||
| 232 | void PauseEmulation() { | 233 | void PauseEmulation() { |
| 234 | Kernel::KScopedSchedulerLock sl{system.Kernel()}; | ||
| 235 | |||
| 233 | // Put all threads to sleep on next scheduler round. | 236 | // Put all threads to sleep on next scheduler round. |
| 234 | for (auto* thread : ThreadList()) { | 237 | for (auto* thread : ThreadList()) { |
| 235 | thread->RequestSuspend(Kernel::SuspendType::Debug); | 238 | thread->RequestSuspend(Kernel::SuspendType::Debug); |
| 236 | } | 239 | } |
| 237 | |||
| 238 | // Signal an interrupt so that scheduler will fire. | ||
| 239 | system.Kernel().InterruptAllPhysicalCores(); | ||
| 240 | } | 240 | } |
| 241 | 241 | ||
| 242 | void ResumeEmulation(Kernel::KThread* except = nullptr) { | 242 | void ResumeEmulation(Kernel::KThread* except = nullptr) { |
| @@ -253,7 +253,8 @@ private: | |||
| 253 | 253 | ||
| 254 | template <typename Callback> | 254 | template <typename Callback> |
| 255 | void MarkResumed(Callback&& cb) { | 255 | void MarkResumed(Callback&& cb) { |
| 256 | std::scoped_lock lk{connection_lock}; | 256 | Kernel::KScopedSchedulerLock sl{system.Kernel()}; |
| 257 | std::scoped_lock cl{connection_lock}; | ||
| 257 | stopped = false; | 258 | stopped = false; |
| 258 | cb(); | 259 | cb(); |
| 259 | } | 260 | } |
diff --git a/src/core/file_sys/ips_layer.cpp b/src/core/file_sys/ips_layer.cpp index 4b35ca82f..5aab428bb 100644 --- a/src/core/file_sys/ips_layer.cpp +++ b/src/core/file_sys/ips_layer.cpp | |||
| @@ -217,9 +217,7 @@ void IPSwitchCompiler::Parse() { | |||
| 217 | break; | 217 | break; |
| 218 | } else if (StartsWith(line, "@nsobid-")) { | 218 | } else if (StartsWith(line, "@nsobid-")) { |
| 219 | // NSO Build ID Specifier | 219 | // NSO Build ID Specifier |
| 220 | auto raw_build_id = line.substr(8); | 220 | const auto raw_build_id = fmt::format("{:0<64}", line.substr(8)); |
| 221 | if (raw_build_id.size() != 0x40) | ||
| 222 | raw_build_id.resize(0x40, '0'); | ||
| 223 | nso_build_id = Common::HexStringToArray<0x20>(raw_build_id); | 221 | nso_build_id = Common::HexStringToArray<0x20>(raw_build_id); |
| 224 | } else if (StartsWith(line, "#")) { | 222 | } else if (StartsWith(line, "#")) { |
| 225 | // Mandatory Comment | 223 | // Mandatory Comment |
| @@ -287,7 +285,8 @@ void IPSwitchCompiler::Parse() { | |||
| 287 | std::copy(value.begin(), value.end(), std::back_inserter(replace)); | 285 | std::copy(value.begin(), value.end(), std::back_inserter(replace)); |
| 288 | } else { | 286 | } else { |
| 289 | // hex replacement | 287 | // hex replacement |
| 290 | const auto value = patch_line.substr(9); | 288 | const auto value = |
| 289 | patch_line.substr(9, patch_line.find_first_of(" /\r\n", 9) - 9); | ||
| 291 | replace = Common::HexStringToVector(value, is_little_endian); | 290 | replace = Common::HexStringToVector(value, is_little_endian); |
| 292 | } | 291 | } |
| 293 | 292 | ||
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index bd525b26c..4c80e13a9 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp | |||
| @@ -191,6 +191,7 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const { | |||
| 191 | std::vector<VirtualFile> PatchManager::CollectPatches(const std::vector<VirtualDir>& patch_dirs, | 191 | std::vector<VirtualFile> PatchManager::CollectPatches(const std::vector<VirtualDir>& patch_dirs, |
| 192 | const std::string& build_id) const { | 192 | const std::string& build_id) const { |
| 193 | const auto& disabled = Settings::values.disabled_addons[title_id]; | 193 | const auto& disabled = Settings::values.disabled_addons[title_id]; |
| 194 | const auto nso_build_id = fmt::format("{:0<64}", build_id); | ||
| 194 | 195 | ||
| 195 | std::vector<VirtualFile> out; | 196 | std::vector<VirtualFile> out; |
| 196 | out.reserve(patch_dirs.size()); | 197 | out.reserve(patch_dirs.size()); |
| @@ -203,21 +204,18 @@ std::vector<VirtualFile> PatchManager::CollectPatches(const std::vector<VirtualD | |||
| 203 | for (const auto& file : exefs_dir->GetFiles()) { | 204 | for (const auto& file : exefs_dir->GetFiles()) { |
| 204 | if (file->GetExtension() == "ips") { | 205 | if (file->GetExtension() == "ips") { |
| 205 | auto name = file->GetName(); | 206 | auto name = file->GetName(); |
| 206 | const auto p1 = name.substr(0, name.find('.')); | ||
| 207 | const auto this_build_id = p1.substr(0, p1.find_last_not_of('0') + 1); | ||
| 208 | 207 | ||
| 209 | if (build_id == this_build_id) | 208 | const auto this_build_id = |
| 209 | fmt::format("{:0<64}", name.substr(0, name.find('.'))); | ||
| 210 | if (nso_build_id == this_build_id) | ||
| 210 | out.push_back(file); | 211 | out.push_back(file); |
| 211 | } else if (file->GetExtension() == "pchtxt") { | 212 | } else if (file->GetExtension() == "pchtxt") { |
| 212 | IPSwitchCompiler compiler{file}; | 213 | IPSwitchCompiler compiler{file}; |
| 213 | if (!compiler.IsValid()) | 214 | if (!compiler.IsValid()) |
| 214 | continue; | 215 | continue; |
| 215 | 216 | ||
| 216 | auto this_build_id = Common::HexToString(compiler.GetBuildID()); | 217 | const auto this_build_id = Common::HexToString(compiler.GetBuildID()); |
| 217 | this_build_id = | 218 | if (nso_build_id == this_build_id) |
| 218 | this_build_id.substr(0, this_build_id.find_last_not_of('0') + 1); | ||
| 219 | |||
| 220 | if (build_id == this_build_id) | ||
| 221 | out.push_back(file); | 219 | out.push_back(file); |
| 222 | } | 220 | } |
| 223 | } | 221 | } |
diff --git a/src/core/file_sys/system_archive/shared_font.cpp b/src/core/file_sys/system_archive/shared_font.cpp index f841988ff..3210583f0 100644 --- a/src/core/file_sys/system_archive/shared_font.cpp +++ b/src/core/file_sys/system_archive/shared_font.cpp | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | #include "core/file_sys/system_archive/data/font_standard.h" | 9 | #include "core/file_sys/system_archive/data/font_standard.h" |
| 10 | #include "core/file_sys/system_archive/shared_font.h" | 10 | #include "core/file_sys/system_archive/shared_font.h" |
| 11 | #include "core/file_sys/vfs_vector.h" | 11 | #include "core/file_sys/vfs_vector.h" |
| 12 | #include "core/hle/service/ns/pl_u.h" | 12 | #include "core/hle/service/ns/iplatform_service_manager.h" |
| 13 | 13 | ||
| 14 | namespace FileSys::SystemArchive { | 14 | namespace FileSys::SystemArchive { |
| 15 | 15 | ||
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 8c3895937..01c43be93 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "common/thread.h" | ||
| 4 | #include "core/hid/emulated_controller.h" | 5 | #include "core/hid/emulated_controller.h" |
| 5 | #include "core/hid/input_converter.h" | 6 | #include "core/hid/input_converter.h" |
| 6 | 7 | ||
| @@ -84,23 +85,26 @@ void EmulatedController::ReloadFromSettings() { | |||
| 84 | motion_params[index] = Common::ParamPackage(player.motions[index]); | 85 | motion_params[index] = Common::ParamPackage(player.motions[index]); |
| 85 | } | 86 | } |
| 86 | 87 | ||
| 88 | controller.colors_state.fullkey = { | ||
| 89 | .body = GetNpadColor(player.body_color_left), | ||
| 90 | .button = GetNpadColor(player.button_color_left), | ||
| 91 | }; | ||
| 87 | controller.colors_state.left = { | 92 | controller.colors_state.left = { |
| 88 | .body = player.body_color_left, | 93 | .body = GetNpadColor(player.body_color_left), |
| 89 | .button = player.button_color_left, | 94 | .button = GetNpadColor(player.button_color_left), |
| 90 | }; | 95 | }; |
| 91 | 96 | controller.colors_state.left = { | |
| 92 | controller.colors_state.right = { | 97 | .body = GetNpadColor(player.body_color_right), |
| 93 | .body = player.body_color_right, | 98 | .button = GetNpadColor(player.button_color_right), |
| 94 | .button = player.button_color_right, | ||
| 95 | }; | 99 | }; |
| 96 | 100 | ||
| 97 | controller.colors_state.fullkey = controller.colors_state.left; | ||
| 98 | |||
| 99 | // Other or debug controller should always be a pro controller | 101 | // Other or debug controller should always be a pro controller |
| 100 | if (npad_id_type != NpadIdType::Other) { | 102 | if (npad_id_type != NpadIdType::Other) { |
| 101 | SetNpadStyleIndex(MapSettingsTypeToNPad(player.controller_type)); | 103 | SetNpadStyleIndex(MapSettingsTypeToNPad(player.controller_type)); |
| 104 | original_npad_type = npad_type; | ||
| 102 | } else { | 105 | } else { |
| 103 | SetNpadStyleIndex(NpadStyleIndex::ProController); | 106 | SetNpadStyleIndex(NpadStyleIndex::ProController); |
| 107 | original_npad_type = npad_type; | ||
| 104 | } | 108 | } |
| 105 | 109 | ||
| 106 | if (player.connected) { | 110 | if (player.connected) { |
| @@ -352,6 +356,7 @@ void EmulatedController::DisableConfiguration() { | |||
| 352 | Disconnect(); | 356 | Disconnect(); |
| 353 | } | 357 | } |
| 354 | SetNpadStyleIndex(tmp_npad_type); | 358 | SetNpadStyleIndex(tmp_npad_type); |
| 359 | original_npad_type = tmp_npad_type; | ||
| 355 | } | 360 | } |
| 356 | 361 | ||
| 357 | // Apply temporary connected status to the real controller | 362 | // Apply temporary connected status to the real controller |
| @@ -557,6 +562,16 @@ void EmulatedController::SetButton(const Common::Input::CallbackStatus& callback | |||
| 557 | return; | 562 | return; |
| 558 | } | 563 | } |
| 559 | 564 | ||
| 565 | // GC controllers have triggers not buttons | ||
| 566 | if (npad_type == NpadStyleIndex::GameCube) { | ||
| 567 | if (index == Settings::NativeButton::ZR) { | ||
| 568 | return; | ||
| 569 | } | ||
| 570 | if (index == Settings::NativeButton::ZL) { | ||
| 571 | return; | ||
| 572 | } | ||
| 573 | } | ||
| 574 | |||
| 560 | switch (index) { | 575 | switch (index) { |
| 561 | case Settings::NativeButton::A: | 576 | case Settings::NativeButton::A: |
| 562 | controller.npad_button_state.a.Assign(current_status.value); | 577 | controller.npad_button_state.a.Assign(current_status.value); |
| @@ -733,6 +748,11 @@ void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callbac | |||
| 733 | return; | 748 | return; |
| 734 | } | 749 | } |
| 735 | 750 | ||
| 751 | // Only GC controllers have analog triggers | ||
| 752 | if (npad_type != NpadStyleIndex::GameCube) { | ||
| 753 | return; | ||
| 754 | } | ||
| 755 | |||
| 736 | const auto& trigger = controller.trigger_values[index]; | 756 | const auto& trigger = controller.trigger_values[index]; |
| 737 | 757 | ||
| 738 | switch (index) { | 758 | switch (index) { |
| @@ -949,6 +969,9 @@ bool EmulatedController::TestVibration(std::size_t device_index) { | |||
| 949 | // Send a slight vibration to test for rumble support | 969 | // Send a slight vibration to test for rumble support |
| 950 | output_devices[device_index]->SetVibration(test_vibration); | 970 | output_devices[device_index]->SetVibration(test_vibration); |
| 951 | 971 | ||
| 972 | // Wait for about 15ms to ensure the controller is ready for the stop command | ||
| 973 | std::this_thread::sleep_for(std::chrono::milliseconds(15)); | ||
| 974 | |||
| 952 | // Stop any vibration and return the result | 975 | // Stop any vibration and return the result |
| 953 | return output_devices[device_index]->SetVibration(zero_vibration) == | 976 | return output_devices[device_index]->SetVibration(zero_vibration) == |
| 954 | Common::Input::VibrationError::None; | 977 | Common::Input::VibrationError::None; |
| @@ -999,13 +1022,27 @@ void EmulatedController::SetSupportedNpadStyleTag(NpadStyleTag supported_styles) | |||
| 999 | if (!is_connected) { | 1022 | if (!is_connected) { |
| 1000 | return; | 1023 | return; |
| 1001 | } | 1024 | } |
| 1025 | |||
| 1026 | // Attempt to reconnect with the original type | ||
| 1027 | if (npad_type != original_npad_type) { | ||
| 1028 | Disconnect(); | ||
| 1029 | const auto current_npad_type = npad_type; | ||
| 1030 | SetNpadStyleIndex(original_npad_type); | ||
| 1031 | if (IsControllerSupported()) { | ||
| 1032 | Connect(); | ||
| 1033 | return; | ||
| 1034 | } | ||
| 1035 | SetNpadStyleIndex(current_npad_type); | ||
| 1036 | Connect(); | ||
| 1037 | } | ||
| 1038 | |||
| 1002 | if (IsControllerSupported()) { | 1039 | if (IsControllerSupported()) { |
| 1003 | return; | 1040 | return; |
| 1004 | } | 1041 | } |
| 1005 | 1042 | ||
| 1006 | Disconnect(); | 1043 | Disconnect(); |
| 1007 | 1044 | ||
| 1008 | // Fallback fullkey controllers to Pro controllers | 1045 | // Fallback Fullkey controllers to Pro controllers |
| 1009 | if (IsControllerFullkey() && supported_style_tag.fullkey) { | 1046 | if (IsControllerFullkey() && supported_style_tag.fullkey) { |
| 1010 | LOG_WARNING(Service_HID, "Reconnecting controller type {} as Pro controller", npad_type); | 1047 | LOG_WARNING(Service_HID, "Reconnecting controller type {} as Pro controller", npad_type); |
| 1011 | SetNpadStyleIndex(NpadStyleIndex::ProController); | 1048 | SetNpadStyleIndex(NpadStyleIndex::ProController); |
| @@ -1013,6 +1050,22 @@ void EmulatedController::SetSupportedNpadStyleTag(NpadStyleTag supported_styles) | |||
| 1013 | return; | 1050 | return; |
| 1014 | } | 1051 | } |
| 1015 | 1052 | ||
| 1053 | // Fallback Dual joycon controllers to Pro controllers | ||
| 1054 | if (npad_type == NpadStyleIndex::JoyconDual && supported_style_tag.fullkey) { | ||
| 1055 | LOG_WARNING(Service_HID, "Reconnecting controller type {} as Pro controller", npad_type); | ||
| 1056 | SetNpadStyleIndex(NpadStyleIndex::ProController); | ||
| 1057 | Connect(); | ||
| 1058 | return; | ||
| 1059 | } | ||
| 1060 | |||
| 1061 | // Fallback Pro controllers to Dual joycon | ||
| 1062 | if (npad_type == NpadStyleIndex::ProController && supported_style_tag.joycon_dual) { | ||
| 1063 | LOG_WARNING(Service_HID, "Reconnecting controller type {} as Dual Joycons", npad_type); | ||
| 1064 | SetNpadStyleIndex(NpadStyleIndex::JoyconDual); | ||
| 1065 | Connect(); | ||
| 1066 | return; | ||
| 1067 | } | ||
| 1068 | |||
| 1016 | LOG_ERROR(Service_HID, "Controller type {} is not supported. Disconnecting controller", | 1069 | LOG_ERROR(Service_HID, "Controller type {} is not supported. Disconnecting controller", |
| 1017 | npad_type); | 1070 | npad_type); |
| 1018 | } | 1071 | } |
| @@ -1310,6 +1363,15 @@ const CameraState& EmulatedController::GetCamera() const { | |||
| 1310 | return controller.camera_state; | 1363 | return controller.camera_state; |
| 1311 | } | 1364 | } |
| 1312 | 1365 | ||
| 1366 | NpadColor EmulatedController::GetNpadColor(u32 color) { | ||
| 1367 | return { | ||
| 1368 | .r = static_cast<u8>((color >> 16) & 0xFF), | ||
| 1369 | .g = static_cast<u8>((color >> 8) & 0xFF), | ||
| 1370 | .b = static_cast<u8>(color & 0xFF), | ||
| 1371 | .a = 0xff, | ||
| 1372 | }; | ||
| 1373 | } | ||
| 1374 | |||
| 1313 | void EmulatedController::TriggerOnChange(ControllerTriggerType type, bool is_npad_service_update) { | 1375 | void EmulatedController::TriggerOnChange(ControllerTriggerType type, bool is_npad_service_update) { |
| 1314 | std::scoped_lock lock{callback_mutex}; | 1376 | std::scoped_lock lock{callback_mutex}; |
| 1315 | for (const auto& poller_pair : callback_list) { | 1377 | for (const auto& poller_pair : callback_list) { |
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index 823c1700c..c3aa8f9d3 100644 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h | |||
| @@ -425,6 +425,13 @@ private: | |||
| 425 | void SetCamera(const Common::Input::CallbackStatus& callback); | 425 | void SetCamera(const Common::Input::CallbackStatus& callback); |
| 426 | 426 | ||
| 427 | /** | 427 | /** |
| 428 | * Converts a color format from bgra to rgba | ||
| 429 | * @param color in bgra format | ||
| 430 | * @return NpadColor in rgba format | ||
| 431 | */ | ||
| 432 | NpadColor GetNpadColor(u32 color); | ||
| 433 | |||
| 434 | /** | ||
| 428 | * Triggers a callback that something has changed on the controller status | 435 | * Triggers a callback that something has changed on the controller status |
| 429 | * @param type Input type of the event to trigger | 436 | * @param type Input type of the event to trigger |
| 430 | * @param is_service_update indicates if this event should only be sent to HID services | 437 | * @param is_service_update indicates if this event should only be sent to HID services |
| @@ -433,6 +440,7 @@ private: | |||
| 433 | 440 | ||
| 434 | const NpadIdType npad_id_type; | 441 | const NpadIdType npad_id_type; |
| 435 | NpadStyleIndex npad_type{NpadStyleIndex::None}; | 442 | NpadStyleIndex npad_type{NpadStyleIndex::None}; |
| 443 | NpadStyleIndex original_npad_type{NpadStyleIndex::None}; | ||
| 436 | NpadStyleTag supported_style_tag{NpadStyleSet::All}; | 444 | NpadStyleTag supported_style_tag{NpadStyleSet::All}; |
| 437 | bool is_connected{false}; | 445 | bool is_connected{false}; |
| 438 | bool is_configuring{false}; | 446 | bool is_configuring{false}; |
diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h index e49223016..e3b1cfbc6 100644 --- a/src/core/hid/hid_types.h +++ b/src/core/hid/hid_types.h | |||
| @@ -327,10 +327,18 @@ struct TouchState { | |||
| 327 | }; | 327 | }; |
| 328 | static_assert(sizeof(TouchState) == 0x28, "Touchstate is an invalid size"); | 328 | static_assert(sizeof(TouchState) == 0x28, "Touchstate is an invalid size"); |
| 329 | 329 | ||
| 330 | struct NpadColor { | ||
| 331 | u8 r{}; | ||
| 332 | u8 g{}; | ||
| 333 | u8 b{}; | ||
| 334 | u8 a{}; | ||
| 335 | }; | ||
| 336 | static_assert(sizeof(NpadColor) == 4, "NpadColor is an invalid size"); | ||
| 337 | |||
| 330 | // This is nn::hid::NpadControllerColor | 338 | // This is nn::hid::NpadControllerColor |
| 331 | struct NpadControllerColor { | 339 | struct NpadControllerColor { |
| 332 | u32 body{}; | 340 | NpadColor body{}; |
| 333 | u32 button{}; | 341 | NpadColor button{}; |
| 334 | }; | 342 | }; |
| 335 | static_assert(sizeof(NpadControllerColor) == 8, "NpadControllerColor is an invalid size"); | 343 | static_assert(sizeof(NpadControllerColor) == 8, "NpadControllerColor is an invalid size"); |
| 336 | 344 | ||
diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp index 68d143a01..52fb69e9c 100644 --- a/src/core/hid/input_converter.cpp +++ b/src/core/hid/input_converter.cpp | |||
| @@ -52,6 +52,9 @@ Common::Input::ButtonStatus TransformToButton(const Common::Input::CallbackStatu | |||
| 52 | Common::Input::ButtonStatus status{}; | 52 | Common::Input::ButtonStatus status{}; |
| 53 | switch (callback.type) { | 53 | switch (callback.type) { |
| 54 | case Common::Input::InputType::Analog: | 54 | case Common::Input::InputType::Analog: |
| 55 | status.value = TransformToTrigger(callback).pressed.value; | ||
| 56 | status.toggle = callback.analog_status.properties.toggle; | ||
| 57 | break; | ||
| 55 | case Common::Input::InputType::Trigger: | 58 | case Common::Input::InputType::Trigger: |
| 56 | status.value = TransformToTrigger(callback).pressed.value; | 59 | status.value = TransformToTrigger(callback).pressed.value; |
| 57 | break; | 60 | break; |
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index f4072e1c3..ce7fa8275 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -17,7 +17,6 @@ | |||
| 17 | #include "common/thread.h" | 17 | #include "common/thread.h" |
| 18 | #include "common/thread_worker.h" | 18 | #include "common/thread_worker.h" |
| 19 | #include "core/arm/arm_interface.h" | 19 | #include "core/arm/arm_interface.h" |
| 20 | #include "core/arm/cpu_interrupt_handler.h" | ||
| 21 | #include "core/arm/exclusive_monitor.h" | 20 | #include "core/arm/exclusive_monitor.h" |
| 22 | #include "core/core.h" | 21 | #include "core/core.h" |
| 23 | #include "core/core_timing.h" | 22 | #include "core/core_timing.h" |
| @@ -82,7 +81,7 @@ struct KernelCore::Impl { | |||
| 82 | 81 | ||
| 83 | void InitializeCores() { | 82 | void InitializeCores() { |
| 84 | for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) { | 83 | for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) { |
| 85 | cores[core_id].Initialize((*current_process).Is64BitProcess()); | 84 | cores[core_id]->Initialize((*current_process).Is64BitProcess()); |
| 86 | system.Memory().SetCurrentPageTable(*current_process, core_id); | 85 | system.Memory().SetCurrentPageTable(*current_process, core_id); |
| 87 | } | 86 | } |
| 88 | } | 87 | } |
| @@ -100,7 +99,9 @@ struct KernelCore::Impl { | |||
| 100 | next_user_process_id = KProcess::ProcessIDMin; | 99 | next_user_process_id = KProcess::ProcessIDMin; |
| 101 | next_thread_id = 1; | 100 | next_thread_id = 1; |
| 102 | 101 | ||
| 103 | cores.clear(); | 102 | for (auto& core : cores) { |
| 103 | core = nullptr; | ||
| 104 | } | ||
| 104 | 105 | ||
| 105 | global_handle_table->Finalize(); | 106 | global_handle_table->Finalize(); |
| 106 | global_handle_table.reset(); | 107 | global_handle_table.reset(); |
| @@ -199,7 +200,7 @@ struct KernelCore::Impl { | |||
| 199 | const s32 core{static_cast<s32>(i)}; | 200 | const s32 core{static_cast<s32>(i)}; |
| 200 | 201 | ||
| 201 | schedulers[i] = std::make_unique<Kernel::KScheduler>(system.Kernel()); | 202 | schedulers[i] = std::make_unique<Kernel::KScheduler>(system.Kernel()); |
| 202 | cores.emplace_back(i, system, *schedulers[i], interrupts); | 203 | cores[i] = std::make_unique<Kernel::PhysicalCore>(i, system, *schedulers[i]); |
| 203 | 204 | ||
| 204 | auto* main_thread{Kernel::KThread::Create(system.Kernel())}; | 205 | auto* main_thread{Kernel::KThread::Create(system.Kernel())}; |
| 205 | main_thread->SetName(fmt::format("MainThread:{}", core)); | 206 | main_thread->SetName(fmt::format("MainThread:{}", core)); |
| @@ -761,7 +762,7 @@ struct KernelCore::Impl { | |||
| 761 | std::unordered_set<KAutoObject*> registered_in_use_objects; | 762 | std::unordered_set<KAutoObject*> registered_in_use_objects; |
| 762 | 763 | ||
| 763 | std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; | 764 | std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; |
| 764 | std::vector<Kernel::PhysicalCore> cores; | 765 | std::array<std::unique_ptr<Kernel::PhysicalCore>, Core::Hardware::NUM_CPU_CORES> cores; |
| 765 | 766 | ||
| 766 | // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others | 767 | // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others |
| 767 | std::atomic<u32> next_host_thread_id{Core::Hardware::NUM_CPU_CORES}; | 768 | std::atomic<u32> next_host_thread_id{Core::Hardware::NUM_CPU_CORES}; |
| @@ -785,7 +786,6 @@ struct KernelCore::Impl { | |||
| 785 | Common::ThreadWorker service_threads_manager; | 786 | Common::ThreadWorker service_threads_manager; |
| 786 | 787 | ||
| 787 | std::array<KThread*, Core::Hardware::NUM_CPU_CORES> shutdown_threads; | 788 | std::array<KThread*, Core::Hardware::NUM_CPU_CORES> shutdown_threads; |
| 788 | std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES> interrupts{}; | ||
| 789 | std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{}; | 789 | std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{}; |
| 790 | 790 | ||
| 791 | bool is_multicore{}; | 791 | bool is_multicore{}; |
| @@ -874,11 +874,11 @@ const Kernel::KScheduler& KernelCore::Scheduler(std::size_t id) const { | |||
| 874 | } | 874 | } |
| 875 | 875 | ||
| 876 | Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) { | 876 | Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) { |
| 877 | return impl->cores[id]; | 877 | return *impl->cores[id]; |
| 878 | } | 878 | } |
| 879 | 879 | ||
| 880 | const Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) const { | 880 | const Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) const { |
| 881 | return impl->cores[id]; | 881 | return *impl->cores[id]; |
| 882 | } | 882 | } |
| 883 | 883 | ||
| 884 | size_t KernelCore::CurrentPhysicalCoreIndex() const { | 884 | size_t KernelCore::CurrentPhysicalCoreIndex() const { |
| @@ -890,11 +890,11 @@ size_t KernelCore::CurrentPhysicalCoreIndex() const { | |||
| 890 | } | 890 | } |
| 891 | 891 | ||
| 892 | Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() { | 892 | Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() { |
| 893 | return impl->cores[CurrentPhysicalCoreIndex()]; | 893 | return *impl->cores[CurrentPhysicalCoreIndex()]; |
| 894 | } | 894 | } |
| 895 | 895 | ||
| 896 | const Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() const { | 896 | const Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() const { |
| 897 | return impl->cores[CurrentPhysicalCoreIndex()]; | 897 | return *impl->cores[CurrentPhysicalCoreIndex()]; |
| 898 | } | 898 | } |
| 899 | 899 | ||
| 900 | Kernel::KScheduler* KernelCore::CurrentScheduler() { | 900 | Kernel::KScheduler* KernelCore::CurrentScheduler() { |
| @@ -906,15 +906,6 @@ Kernel::KScheduler* KernelCore::CurrentScheduler() { | |||
| 906 | return impl->schedulers[core_id].get(); | 906 | return impl->schedulers[core_id].get(); |
| 907 | } | 907 | } |
| 908 | 908 | ||
| 909 | std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& KernelCore::Interrupts() { | ||
| 910 | return impl->interrupts; | ||
| 911 | } | ||
| 912 | |||
| 913 | const std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& KernelCore::Interrupts() | ||
| 914 | const { | ||
| 915 | return impl->interrupts; | ||
| 916 | } | ||
| 917 | |||
| 918 | Kernel::TimeManager& KernelCore::TimeManager() { | 909 | Kernel::TimeManager& KernelCore::TimeManager() { |
| 919 | return impl->time_manager; | 910 | return impl->time_manager; |
| 920 | } | 911 | } |
| @@ -939,24 +930,18 @@ const KAutoObjectWithListContainer& KernelCore::ObjectListContainer() const { | |||
| 939 | return *impl->global_object_list_container; | 930 | return *impl->global_object_list_container; |
| 940 | } | 931 | } |
| 941 | 932 | ||
| 942 | void KernelCore::InterruptAllPhysicalCores() { | ||
| 943 | for (auto& physical_core : impl->cores) { | ||
| 944 | physical_core.Interrupt(); | ||
| 945 | } | ||
| 946 | } | ||
| 947 | |||
| 948 | void KernelCore::InvalidateAllInstructionCaches() { | 933 | void KernelCore::InvalidateAllInstructionCaches() { |
| 949 | for (auto& physical_core : impl->cores) { | 934 | for (auto& physical_core : impl->cores) { |
| 950 | physical_core.ArmInterface().ClearInstructionCache(); | 935 | physical_core->ArmInterface().ClearInstructionCache(); |
| 951 | } | 936 | } |
| 952 | } | 937 | } |
| 953 | 938 | ||
| 954 | void KernelCore::InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size) { | 939 | void KernelCore::InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size) { |
| 955 | for (auto& physical_core : impl->cores) { | 940 | for (auto& physical_core : impl->cores) { |
| 956 | if (!physical_core.IsInitialized()) { | 941 | if (!physical_core->IsInitialized()) { |
| 957 | continue; | 942 | continue; |
| 958 | } | 943 | } |
| 959 | physical_core.ArmInterface().InvalidateCacheRange(addr, size); | 944 | physical_core->ArmInterface().InvalidateCacheRange(addr, size); |
| 960 | } | 945 | } |
| 961 | } | 946 | } |
| 962 | 947 | ||
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 6c7cf6af2..bcf016a97 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -9,14 +9,12 @@ | |||
| 9 | #include <string> | 9 | #include <string> |
| 10 | #include <unordered_map> | 10 | #include <unordered_map> |
| 11 | #include <vector> | 11 | #include <vector> |
| 12 | #include "core/arm/cpu_interrupt_handler.h" | ||
| 13 | #include "core/hardware_properties.h" | 12 | #include "core/hardware_properties.h" |
| 14 | #include "core/hle/kernel/k_auto_object.h" | 13 | #include "core/hle/kernel/k_auto_object.h" |
| 15 | #include "core/hle/kernel/k_slab_heap.h" | 14 | #include "core/hle/kernel/k_slab_heap.h" |
| 16 | #include "core/hle/kernel/svc_common.h" | 15 | #include "core/hle/kernel/svc_common.h" |
| 17 | 16 | ||
| 18 | namespace Core { | 17 | namespace Core { |
| 19 | class CPUInterruptHandler; | ||
| 20 | class ExclusiveMonitor; | 18 | class ExclusiveMonitor; |
| 21 | class System; | 19 | class System; |
| 22 | } // namespace Core | 20 | } // namespace Core |
| @@ -183,12 +181,6 @@ public: | |||
| 183 | 181 | ||
| 184 | const KAutoObjectWithListContainer& ObjectListContainer() const; | 182 | const KAutoObjectWithListContainer& ObjectListContainer() const; |
| 185 | 183 | ||
| 186 | std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& Interrupts(); | ||
| 187 | |||
| 188 | const std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& Interrupts() const; | ||
| 189 | |||
| 190 | void InterruptAllPhysicalCores(); | ||
| 191 | |||
| 192 | void InvalidateAllInstructionCaches(); | 184 | void InvalidateAllInstructionCaches(); |
| 193 | 185 | ||
| 194 | void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size); | 186 | void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size); |
diff --git a/src/core/hle/kernel/physical_core.cpp b/src/core/hle/kernel/physical_core.cpp index 6e7dacf97..d4375962f 100644 --- a/src/core/hle/kernel/physical_core.cpp +++ b/src/core/hle/kernel/physical_core.cpp | |||
| @@ -1,7 +1,6 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "core/arm/cpu_interrupt_handler.h" | ||
| 5 | #include "core/arm/dynarmic/arm_dynarmic_32.h" | 4 | #include "core/arm/dynarmic/arm_dynarmic_32.h" |
| 6 | #include "core/arm/dynarmic/arm_dynarmic_64.h" | 5 | #include "core/arm/dynarmic/arm_dynarmic_64.h" |
| 7 | #include "core/core.h" | 6 | #include "core/core.h" |
| @@ -11,16 +10,14 @@ | |||
| 11 | 10 | ||
| 12 | namespace Kernel { | 11 | namespace Kernel { |
| 13 | 12 | ||
| 14 | PhysicalCore::PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_, | 13 | PhysicalCore::PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_) |
| 15 | Core::CPUInterrupts& interrupts_) | 14 | : core_index{core_index_}, system{system_}, scheduler{scheduler_} { |
| 16 | : core_index{core_index_}, system{system_}, scheduler{scheduler_}, | ||
| 17 | interrupts{interrupts_}, guard{std::make_unique<std::mutex>()} { | ||
| 18 | #ifdef ARCHITECTURE_x86_64 | 15 | #ifdef ARCHITECTURE_x86_64 |
| 19 | // TODO(bunnei): Initialization relies on a core being available. We may later replace this with | 16 | // TODO(bunnei): Initialization relies on a core being available. We may later replace this with |
| 20 | // a 32-bit instance of Dynarmic. This should be abstracted out to a CPU manager. | 17 | // a 32-bit instance of Dynarmic. This should be abstracted out to a CPU manager. |
| 21 | auto& kernel = system.Kernel(); | 18 | auto& kernel = system.Kernel(); |
| 22 | arm_interface = std::make_unique<Core::ARM_Dynarmic_64>( | 19 | arm_interface = std::make_unique<Core::ARM_Dynarmic_64>( |
| 23 | system, interrupts, kernel.IsMulticore(), kernel.GetExclusiveMonitor(), core_index); | 20 | system, kernel.IsMulticore(), kernel.GetExclusiveMonitor(), core_index); |
| 24 | #else | 21 | #else |
| 25 | #error Platform not supported yet. | 22 | #error Platform not supported yet. |
| 26 | #endif | 23 | #endif |
| @@ -34,7 +31,7 @@ void PhysicalCore::Initialize([[maybe_unused]] bool is_64_bit) { | |||
| 34 | if (!is_64_bit) { | 31 | if (!is_64_bit) { |
| 35 | // We already initialized a 64-bit core, replace with a 32-bit one. | 32 | // We already initialized a 64-bit core, replace with a 32-bit one. |
| 36 | arm_interface = std::make_unique<Core::ARM_Dynarmic_32>( | 33 | arm_interface = std::make_unique<Core::ARM_Dynarmic_32>( |
| 37 | system, interrupts, kernel.IsMulticore(), kernel.GetExclusiveMonitor(), core_index); | 34 | system, kernel.IsMulticore(), kernel.GetExclusiveMonitor(), core_index); |
| 38 | } | 35 | } |
| 39 | #else | 36 | #else |
| 40 | #error Platform not supported yet. | 37 | #error Platform not supported yet. |
| @@ -47,24 +44,26 @@ void PhysicalCore::Run() { | |||
| 47 | } | 44 | } |
| 48 | 45 | ||
| 49 | void PhysicalCore::Idle() { | 46 | void PhysicalCore::Idle() { |
| 50 | interrupts[core_index].AwaitInterrupt(); | 47 | std::unique_lock lk{guard}; |
| 48 | on_interrupt.wait(lk, [this] { return is_interrupted; }); | ||
| 51 | } | 49 | } |
| 52 | 50 | ||
| 53 | bool PhysicalCore::IsInterrupted() const { | 51 | bool PhysicalCore::IsInterrupted() const { |
| 54 | return interrupts[core_index].IsInterrupted(); | 52 | return is_interrupted; |
| 55 | } | 53 | } |
| 56 | 54 | ||
| 57 | void PhysicalCore::Interrupt() { | 55 | void PhysicalCore::Interrupt() { |
| 58 | guard->lock(); | 56 | std::unique_lock lk{guard}; |
| 59 | interrupts[core_index].SetInterrupt(true); | 57 | is_interrupted = true; |
| 60 | arm_interface->SignalInterrupt(); | 58 | arm_interface->SignalInterrupt(); |
| 61 | guard->unlock(); | 59 | on_interrupt.notify_all(); |
| 62 | } | 60 | } |
| 63 | 61 | ||
| 64 | void PhysicalCore::ClearInterrupt() { | 62 | void PhysicalCore::ClearInterrupt() { |
| 65 | guard->lock(); | 63 | std::unique_lock lk{guard}; |
| 66 | interrupts[core_index].SetInterrupt(false); | 64 | is_interrupted = false; |
| 67 | guard->unlock(); | 65 | arm_interface->ClearInterrupt(); |
| 66 | on_interrupt.notify_all(); | ||
| 68 | } | 67 | } |
| 69 | 68 | ||
| 70 | } // namespace Kernel | 69 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/physical_core.h b/src/core/hle/kernel/physical_core.h index 898d1e5db..2fc8d4be2 100644 --- a/src/core/hle/kernel/physical_core.h +++ b/src/core/hle/kernel/physical_core.h | |||
| @@ -14,7 +14,6 @@ class KScheduler; | |||
| 14 | } // namespace Kernel | 14 | } // namespace Kernel |
| 15 | 15 | ||
| 16 | namespace Core { | 16 | namespace Core { |
| 17 | class CPUInterruptHandler; | ||
| 18 | class ExclusiveMonitor; | 17 | class ExclusiveMonitor; |
| 19 | class System; | 18 | class System; |
| 20 | } // namespace Core | 19 | } // namespace Core |
| @@ -23,15 +22,11 @@ namespace Kernel { | |||
| 23 | 22 | ||
| 24 | class PhysicalCore { | 23 | class PhysicalCore { |
| 25 | public: | 24 | public: |
| 26 | PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_, | 25 | PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_); |
| 27 | Core::CPUInterrupts& interrupts_); | ||
| 28 | ~PhysicalCore(); | 26 | ~PhysicalCore(); |
| 29 | 27 | ||
| 30 | PhysicalCore(const PhysicalCore&) = delete; | 28 | YUZU_NON_COPYABLE(PhysicalCore); |
| 31 | PhysicalCore& operator=(const PhysicalCore&) = delete; | 29 | YUZU_NON_MOVEABLE(PhysicalCore); |
| 32 | |||
| 33 | PhysicalCore(PhysicalCore&&) = default; | ||
| 34 | PhysicalCore& operator=(PhysicalCore&&) = delete; | ||
| 35 | 30 | ||
| 36 | /// Initialize the core for the specified parameters. | 31 | /// Initialize the core for the specified parameters. |
| 37 | void Initialize(bool is_64_bit); | 32 | void Initialize(bool is_64_bit); |
| @@ -86,9 +81,11 @@ private: | |||
| 86 | const std::size_t core_index; | 81 | const std::size_t core_index; |
| 87 | Core::System& system; | 82 | Core::System& system; |
| 88 | Kernel::KScheduler& scheduler; | 83 | Kernel::KScheduler& scheduler; |
| 89 | Core::CPUInterrupts& interrupts; | 84 | |
| 90 | std::unique_ptr<std::mutex> guard; | 85 | std::mutex guard; |
| 86 | std::condition_variable on_interrupt; | ||
| 91 | std::unique_ptr<Core::ARM_Interface> arm_interface; | 87 | std::unique_ptr<Core::ARM_Interface> arm_interface; |
| 88 | bool is_interrupted; | ||
| 92 | }; | 89 | }; |
| 93 | 90 | ||
| 94 | } // namespace Kernel | 91 | } // namespace Kernel |
diff --git a/src/core/hle/result.h b/src/core/hle/result.h index 4de44cd06..47a1b829b 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h | |||
| @@ -117,6 +117,7 @@ union Result { | |||
| 117 | BitField<0, 9, ErrorModule> module; | 117 | BitField<0, 9, ErrorModule> module; |
| 118 | BitField<9, 13, u32> description; | 118 | BitField<9, 13, u32> description; |
| 119 | 119 | ||
| 120 | Result() = default; | ||
| 120 | constexpr explicit Result(u32 raw_) : raw(raw_) {} | 121 | constexpr explicit Result(u32 raw_) : raw(raw_) {} |
| 121 | 122 | ||
| 122 | constexpr Result(ErrorModule module_, u32 description_) | 123 | constexpr Result(ErrorModule module_, u32 description_) |
| @@ -130,6 +131,7 @@ union Result { | |||
| 130 | return !IsSuccess(); | 131 | return !IsSuccess(); |
| 131 | } | 132 | } |
| 132 | }; | 133 | }; |
| 134 | static_assert(std::is_trivial_v<Result>); | ||
| 133 | 135 | ||
| 134 | [[nodiscard]] constexpr bool operator==(const Result& a, const Result& b) { | 136 | [[nodiscard]] constexpr bool operator==(const Result& a, const Result& b) { |
| 135 | return a.raw == b.raw; | 137 | return a.raw == b.raw; |
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index def105832..bb838e285 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp | |||
| @@ -534,7 +534,7 @@ public: | |||
| 534 | 534 | ||
| 535 | private: | 535 | private: |
| 536 | void CheckAvailability(Kernel::HLERequestContext& ctx) { | 536 | void CheckAvailability(Kernel::HLERequestContext& ctx) { |
| 537 | LOG_WARNING(Service_ACC, "(STUBBED) called"); | 537 | LOG_DEBUG(Service_ACC, "(STUBBED) called"); |
| 538 | IPC::ResponseBuilder rb{ctx, 3}; | 538 | IPC::ResponseBuilder rb{ctx, 3}; |
| 539 | rb.Push(ResultSuccess); | 539 | rb.Push(ResultSuccess); |
| 540 | rb.Push(false); // TODO: Check when this is supposed to return true and when not | 540 | rb.Push(false); // TODO: Check when this is supposed to return true and when not |
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 118f226e4..6fb7e198e 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -754,7 +754,7 @@ void ICommonStateGetter::ReceiveMessage(Kernel::HLERequestContext& ctx) { | |||
| 754 | } | 754 | } |
| 755 | 755 | ||
| 756 | void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) { | 756 | void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) { |
| 757 | LOG_WARNING(Service_AM, "(STUBBED) called"); | 757 | LOG_DEBUG(Service_AM, "(STUBBED) called"); |
| 758 | 758 | ||
| 759 | IPC::ResponseBuilder rb{ctx, 3}; | 759 | IPC::ResponseBuilder rb{ctx, 3}; |
| 760 | rb.Push(ResultSuccess); | 760 | rb.Push(ResultSuccess); |
diff --git a/src/core/hle/service/am/applets/applet_web_browser.cpp b/src/core/hle/service/am/applets/applet_web_browser.cpp index 4b804b78c..14aa6f69e 100644 --- a/src/core/hle/service/am/applets/applet_web_browser.cpp +++ b/src/core/hle/service/am/applets/applet_web_browser.cpp | |||
| @@ -21,7 +21,7 @@ | |||
| 21 | #include "core/hle/service/am/am.h" | 21 | #include "core/hle/service/am/am.h" |
| 22 | #include "core/hle/service/am/applets/applet_web_browser.h" | 22 | #include "core/hle/service/am/applets/applet_web_browser.h" |
| 23 | #include "core/hle/service/filesystem/filesystem.h" | 23 | #include "core/hle/service/filesystem/filesystem.h" |
| 24 | #include "core/hle/service/ns/pl_u.h" | 24 | #include "core/hle/service/ns/iplatform_service_manager.h" |
| 25 | #include "core/loader/loader.h" | 25 | #include "core/loader/loader.h" |
| 26 | 26 | ||
| 27 | namespace Service::AM::Applets { | 27 | namespace Service::AM::Applets { |
diff --git a/src/core/hle/service/apm/apm_controller.cpp b/src/core/hle/service/apm/apm_controller.cpp index 4e710491b..d6de84066 100644 --- a/src/core/hle/service/apm/apm_controller.cpp +++ b/src/core/hle/service/apm/apm_controller.cpp | |||
| @@ -80,7 +80,7 @@ PerformanceConfiguration Controller::GetCurrentPerformanceConfiguration(Performa | |||
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | void Controller::SetClockSpeed(u32 mhz) { | 82 | void Controller::SetClockSpeed(u32 mhz) { |
| 83 | LOG_INFO(Service_APM, "called, mhz={:08X}", mhz); | 83 | LOG_DEBUG(Service_APM, "called, mhz={:08X}", mhz); |
| 84 | // TODO(DarkLordZach): Actually signal core_timing to change clock speed. | 84 | // TODO(DarkLordZach): Actually signal core_timing to change clock speed. |
| 85 | // TODO(Rodrigo): Remove [[maybe_unused]] when core_timing is used. | 85 | // TODO(Rodrigo): Remove [[maybe_unused]] when core_timing is used. |
| 86 | } | 86 | } |
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index a44dd842a..49c092301 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp | |||
| @@ -246,9 +246,8 @@ void AudOutU::ListAudioOuts(Kernel::HLERequestContext& ctx) { | |||
| 246 | const auto write_count = | 246 | const auto write_count = |
| 247 | static_cast<u32>(ctx.GetWriteBufferSize() / sizeof(AudioDevice::AudioDeviceName)); | 247 | static_cast<u32>(ctx.GetWriteBufferSize() / sizeof(AudioDevice::AudioDeviceName)); |
| 248 | std::vector<AudioDevice::AudioDeviceName> device_names{}; | 248 | std::vector<AudioDevice::AudioDeviceName> device_names{}; |
| 249 | std::string print_names{}; | ||
| 250 | if (write_count > 0) { | 249 | if (write_count > 0) { |
| 251 | device_names.push_back(AudioDevice::AudioDeviceName("DeviceOut")); | 250 | device_names.emplace_back("DeviceOut"); |
| 252 | LOG_DEBUG(Service_Audio, "called. \nName=DeviceOut"); | 251 | LOG_DEBUG(Service_Audio, "called. \nName=DeviceOut"); |
| 253 | } else { | 252 | } else { |
| 254 | LOG_DEBUG(Service_Audio, "called. Empty buffer passed in."); | 253 | LOG_DEBUG(Service_Audio, "called. Empty buffer passed in."); |
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index 381a66ba5..6fb07c37d 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp | |||
| @@ -50,7 +50,7 @@ public: | |||
| 50 | {7, &IAudioRenderer::QuerySystemEvent, "QuerySystemEvent"}, | 50 | {7, &IAudioRenderer::QuerySystemEvent, "QuerySystemEvent"}, |
| 51 | {8, &IAudioRenderer::SetRenderingTimeLimit, "SetRenderingTimeLimit"}, | 51 | {8, &IAudioRenderer::SetRenderingTimeLimit, "SetRenderingTimeLimit"}, |
| 52 | {9, &IAudioRenderer::GetRenderingTimeLimit, "GetRenderingTimeLimit"}, | 52 | {9, &IAudioRenderer::GetRenderingTimeLimit, "GetRenderingTimeLimit"}, |
| 53 | {10, nullptr, "RequestUpdateAuto"}, | 53 | {10, &IAudioRenderer::RequestUpdate, "RequestUpdateAuto"}, |
| 54 | {11, nullptr, "ExecuteAudioRendererRendering"}, | 54 | {11, nullptr, "ExecuteAudioRendererRendering"}, |
| 55 | }; | 55 | }; |
| 56 | // clang-format on | 56 | // clang-format on |
| @@ -113,15 +113,30 @@ private: | |||
| 113 | 113 | ||
| 114 | // These buffers are written manually to avoid an issue with WriteBuffer throwing errors for | 114 | // These buffers are written manually to avoid an issue with WriteBuffer throwing errors for |
| 115 | // checking size 0. Performance size is 0 for most games. | 115 | // checking size 0. Performance size is 0 for most games. |
| 116 | const auto buffers{ctx.BufferDescriptorB()}; | 116 | |
| 117 | std::vector<u8> output(buffers[0].Size(), 0); | 117 | std::vector<u8> output{}; |
| 118 | std::vector<u8> performance(buffers[1].Size(), 0); | 118 | std::vector<u8> performance{}; |
| 119 | auto is_buffer_b{ctx.BufferDescriptorB()[0].Size() != 0}; | ||
| 120 | if (is_buffer_b) { | ||
| 121 | const auto buffersB{ctx.BufferDescriptorB()}; | ||
| 122 | output.resize(buffersB[0].Size(), 0); | ||
| 123 | performance.resize(buffersB[1].Size(), 0); | ||
| 124 | } else { | ||
| 125 | const auto buffersC{ctx.BufferDescriptorC()}; | ||
| 126 | output.resize(buffersC[0].Size(), 0); | ||
| 127 | performance.resize(buffersC[1].Size(), 0); | ||
| 128 | } | ||
| 119 | 129 | ||
| 120 | auto result = impl->RequestUpdate(input, performance, output); | 130 | auto result = impl->RequestUpdate(input, performance, output); |
| 121 | 131 | ||
| 122 | if (result.IsSuccess()) { | 132 | if (result.IsSuccess()) { |
| 123 | ctx.WriteBufferB(output.data(), output.size(), 0); | 133 | if (is_buffer_b) { |
| 124 | ctx.WriteBufferB(performance.data(), performance.size(), 1); | 134 | ctx.WriteBufferB(output.data(), output.size(), 0); |
| 135 | ctx.WriteBufferB(performance.data(), performance.size(), 1); | ||
| 136 | } else { | ||
| 137 | ctx.WriteBufferC(output.data(), output.size(), 0); | ||
| 138 | ctx.WriteBufferC(performance.data(), performance.size(), 1); | ||
| 139 | } | ||
| 125 | } else { | 140 | } else { |
| 126 | LOG_ERROR(Service_Audio, "RequestUpdate failed error 0x{:02X}!", result.description); | 141 | LOG_ERROR(Service_Audio, "RequestUpdate failed error 0x{:02X}!", result.description); |
| 127 | } | 142 | } |
| @@ -237,7 +252,7 @@ private: | |||
| 237 | 252 | ||
| 238 | std::vector<AudioDevice::AudioDeviceName> out_names{}; | 253 | std::vector<AudioDevice::AudioDeviceName> out_names{}; |
| 239 | 254 | ||
| 240 | u32 out_count = impl->ListAudioDeviceName(out_names, in_count); | 255 | const u32 out_count = impl->ListAudioDeviceName(out_names, in_count); |
| 241 | 256 | ||
| 242 | std::string out{}; | 257 | std::string out{}; |
| 243 | for (u32 i = 0; i < out_count; i++) { | 258 | for (u32 i = 0; i < out_count; i++) { |
| @@ -350,7 +365,7 @@ private: | |||
| 350 | 365 | ||
| 351 | std::vector<AudioDevice::AudioDeviceName> out_names{}; | 366 | std::vector<AudioDevice::AudioDeviceName> out_names{}; |
| 352 | 367 | ||
| 353 | u32 out_count = impl->ListAudioOutputDeviceName(out_names, in_count); | 368 | const u32 out_count = impl->ListAudioOutputDeviceName(out_names, in_count); |
| 354 | 369 | ||
| 355 | std::string out{}; | 370 | std::string out{}; |
| 356 | for (u32 i = 0; i < out_count; i++) { | 371 | for (u32 i = 0; i < out_count; i++) { |
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index fae6e5aff..e23eae36a 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp | |||
| @@ -246,7 +246,8 @@ static void BuildEntryIndex(std::vector<FileSys::Entry>& entries, const std::vec | |||
| 246 | entries.reserve(entries.size() + new_data.size()); | 246 | entries.reserve(entries.size() + new_data.size()); |
| 247 | 247 | ||
| 248 | for (const auto& new_entry : new_data) { | 248 | for (const auto& new_entry : new_data) { |
| 249 | entries.emplace_back(new_entry->GetName(), type, new_entry->GetSize()); | 249 | entries.emplace_back(new_entry->GetName(), type, |
| 250 | type == FileSys::EntryType::Directory ? 0 : new_entry->GetSize()); | ||
| 250 | } | 251 | } |
| 251 | } | 252 | } |
| 252 | 253 | ||
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 3c28dee76..cb29004e8 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp | |||
| @@ -163,28 +163,51 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { | |||
| 163 | } | 163 | } |
| 164 | LOG_DEBUG(Service_HID, "Npad connected {}", npad_id); | 164 | LOG_DEBUG(Service_HID, "Npad connected {}", npad_id); |
| 165 | const auto controller_type = controller.device->GetNpadStyleIndex(); | 165 | const auto controller_type = controller.device->GetNpadStyleIndex(); |
| 166 | const auto& body_colors = controller.device->GetColors(); | ||
| 167 | const auto& battery_level = controller.device->GetBattery(); | ||
| 166 | auto* shared_memory = controller.shared_memory; | 168 | auto* shared_memory = controller.shared_memory; |
| 167 | if (controller_type == Core::HID::NpadStyleIndex::None) { | 169 | if (controller_type == Core::HID::NpadStyleIndex::None) { |
| 168 | controller.styleset_changed_event->GetWritableEvent().Signal(); | 170 | controller.styleset_changed_event->GetWritableEvent().Signal(); |
| 169 | return; | 171 | return; |
| 170 | } | 172 | } |
| 173 | |||
| 174 | // Reset memory values | ||
| 171 | shared_memory->style_tag.raw = Core::HID::NpadStyleSet::None; | 175 | shared_memory->style_tag.raw = Core::HID::NpadStyleSet::None; |
| 172 | shared_memory->device_type.raw = 0; | 176 | shared_memory->device_type.raw = 0; |
| 173 | shared_memory->system_properties.raw = 0; | 177 | shared_memory->system_properties.raw = 0; |
| 178 | shared_memory->joycon_color.attribute = ColorAttribute::NoController; | ||
| 179 | shared_memory->joycon_color.attribute = ColorAttribute::NoController; | ||
| 180 | shared_memory->fullkey_color = {}; | ||
| 181 | shared_memory->joycon_color.left = {}; | ||
| 182 | shared_memory->joycon_color.right = {}; | ||
| 183 | shared_memory->battery_level_dual = {}; | ||
| 184 | shared_memory->battery_level_left = {}; | ||
| 185 | shared_memory->battery_level_right = {}; | ||
| 186 | |||
| 174 | switch (controller_type) { | 187 | switch (controller_type) { |
| 175 | case Core::HID::NpadStyleIndex::None: | 188 | case Core::HID::NpadStyleIndex::None: |
| 176 | ASSERT(false); | 189 | ASSERT(false); |
| 177 | break; | 190 | break; |
| 178 | case Core::HID::NpadStyleIndex::ProController: | 191 | case Core::HID::NpadStyleIndex::ProController: |
| 192 | shared_memory->fullkey_color.attribute = ColorAttribute::Ok; | ||
| 193 | shared_memory->fullkey_color.fullkey = body_colors.fullkey; | ||
| 194 | shared_memory->battery_level_dual = battery_level.dual.battery_level; | ||
| 179 | shared_memory->style_tag.fullkey.Assign(1); | 195 | shared_memory->style_tag.fullkey.Assign(1); |
| 180 | shared_memory->device_type.fullkey.Assign(1); | 196 | shared_memory->device_type.fullkey.Assign(1); |
| 181 | shared_memory->system_properties.is_vertical.Assign(1); | 197 | shared_memory->system_properties.is_vertical.Assign(1); |
| 182 | shared_memory->system_properties.use_plus.Assign(1); | 198 | shared_memory->system_properties.use_plus.Assign(1); |
| 183 | shared_memory->system_properties.use_minus.Assign(1); | 199 | shared_memory->system_properties.use_minus.Assign(1); |
| 200 | shared_memory->system_properties.is_charging_joy_dual.Assign( | ||
| 201 | battery_level.dual.is_charging); | ||
| 184 | shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::SwitchProController; | 202 | shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::SwitchProController; |
| 185 | shared_memory->sixaxis_fullkey_properties.is_newly_assigned.Assign(1); | 203 | shared_memory->sixaxis_fullkey_properties.is_newly_assigned.Assign(1); |
| 186 | break; | 204 | break; |
| 187 | case Core::HID::NpadStyleIndex::Handheld: | 205 | case Core::HID::NpadStyleIndex::Handheld: |
| 206 | shared_memory->fullkey_color.attribute = ColorAttribute::Ok; | ||
| 207 | shared_memory->joycon_color.attribute = ColorAttribute::Ok; | ||
| 208 | shared_memory->fullkey_color.fullkey = body_colors.fullkey; | ||
| 209 | shared_memory->joycon_color.left = body_colors.left; | ||
| 210 | shared_memory->joycon_color.right = body_colors.right; | ||
| 188 | shared_memory->style_tag.handheld.Assign(1); | 211 | shared_memory->style_tag.handheld.Assign(1); |
| 189 | shared_memory->device_type.handheld_left.Assign(1); | 212 | shared_memory->device_type.handheld_left.Assign(1); |
| 190 | shared_memory->device_type.handheld_right.Assign(1); | 213 | shared_memory->device_type.handheld_right.Assign(1); |
| @@ -192,47 +215,86 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { | |||
| 192 | shared_memory->system_properties.use_plus.Assign(1); | 215 | shared_memory->system_properties.use_plus.Assign(1); |
| 193 | shared_memory->system_properties.use_minus.Assign(1); | 216 | shared_memory->system_properties.use_minus.Assign(1); |
| 194 | shared_memory->system_properties.use_directional_buttons.Assign(1); | 217 | shared_memory->system_properties.use_directional_buttons.Assign(1); |
| 218 | shared_memory->system_properties.is_charging_joy_dual.Assign( | ||
| 219 | battery_level.left.is_charging); | ||
| 220 | shared_memory->system_properties.is_charging_joy_left.Assign( | ||
| 221 | battery_level.left.is_charging); | ||
| 222 | shared_memory->system_properties.is_charging_joy_right.Assign( | ||
| 223 | battery_level.right.is_charging); | ||
| 195 | shared_memory->assignment_mode = NpadJoyAssignmentMode::Dual; | 224 | shared_memory->assignment_mode = NpadJoyAssignmentMode::Dual; |
| 196 | shared_memory->applet_nfc_xcd.applet_footer.type = | 225 | shared_memory->applet_nfc_xcd.applet_footer.type = |
| 197 | AppletFooterUiType::HandheldJoyConLeftJoyConRight; | 226 | AppletFooterUiType::HandheldJoyConLeftJoyConRight; |
| 198 | shared_memory->sixaxis_handheld_properties.is_newly_assigned.Assign(1); | 227 | shared_memory->sixaxis_handheld_properties.is_newly_assigned.Assign(1); |
| 199 | break; | 228 | break; |
| 200 | case Core::HID::NpadStyleIndex::JoyconDual: | 229 | case Core::HID::NpadStyleIndex::JoyconDual: |
| 230 | shared_memory->fullkey_color.attribute = ColorAttribute::Ok; | ||
| 231 | shared_memory->joycon_color.attribute = ColorAttribute::Ok; | ||
| 201 | shared_memory->style_tag.joycon_dual.Assign(1); | 232 | shared_memory->style_tag.joycon_dual.Assign(1); |
| 202 | if (controller.is_dual_left_connected) { | 233 | if (controller.is_dual_left_connected) { |
| 234 | shared_memory->joycon_color.left = body_colors.left; | ||
| 235 | shared_memory->battery_level_left = battery_level.left.battery_level; | ||
| 203 | shared_memory->device_type.joycon_left.Assign(1); | 236 | shared_memory->device_type.joycon_left.Assign(1); |
| 204 | shared_memory->system_properties.use_minus.Assign(1); | 237 | shared_memory->system_properties.use_minus.Assign(1); |
| 238 | shared_memory->system_properties.is_charging_joy_left.Assign( | ||
| 239 | battery_level.left.is_charging); | ||
| 205 | shared_memory->sixaxis_dual_left_properties.is_newly_assigned.Assign(1); | 240 | shared_memory->sixaxis_dual_left_properties.is_newly_assigned.Assign(1); |
| 206 | } | 241 | } |
| 207 | if (controller.is_dual_right_connected) { | 242 | if (controller.is_dual_right_connected) { |
| 243 | shared_memory->joycon_color.right = body_colors.right; | ||
| 244 | shared_memory->battery_level_right = battery_level.right.battery_level; | ||
| 208 | shared_memory->device_type.joycon_right.Assign(1); | 245 | shared_memory->device_type.joycon_right.Assign(1); |
| 209 | shared_memory->system_properties.use_plus.Assign(1); | 246 | shared_memory->system_properties.use_plus.Assign(1); |
| 247 | shared_memory->system_properties.is_charging_joy_right.Assign( | ||
| 248 | battery_level.right.is_charging); | ||
| 210 | shared_memory->sixaxis_dual_right_properties.is_newly_assigned.Assign(1); | 249 | shared_memory->sixaxis_dual_right_properties.is_newly_assigned.Assign(1); |
| 211 | } | 250 | } |
| 212 | shared_memory->system_properties.use_directional_buttons.Assign(1); | 251 | shared_memory->system_properties.use_directional_buttons.Assign(1); |
| 213 | shared_memory->system_properties.is_vertical.Assign(1); | 252 | shared_memory->system_properties.is_vertical.Assign(1); |
| 214 | shared_memory->assignment_mode = NpadJoyAssignmentMode::Dual; | 253 | shared_memory->assignment_mode = NpadJoyAssignmentMode::Dual; |
| 254 | |||
| 215 | if (controller.is_dual_left_connected && controller.is_dual_right_connected) { | 255 | if (controller.is_dual_left_connected && controller.is_dual_right_connected) { |
| 216 | shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyDual; | 256 | shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyDual; |
| 257 | shared_memory->fullkey_color.fullkey = body_colors.left; | ||
| 258 | shared_memory->battery_level_dual = battery_level.left.battery_level; | ||
| 259 | shared_memory->system_properties.is_charging_joy_dual.Assign( | ||
| 260 | battery_level.left.is_charging); | ||
| 217 | } else if (controller.is_dual_left_connected) { | 261 | } else if (controller.is_dual_left_connected) { |
| 218 | shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyDualLeftOnly; | 262 | shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyDualLeftOnly; |
| 263 | shared_memory->fullkey_color.fullkey = body_colors.left; | ||
| 264 | shared_memory->battery_level_dual = battery_level.left.battery_level; | ||
| 265 | shared_memory->system_properties.is_charging_joy_dual.Assign( | ||
| 266 | battery_level.left.is_charging); | ||
| 219 | } else { | 267 | } else { |
| 220 | shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyDualRightOnly; | 268 | shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyDualRightOnly; |
| 269 | shared_memory->fullkey_color.fullkey = body_colors.right; | ||
| 270 | shared_memory->battery_level_dual = battery_level.right.battery_level; | ||
| 271 | shared_memory->system_properties.is_charging_joy_dual.Assign( | ||
| 272 | battery_level.right.is_charging); | ||
| 221 | } | 273 | } |
| 222 | break; | 274 | break; |
| 223 | case Core::HID::NpadStyleIndex::JoyconLeft: | 275 | case Core::HID::NpadStyleIndex::JoyconLeft: |
| 276 | shared_memory->joycon_color.attribute = ColorAttribute::Ok; | ||
| 277 | shared_memory->joycon_color.left = body_colors.left; | ||
| 278 | shared_memory->battery_level_dual = battery_level.left.battery_level; | ||
| 224 | shared_memory->style_tag.joycon_left.Assign(1); | 279 | shared_memory->style_tag.joycon_left.Assign(1); |
| 225 | shared_memory->device_type.joycon_left.Assign(1); | 280 | shared_memory->device_type.joycon_left.Assign(1); |
| 226 | shared_memory->system_properties.is_horizontal.Assign(1); | 281 | shared_memory->system_properties.is_horizontal.Assign(1); |
| 227 | shared_memory->system_properties.use_minus.Assign(1); | 282 | shared_memory->system_properties.use_minus.Assign(1); |
| 283 | shared_memory->system_properties.is_charging_joy_left.Assign( | ||
| 284 | battery_level.left.is_charging); | ||
| 228 | shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyLeftHorizontal; | 285 | shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyLeftHorizontal; |
| 229 | shared_memory->sixaxis_left_properties.is_newly_assigned.Assign(1); | 286 | shared_memory->sixaxis_left_properties.is_newly_assigned.Assign(1); |
| 230 | break; | 287 | break; |
| 231 | case Core::HID::NpadStyleIndex::JoyconRight: | 288 | case Core::HID::NpadStyleIndex::JoyconRight: |
| 289 | shared_memory->joycon_color.attribute = ColorAttribute::Ok; | ||
| 290 | shared_memory->joycon_color.right = body_colors.right; | ||
| 291 | shared_memory->battery_level_right = battery_level.right.battery_level; | ||
| 232 | shared_memory->style_tag.joycon_right.Assign(1); | 292 | shared_memory->style_tag.joycon_right.Assign(1); |
| 233 | shared_memory->device_type.joycon_right.Assign(1); | 293 | shared_memory->device_type.joycon_right.Assign(1); |
| 234 | shared_memory->system_properties.is_horizontal.Assign(1); | 294 | shared_memory->system_properties.is_horizontal.Assign(1); |
| 235 | shared_memory->system_properties.use_plus.Assign(1); | 295 | shared_memory->system_properties.use_plus.Assign(1); |
| 296 | shared_memory->system_properties.is_charging_joy_right.Assign( | ||
| 297 | battery_level.right.is_charging); | ||
| 236 | shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyRightHorizontal; | 298 | shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyRightHorizontal; |
| 237 | shared_memory->sixaxis_right_properties.is_newly_assigned.Assign(1); | 299 | shared_memory->sixaxis_right_properties.is_newly_assigned.Assign(1); |
| 238 | break; | 300 | break; |
| @@ -269,21 +331,6 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { | |||
| 269 | break; | 331 | break; |
| 270 | } | 332 | } |
| 271 | 333 | ||
| 272 | const auto& body_colors = controller.device->GetColors(); | ||
| 273 | |||
| 274 | shared_memory->fullkey_color.attribute = ColorAttribute::Ok; | ||
| 275 | shared_memory->fullkey_color.fullkey = body_colors.fullkey; | ||
| 276 | |||
| 277 | shared_memory->joycon_color.attribute = ColorAttribute::Ok; | ||
| 278 | shared_memory->joycon_color.left = body_colors.left; | ||
| 279 | shared_memory->joycon_color.right = body_colors.right; | ||
| 280 | |||
| 281 | // TODO: Investigate when we should report all batery types | ||
| 282 | const auto& battery_level = controller.device->GetBattery(); | ||
| 283 | shared_memory->battery_level_dual = battery_level.dual.battery_level; | ||
| 284 | shared_memory->battery_level_left = battery_level.left.battery_level; | ||
| 285 | shared_memory->battery_level_right = battery_level.right.battery_level; | ||
| 286 | |||
| 287 | controller.is_connected = true; | 334 | controller.is_connected = true; |
| 288 | controller.device->Connect(); | 335 | controller.device->Connect(); |
| 289 | SignalStyleSetChangedEvent(npad_id); | 336 | SignalStyleSetChangedEvent(npad_id); |
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 5ecbddf94..3d3457160 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -819,12 +819,12 @@ void Hid::EnableSixAxisSensorUnalteredPassthrough(Kernel::HLERequestContext& ctx | |||
| 819 | const auto result = controller.EnableSixAxisSensorUnalteredPassthrough( | 819 | const auto result = controller.EnableSixAxisSensorUnalteredPassthrough( |
| 820 | parameters.sixaxis_handle, parameters.enabled); | 820 | parameters.sixaxis_handle, parameters.enabled); |
| 821 | 821 | ||
| 822 | LOG_WARNING(Service_HID, | 822 | LOG_DEBUG(Service_HID, |
| 823 | "(STUBBED) called, enabled={}, npad_type={}, npad_id={}, device_index={}, " | 823 | "(STUBBED) called, enabled={}, npad_type={}, npad_id={}, device_index={}, " |
| 824 | "applet_resource_user_id={}", | 824 | "applet_resource_user_id={}", |
| 825 | parameters.enabled, parameters.sixaxis_handle.npad_type, | 825 | parameters.enabled, parameters.sixaxis_handle.npad_type, |
| 826 | parameters.sixaxis_handle.npad_id, parameters.sixaxis_handle.device_index, | 826 | parameters.sixaxis_handle.npad_id, parameters.sixaxis_handle.device_index, |
| 827 | parameters.applet_resource_user_id); | 827 | parameters.applet_resource_user_id); |
| 828 | 828 | ||
| 829 | IPC::ResponseBuilder rb{ctx, 2}; | 829 | IPC::ResponseBuilder rb{ctx, 2}; |
| 830 | rb.Push(result); | 830 | rb.Push(result); |
| @@ -846,7 +846,7 @@ void Hid::IsSixAxisSensorUnalteredPassthroughEnabled(Kernel::HLERequestContext& | |||
| 846 | const auto result = controller.IsSixAxisSensorUnalteredPassthroughEnabled( | 846 | const auto result = controller.IsSixAxisSensorUnalteredPassthroughEnabled( |
| 847 | parameters.sixaxis_handle, is_unaltered_sisxaxis_enabled); | 847 | parameters.sixaxis_handle, is_unaltered_sisxaxis_enabled); |
| 848 | 848 | ||
| 849 | LOG_WARNING( | 849 | LOG_DEBUG( |
| 850 | Service_HID, | 850 | Service_HID, |
| 851 | "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", | 851 | "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", |
| 852 | parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, | 852 | parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, |
| @@ -2146,12 +2146,18 @@ public: | |||
| 2146 | {324, nullptr, "GetUniquePadButtonSet"}, | 2146 | {324, nullptr, "GetUniquePadButtonSet"}, |
| 2147 | {325, nullptr, "GetUniquePadColor"}, | 2147 | {325, nullptr, "GetUniquePadColor"}, |
| 2148 | {326, nullptr, "GetUniquePadAppletDetailedUiType"}, | 2148 | {326, nullptr, "GetUniquePadAppletDetailedUiType"}, |
| 2149 | {327, nullptr, "GetAbstractedPadIdDataFromNpad"}, | ||
| 2150 | {328, nullptr, "AttachAbstractedPadToNpad"}, | ||
| 2151 | {329, nullptr, "DetachAbstractedPadAll"}, | ||
| 2152 | {330, nullptr, "CheckAbstractedPadConnection"}, | ||
| 2149 | {500, nullptr, "SetAppletResourceUserId"}, | 2153 | {500, nullptr, "SetAppletResourceUserId"}, |
| 2150 | {501, nullptr, "RegisterAppletResourceUserId"}, | 2154 | {501, nullptr, "RegisterAppletResourceUserId"}, |
| 2151 | {502, nullptr, "UnregisterAppletResourceUserId"}, | 2155 | {502, nullptr, "UnregisterAppletResourceUserId"}, |
| 2152 | {503, nullptr, "EnableAppletToGetInput"}, | 2156 | {503, nullptr, "EnableAppletToGetInput"}, |
| 2153 | {504, nullptr, "SetAruidValidForVibration"}, | 2157 | {504, nullptr, "SetAruidValidForVibration"}, |
| 2154 | {505, nullptr, "EnableAppletToGetSixAxisSensor"}, | 2158 | {505, nullptr, "EnableAppletToGetSixAxisSensor"}, |
| 2159 | {506, nullptr, "EnableAppletToGetPadInput"}, | ||
| 2160 | {507, nullptr, "EnableAppletToGetTouchScreen"}, | ||
| 2155 | {510, nullptr, "SetVibrationMasterVolume"}, | 2161 | {510, nullptr, "SetVibrationMasterVolume"}, |
| 2156 | {511, nullptr, "GetVibrationMasterVolume"}, | 2162 | {511, nullptr, "GetVibrationMasterVolume"}, |
| 2157 | {512, nullptr, "BeginPermitVibrationSession"}, | 2163 | {512, nullptr, "BeginPermitVibrationSession"}, |
diff --git a/src/core/hle/service/ldn/errors.h b/src/core/hle/service/ldn/errors.h deleted file mode 100644 index 972a74806..000000000 --- a/src/core/hle/service/ldn/errors.h +++ /dev/null | |||
| @@ -1,12 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/result.h" | ||
| 7 | |||
| 8 | namespace Service::LDN { | ||
| 9 | |||
| 10 | constexpr Result ERROR_DISABLED{ErrorModule::LDN, 22}; | ||
| 11 | |||
| 12 | } // namespace Service::LDN | ||
diff --git a/src/core/hle/service/ldn/ldn.cpp b/src/core/hle/service/ldn/ldn.cpp index 125d4dc4c..c11daff54 100644 --- a/src/core/hle/service/ldn/ldn.cpp +++ b/src/core/hle/service/ldn/ldn.cpp | |||
| @@ -3,11 +3,15 @@ | |||
| 3 | 3 | ||
| 4 | #include <memory> | 4 | #include <memory> |
| 5 | 5 | ||
| 6 | #include "core/hle/ipc_helpers.h" | 6 | #include "core/core.h" |
| 7 | #include "core/hle/result.h" | ||
| 8 | #include "core/hle/service/ldn/errors.h" | ||
| 9 | #include "core/hle/service/ldn/ldn.h" | 7 | #include "core/hle/service/ldn/ldn.h" |
| 10 | #include "core/hle/service/sm/sm.h" | 8 | #include "core/hle/service/ldn/ldn_results.h" |
| 9 | #include "core/hle/service/ldn/ldn_types.h" | ||
| 10 | #include "core/internal_network/network.h" | ||
| 11 | #include "core/internal_network/network_interface.h" | ||
| 12 | |||
| 13 | // This is defined by synchapi.h and conflicts with ServiceContext::CreateEvent | ||
| 14 | #undef CreateEvent | ||
| 11 | 15 | ||
| 12 | namespace Service::LDN { | 16 | namespace Service::LDN { |
| 13 | 17 | ||
| @@ -100,74 +104,418 @@ class IUserLocalCommunicationService final | |||
| 100 | : public ServiceFramework<IUserLocalCommunicationService> { | 104 | : public ServiceFramework<IUserLocalCommunicationService> { |
| 101 | public: | 105 | public: |
| 102 | explicit IUserLocalCommunicationService(Core::System& system_) | 106 | explicit IUserLocalCommunicationService(Core::System& system_) |
| 103 | : ServiceFramework{system_, "IUserLocalCommunicationService"} { | 107 | : ServiceFramework{system_, "IUserLocalCommunicationService", ServiceThreadType::CreateNew}, |
| 108 | service_context{system, "IUserLocalCommunicationService"}, room_network{ | ||
| 109 | system_.GetRoomNetwork()} { | ||
| 104 | // clang-format off | 110 | // clang-format off |
| 105 | static const FunctionInfo functions[] = { | 111 | static const FunctionInfo functions[] = { |
| 106 | {0, &IUserLocalCommunicationService::GetState, "GetState"}, | 112 | {0, &IUserLocalCommunicationService::GetState, "GetState"}, |
| 107 | {1, nullptr, "GetNetworkInfo"}, | 113 | {1, &IUserLocalCommunicationService::GetNetworkInfo, "GetNetworkInfo"}, |
| 108 | {2, nullptr, "GetIpv4Address"}, | 114 | {2, nullptr, "GetIpv4Address"}, |
| 109 | {3, nullptr, "GetDisconnectReason"}, | 115 | {3, &IUserLocalCommunicationService::GetDisconnectReason, "GetDisconnectReason"}, |
| 110 | {4, nullptr, "GetSecurityParameter"}, | 116 | {4, &IUserLocalCommunicationService::GetSecurityParameter, "GetSecurityParameter"}, |
| 111 | {5, nullptr, "GetNetworkConfig"}, | 117 | {5, &IUserLocalCommunicationService::GetNetworkConfig, "GetNetworkConfig"}, |
| 112 | {100, nullptr, "AttachStateChangeEvent"}, | 118 | {100, &IUserLocalCommunicationService::AttachStateChangeEvent, "AttachStateChangeEvent"}, |
| 113 | {101, nullptr, "GetNetworkInfoLatestUpdate"}, | 119 | {101, &IUserLocalCommunicationService::GetNetworkInfoLatestUpdate, "GetNetworkInfoLatestUpdate"}, |
| 114 | {102, nullptr, "Scan"}, | 120 | {102, &IUserLocalCommunicationService::Scan, "Scan"}, |
| 115 | {103, nullptr, "ScanPrivate"}, | 121 | {103, &IUserLocalCommunicationService::ScanPrivate, "ScanPrivate"}, |
| 116 | {104, nullptr, "SetWirelessControllerRestriction"}, | 122 | {104, nullptr, "SetWirelessControllerRestriction"}, |
| 117 | {200, nullptr, "OpenAccessPoint"}, | 123 | {200, &IUserLocalCommunicationService::OpenAccessPoint, "OpenAccessPoint"}, |
| 118 | {201, nullptr, "CloseAccessPoint"}, | 124 | {201, &IUserLocalCommunicationService::CloseAccessPoint, "CloseAccessPoint"}, |
| 119 | {202, nullptr, "CreateNetwork"}, | 125 | {202, &IUserLocalCommunicationService::CreateNetwork, "CreateNetwork"}, |
| 120 | {203, nullptr, "CreateNetworkPrivate"}, | 126 | {203, &IUserLocalCommunicationService::CreateNetworkPrivate, "CreateNetworkPrivate"}, |
| 121 | {204, nullptr, "DestroyNetwork"}, | 127 | {204, &IUserLocalCommunicationService::DestroyNetwork, "DestroyNetwork"}, |
| 122 | {205, nullptr, "Reject"}, | 128 | {205, nullptr, "Reject"}, |
| 123 | {206, nullptr, "SetAdvertiseData"}, | 129 | {206, &IUserLocalCommunicationService::SetAdvertiseData, "SetAdvertiseData"}, |
| 124 | {207, nullptr, "SetStationAcceptPolicy"}, | 130 | {207, &IUserLocalCommunicationService::SetStationAcceptPolicy, "SetStationAcceptPolicy"}, |
| 125 | {208, nullptr, "AddAcceptFilterEntry"}, | 131 | {208, &IUserLocalCommunicationService::AddAcceptFilterEntry, "AddAcceptFilterEntry"}, |
| 126 | {209, nullptr, "ClearAcceptFilter"}, | 132 | {209, nullptr, "ClearAcceptFilter"}, |
| 127 | {300, nullptr, "OpenStation"}, | 133 | {300, &IUserLocalCommunicationService::OpenStation, "OpenStation"}, |
| 128 | {301, nullptr, "CloseStation"}, | 134 | {301, &IUserLocalCommunicationService::CloseStation, "CloseStation"}, |
| 129 | {302, nullptr, "Connect"}, | 135 | {302, &IUserLocalCommunicationService::Connect, "Connect"}, |
| 130 | {303, nullptr, "ConnectPrivate"}, | 136 | {303, nullptr, "ConnectPrivate"}, |
| 131 | {304, nullptr, "Disconnect"}, | 137 | {304, &IUserLocalCommunicationService::Disconnect, "Disconnect"}, |
| 132 | {400, nullptr, "Initialize"}, | 138 | {400, &IUserLocalCommunicationService::Initialize, "Initialize"}, |
| 133 | {401, nullptr, "Finalize"}, | 139 | {401, &IUserLocalCommunicationService::Finalize, "Finalize"}, |
| 134 | {402, &IUserLocalCommunicationService::Initialize2, "Initialize2"}, // 7.0.0+ | 140 | {402, &IUserLocalCommunicationService::Initialize2, "Initialize2"}, |
| 135 | }; | 141 | }; |
| 136 | // clang-format on | 142 | // clang-format on |
| 137 | 143 | ||
| 138 | RegisterHandlers(functions); | 144 | RegisterHandlers(functions); |
| 145 | |||
| 146 | state_change_event = | ||
| 147 | service_context.CreateEvent("IUserLocalCommunicationService:StateChangeEvent"); | ||
| 148 | } | ||
| 149 | |||
| 150 | ~IUserLocalCommunicationService() { | ||
| 151 | service_context.CloseEvent(state_change_event); | ||
| 152 | } | ||
| 153 | |||
| 154 | void OnEventFired() { | ||
| 155 | state_change_event->GetWritableEvent().Signal(); | ||
| 139 | } | 156 | } |
| 140 | 157 | ||
| 141 | void GetState(Kernel::HLERequestContext& ctx) { | 158 | void GetState(Kernel::HLERequestContext& ctx) { |
| 159 | State state = State::Error; | ||
| 160 | LOG_WARNING(Service_LDN, "(STUBBED) called, state = {}", state); | ||
| 161 | |||
| 162 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 163 | rb.Push(ResultSuccess); | ||
| 164 | rb.PushEnum(state); | ||
| 165 | } | ||
| 166 | |||
| 167 | void GetNetworkInfo(Kernel::HLERequestContext& ctx) { | ||
| 168 | const auto write_buffer_size = ctx.GetWriteBufferSize(); | ||
| 169 | |||
| 170 | if (write_buffer_size != sizeof(NetworkInfo)) { | ||
| 171 | LOG_ERROR(Service_LDN, "Invalid buffer size {}", write_buffer_size); | ||
| 172 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 173 | rb.Push(ResultBadInput); | ||
| 174 | return; | ||
| 175 | } | ||
| 176 | |||
| 177 | NetworkInfo network_info{}; | ||
| 178 | const auto rc = ResultSuccess; | ||
| 179 | if (rc.IsError()) { | ||
| 180 | LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw); | ||
| 181 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 182 | rb.Push(rc); | ||
| 183 | return; | ||
| 184 | } | ||
| 185 | |||
| 186 | LOG_WARNING(Service_LDN, "(STUBBED) called, ssid='{}', nodes={}", | ||
| 187 | network_info.common.ssid.GetStringValue(), network_info.ldn.node_count); | ||
| 188 | |||
| 189 | ctx.WriteBuffer<NetworkInfo>(network_info); | ||
| 190 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 191 | rb.Push(rc); | ||
| 192 | } | ||
| 193 | |||
| 194 | void GetDisconnectReason(Kernel::HLERequestContext& ctx) { | ||
| 195 | const auto disconnect_reason = DisconnectReason::None; | ||
| 196 | |||
| 197 | LOG_WARNING(Service_LDN, "(STUBBED) called, disconnect_reason={}", disconnect_reason); | ||
| 198 | |||
| 199 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 200 | rb.Push(ResultSuccess); | ||
| 201 | rb.PushEnum(disconnect_reason); | ||
| 202 | } | ||
| 203 | |||
| 204 | void GetSecurityParameter(Kernel::HLERequestContext& ctx) { | ||
| 205 | SecurityParameter security_parameter{}; | ||
| 206 | NetworkInfo info{}; | ||
| 207 | const Result rc = ResultSuccess; | ||
| 208 | |||
| 209 | if (rc.IsError()) { | ||
| 210 | LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw); | ||
| 211 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 212 | rb.Push(rc); | ||
| 213 | return; | ||
| 214 | } | ||
| 215 | |||
| 216 | security_parameter.session_id = info.network_id.session_id; | ||
| 217 | std::memcpy(security_parameter.data.data(), info.ldn.security_parameter.data(), | ||
| 218 | sizeof(SecurityParameter::data)); | ||
| 219 | |||
| 142 | LOG_WARNING(Service_LDN, "(STUBBED) called"); | 220 | LOG_WARNING(Service_LDN, "(STUBBED) called"); |
| 143 | 221 | ||
| 222 | IPC::ResponseBuilder rb{ctx, 10}; | ||
| 223 | rb.Push(rc); | ||
| 224 | rb.PushRaw<SecurityParameter>(security_parameter); | ||
| 225 | } | ||
| 226 | |||
| 227 | void GetNetworkConfig(Kernel::HLERequestContext& ctx) { | ||
| 228 | NetworkConfig config{}; | ||
| 229 | NetworkInfo info{}; | ||
| 230 | const Result rc = ResultSuccess; | ||
| 231 | |||
| 232 | if (rc.IsError()) { | ||
| 233 | LOG_ERROR(Service_LDN, "NetworkConfig is not valid {}", rc.raw); | ||
| 234 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 235 | rb.Push(rc); | ||
| 236 | return; | ||
| 237 | } | ||
| 238 | |||
| 239 | config.intent_id = info.network_id.intent_id; | ||
| 240 | config.channel = info.common.channel; | ||
| 241 | config.node_count_max = info.ldn.node_count_max; | ||
| 242 | config.local_communication_version = info.ldn.nodes[0].local_communication_version; | ||
| 243 | |||
| 244 | LOG_WARNING(Service_LDN, | ||
| 245 | "(STUBBED) called, intent_id={}/{}, channel={}, node_count_max={}, " | ||
| 246 | "local_communication_version={}", | ||
| 247 | config.intent_id.local_communication_id, config.intent_id.scene_id, | ||
| 248 | config.channel, config.node_count_max, config.local_communication_version); | ||
| 249 | |||
| 250 | IPC::ResponseBuilder rb{ctx, 10}; | ||
| 251 | rb.Push(rc); | ||
| 252 | rb.PushRaw<NetworkConfig>(config); | ||
| 253 | } | ||
| 254 | |||
| 255 | void AttachStateChangeEvent(Kernel::HLERequestContext& ctx) { | ||
| 256 | LOG_INFO(Service_LDN, "called"); | ||
| 257 | |||
| 258 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 259 | rb.Push(ResultSuccess); | ||
| 260 | rb.PushCopyObjects(state_change_event->GetReadableEvent()); | ||
| 261 | } | ||
| 262 | |||
| 263 | void GetNetworkInfoLatestUpdate(Kernel::HLERequestContext& ctx) { | ||
| 264 | const std::size_t network_buffer_size = ctx.GetWriteBufferSize(0); | ||
| 265 | const std::size_t node_buffer_count = ctx.GetWriteBufferSize(1) / sizeof(NodeLatestUpdate); | ||
| 266 | |||
| 267 | if (node_buffer_count == 0 || network_buffer_size != sizeof(NetworkInfo)) { | ||
| 268 | LOG_ERROR(Service_LDN, "Invalid buffer size {}, {}", network_buffer_size, | ||
| 269 | node_buffer_count); | ||
| 270 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 271 | rb.Push(ResultBadInput); | ||
| 272 | return; | ||
| 273 | } | ||
| 274 | |||
| 275 | NetworkInfo info; | ||
| 276 | std::vector<NodeLatestUpdate> latest_update(node_buffer_count); | ||
| 277 | |||
| 278 | const auto rc = ResultSuccess; | ||
| 279 | if (rc.IsError()) { | ||
| 280 | LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw); | ||
| 281 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 282 | rb.Push(rc); | ||
| 283 | return; | ||
| 284 | } | ||
| 285 | |||
| 286 | LOG_WARNING(Service_LDN, "(STUBBED) called, ssid='{}', nodes={}", | ||
| 287 | info.common.ssid.GetStringValue(), info.ldn.node_count); | ||
| 288 | |||
| 289 | ctx.WriteBuffer(info, 0); | ||
| 290 | ctx.WriteBuffer(latest_update, 1); | ||
| 291 | |||
| 292 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 293 | rb.Push(ResultSuccess); | ||
| 294 | } | ||
| 295 | |||
| 296 | void Scan(Kernel::HLERequestContext& ctx) { | ||
| 297 | ScanImpl(ctx); | ||
| 298 | } | ||
| 299 | |||
| 300 | void ScanPrivate(Kernel::HLERequestContext& ctx) { | ||
| 301 | ScanImpl(ctx, true); | ||
| 302 | } | ||
| 303 | |||
| 304 | void ScanImpl(Kernel::HLERequestContext& ctx, bool is_private = false) { | ||
| 305 | IPC::RequestParser rp{ctx}; | ||
| 306 | const auto channel{rp.PopEnum<WifiChannel>()}; | ||
| 307 | const auto scan_filter{rp.PopRaw<ScanFilter>()}; | ||
| 308 | |||
| 309 | const std::size_t network_info_size = ctx.GetWriteBufferSize() / sizeof(NetworkInfo); | ||
| 310 | |||
| 311 | if (network_info_size == 0) { | ||
| 312 | LOG_ERROR(Service_LDN, "Invalid buffer size {}", network_info_size); | ||
| 313 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 314 | rb.Push(ResultBadInput); | ||
| 315 | return; | ||
| 316 | } | ||
| 317 | |||
| 318 | u16 count = 0; | ||
| 319 | std::vector<NetworkInfo> network_infos(network_info_size); | ||
| 320 | |||
| 321 | LOG_WARNING(Service_LDN, | ||
| 322 | "(STUBBED) called, channel={}, filter_scan_flag={}, filter_network_type={}", | ||
| 323 | channel, scan_filter.flag, scan_filter.network_type); | ||
| 324 | |||
| 325 | ctx.WriteBuffer(network_infos); | ||
| 326 | |||
| 144 | IPC::ResponseBuilder rb{ctx, 3}; | 327 | IPC::ResponseBuilder rb{ctx, 3}; |
| 328 | rb.Push(ResultSuccess); | ||
| 329 | rb.Push<u32>(count); | ||
| 330 | } | ||
| 331 | |||
| 332 | void OpenAccessPoint(Kernel::HLERequestContext& ctx) { | ||
| 333 | LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||
| 334 | |||
| 335 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 336 | rb.Push(ResultSuccess); | ||
| 337 | } | ||
| 338 | |||
| 339 | void CloseAccessPoint(Kernel::HLERequestContext& ctx) { | ||
| 340 | LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||
| 341 | |||
| 342 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 343 | rb.Push(ResultSuccess); | ||
| 344 | } | ||
| 345 | |||
| 346 | void CreateNetwork(Kernel::HLERequestContext& ctx) { | ||
| 347 | IPC::RequestParser rp{ctx}; | ||
| 348 | struct Parameters { | ||
| 349 | SecurityConfig security_config; | ||
| 350 | UserConfig user_config; | ||
| 351 | INSERT_PADDING_WORDS_NOINIT(1); | ||
| 352 | NetworkConfig network_config; | ||
| 353 | }; | ||
| 354 | static_assert(sizeof(Parameters) == 0x98, "Parameters has incorrect size."); | ||
| 355 | |||
| 356 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 357 | |||
| 358 | LOG_WARNING(Service_LDN, | ||
| 359 | "(STUBBED) called, passphrase_size={}, security_mode={}, " | ||
| 360 | "local_communication_version={}", | ||
| 361 | parameters.security_config.passphrase_size, | ||
| 362 | parameters.security_config.security_mode, | ||
| 363 | parameters.network_config.local_communication_version); | ||
| 364 | |||
| 365 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 366 | rb.Push(ResultSuccess); | ||
| 367 | } | ||
| 368 | |||
| 369 | void CreateNetworkPrivate(Kernel::HLERequestContext& ctx) { | ||
| 370 | IPC::RequestParser rp{ctx}; | ||
| 371 | struct Parameters { | ||
| 372 | SecurityConfig security_config; | ||
| 373 | SecurityParameter security_parameter; | ||
| 374 | UserConfig user_config; | ||
| 375 | NetworkConfig network_config; | ||
| 376 | }; | ||
| 377 | static_assert(sizeof(Parameters) == 0xB8, "Parameters has incorrect size."); | ||
| 378 | |||
| 379 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 380 | |||
| 381 | LOG_WARNING(Service_LDN, | ||
| 382 | "(STUBBED) called, passphrase_size={}, security_mode={}, " | ||
| 383 | "local_communication_version={}", | ||
| 384 | parameters.security_config.passphrase_size, | ||
| 385 | parameters.security_config.security_mode, | ||
| 386 | parameters.network_config.local_communication_version); | ||
| 387 | |||
| 388 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 389 | rb.Push(ResultSuccess); | ||
| 390 | } | ||
| 391 | |||
| 392 | void DestroyNetwork(Kernel::HLERequestContext& ctx) { | ||
| 393 | LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||
| 394 | |||
| 395 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 396 | rb.Push(ResultSuccess); | ||
| 397 | } | ||
| 398 | |||
| 399 | void SetAdvertiseData(Kernel::HLERequestContext& ctx) { | ||
| 400 | std::vector<u8> read_buffer = ctx.ReadBuffer(); | ||
| 401 | |||
| 402 | LOG_WARNING(Service_LDN, "(STUBBED) called, size {}", read_buffer.size()); | ||
| 403 | |||
| 404 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 405 | rb.Push(ResultSuccess); | ||
| 406 | } | ||
| 407 | |||
| 408 | void SetStationAcceptPolicy(Kernel::HLERequestContext& ctx) { | ||
| 409 | LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||
| 410 | |||
| 411 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 412 | rb.Push(ResultSuccess); | ||
| 413 | } | ||
| 145 | 414 | ||
| 146 | // Indicate a network error, as we do not actually emulate LDN | 415 | void AddAcceptFilterEntry(Kernel::HLERequestContext& ctx) { |
| 147 | rb.Push(static_cast<u32>(State::Error)); | 416 | LOG_WARNING(Service_LDN, "(STUBBED) called"); |
| 148 | 417 | ||
| 418 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 419 | rb.Push(ResultSuccess); | ||
| 420 | } | ||
| 421 | |||
| 422 | void OpenStation(Kernel::HLERequestContext& ctx) { | ||
| 423 | LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||
| 424 | |||
| 425 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 426 | rb.Push(ResultSuccess); | ||
| 427 | } | ||
| 428 | |||
| 429 | void CloseStation(Kernel::HLERequestContext& ctx) { | ||
| 430 | LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||
| 431 | |||
| 432 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 433 | rb.Push(ResultSuccess); | ||
| 434 | } | ||
| 435 | |||
| 436 | void Connect(Kernel::HLERequestContext& ctx) { | ||
| 437 | IPC::RequestParser rp{ctx}; | ||
| 438 | struct Parameters { | ||
| 439 | SecurityConfig security_config; | ||
| 440 | UserConfig user_config; | ||
| 441 | u32 local_communication_version; | ||
| 442 | u32 option; | ||
| 443 | }; | ||
| 444 | static_assert(sizeof(Parameters) == 0x7C, "Parameters has incorrect size."); | ||
| 445 | |||
| 446 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 447 | |||
| 448 | LOG_WARNING(Service_LDN, | ||
| 449 | "(STUBBED) called, passphrase_size={}, security_mode={}, " | ||
| 450 | "local_communication_version={}", | ||
| 451 | parameters.security_config.passphrase_size, | ||
| 452 | parameters.security_config.security_mode, | ||
| 453 | parameters.local_communication_version); | ||
| 454 | |||
| 455 | const std::vector<u8> read_buffer = ctx.ReadBuffer(); | ||
| 456 | NetworkInfo network_info{}; | ||
| 457 | |||
| 458 | if (read_buffer.size() != sizeof(NetworkInfo)) { | ||
| 459 | LOG_ERROR(Frontend, "NetworkInfo doesn't match read_buffer size!"); | ||
| 460 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 461 | rb.Push(ResultBadInput); | ||
| 462 | return; | ||
| 463 | } | ||
| 464 | |||
| 465 | std::memcpy(&network_info, read_buffer.data(), read_buffer.size()); | ||
| 466 | |||
| 467 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 468 | rb.Push(ResultSuccess); | ||
| 469 | } | ||
| 470 | |||
| 471 | void Disconnect(Kernel::HLERequestContext& ctx) { | ||
| 472 | LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||
| 473 | |||
| 474 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 475 | rb.Push(ResultSuccess); | ||
| 476 | } | ||
| 477 | void Initialize(Kernel::HLERequestContext& ctx) { | ||
| 478 | LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||
| 479 | |||
| 480 | const auto rc = InitializeImpl(ctx); | ||
| 481 | |||
| 482 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 483 | rb.Push(rc); | ||
| 484 | } | ||
| 485 | |||
| 486 | void Finalize(Kernel::HLERequestContext& ctx) { | ||
| 487 | LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||
| 488 | |||
| 489 | is_initialized = false; | ||
| 490 | |||
| 491 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 149 | rb.Push(ResultSuccess); | 492 | rb.Push(ResultSuccess); |
| 150 | } | 493 | } |
| 151 | 494 | ||
| 152 | void Initialize2(Kernel::HLERequestContext& ctx) { | 495 | void Initialize2(Kernel::HLERequestContext& ctx) { |
| 153 | LOG_DEBUG(Service_LDN, "called"); | 496 | LOG_WARNING(Service_LDN, "(STUBBED) called"); |
| 154 | 497 | ||
| 155 | is_initialized = true; | 498 | const auto rc = InitializeImpl(ctx); |
| 156 | 499 | ||
| 157 | IPC::ResponseBuilder rb{ctx, 2}; | 500 | IPC::ResponseBuilder rb{ctx, 2}; |
| 158 | rb.Push(ERROR_DISABLED); | 501 | rb.Push(rc); |
| 502 | } | ||
| 503 | |||
| 504 | Result InitializeImpl(Kernel::HLERequestContext& ctx) { | ||
| 505 | const auto network_interface = Network::GetSelectedNetworkInterface(); | ||
| 506 | if (!network_interface) { | ||
| 507 | LOG_ERROR(Service_LDN, "No network interface is set"); | ||
| 508 | return ResultAirplaneModeEnabled; | ||
| 509 | } | ||
| 510 | |||
| 511 | is_initialized = true; | ||
| 512 | // TODO (flTobi): Change this to ResultSuccess when LDN is fully implemented | ||
| 513 | return ResultAirplaneModeEnabled; | ||
| 159 | } | 514 | } |
| 160 | 515 | ||
| 161 | private: | 516 | KernelHelpers::ServiceContext service_context; |
| 162 | enum class State { | 517 | Kernel::KEvent* state_change_event; |
| 163 | None, | 518 | Network::RoomNetwork& room_network; |
| 164 | Initialized, | ||
| 165 | AccessPointOpened, | ||
| 166 | AccessPointCreated, | ||
| 167 | StationOpened, | ||
| 168 | StationConnected, | ||
| 169 | Error, | ||
| 170 | }; | ||
| 171 | 519 | ||
| 172 | bool is_initialized{}; | 520 | bool is_initialized{}; |
| 173 | }; | 521 | }; |
| @@ -273,7 +621,7 @@ public: | |||
| 273 | LOG_WARNING(Service_LDN, "(STUBBED) called"); | 621 | LOG_WARNING(Service_LDN, "(STUBBED) called"); |
| 274 | 622 | ||
| 275 | IPC::ResponseBuilder rb{ctx, 2}; | 623 | IPC::ResponseBuilder rb{ctx, 2}; |
| 276 | rb.Push(ERROR_DISABLED); | 624 | rb.Push(ResultDisabled); |
| 277 | } | 625 | } |
| 278 | }; | 626 | }; |
| 279 | 627 | ||
diff --git a/src/core/hle/service/ldn/ldn.h b/src/core/hle/service/ldn/ldn.h index a0031ac71..6afe2ea6f 100644 --- a/src/core/hle/service/ldn/ldn.h +++ b/src/core/hle/service/ldn/ldn.h | |||
| @@ -3,6 +3,12 @@ | |||
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include "core/hle/ipc_helpers.h" | ||
| 7 | #include "core/hle/kernel/k_event.h" | ||
| 8 | #include "core/hle/result.h" | ||
| 9 | #include "core/hle/service/kernel_helpers.h" | ||
| 10 | #include "core/hle/service/sm/sm.h" | ||
| 11 | |||
| 6 | namespace Core { | 12 | namespace Core { |
| 7 | class System; | 13 | class System; |
| 8 | } | 14 | } |
diff --git a/src/core/hle/service/ldn/ldn_results.h b/src/core/hle/service/ldn/ldn_results.h new file mode 100644 index 000000000..f340bda42 --- /dev/null +++ b/src/core/hle/service/ldn/ldn_results.h | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/result.h" | ||
| 7 | |||
| 8 | namespace Service::LDN { | ||
| 9 | |||
| 10 | constexpr Result ResultAdvertiseDataTooLarge{ErrorModule::LDN, 10}; | ||
| 11 | constexpr Result ResultAuthenticationFailed{ErrorModule::LDN, 20}; | ||
| 12 | constexpr Result ResultDisabled{ErrorModule::LDN, 22}; | ||
| 13 | constexpr Result ResultAirplaneModeEnabled{ErrorModule::LDN, 23}; | ||
| 14 | constexpr Result ResultInvalidNodeCount{ErrorModule::LDN, 30}; | ||
| 15 | constexpr Result ResultConnectionFailed{ErrorModule::LDN, 31}; | ||
| 16 | constexpr Result ResultBadState{ErrorModule::LDN, 32}; | ||
| 17 | constexpr Result ResultNoIpAddress{ErrorModule::LDN, 33}; | ||
| 18 | constexpr Result ResultInvalidBufferCount{ErrorModule::LDN, 50}; | ||
| 19 | constexpr Result ResultAccessPointConnectionFailed{ErrorModule::LDN, 65}; | ||
| 20 | constexpr Result ResultAuthenticationTimeout{ErrorModule::LDN, 66}; | ||
| 21 | constexpr Result ResultMaximumNodeCount{ErrorModule::LDN, 67}; | ||
| 22 | constexpr Result ResultBadInput{ErrorModule::LDN, 96}; | ||
| 23 | constexpr Result ResultLocalCommunicationIdNotFound{ErrorModule::LDN, 97}; | ||
| 24 | constexpr Result ResultLocalCommunicationVersionTooLow{ErrorModule::LDN, 113}; | ||
| 25 | constexpr Result ResultLocalCommunicationVersionTooHigh{ErrorModule::LDN, 114}; | ||
| 26 | |||
| 27 | } // namespace Service::LDN | ||
diff --git a/src/core/hle/service/ldn/ldn_types.h b/src/core/hle/service/ldn/ldn_types.h new file mode 100644 index 000000000..6231e936d --- /dev/null +++ b/src/core/hle/service/ldn/ldn_types.h | |||
| @@ -0,0 +1,292 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <fmt/format.h> | ||
| 7 | |||
| 8 | #include "common/common_funcs.h" | ||
| 9 | #include "common/common_types.h" | ||
| 10 | #include "network/network.h" | ||
| 11 | |||
| 12 | namespace Service::LDN { | ||
| 13 | |||
| 14 | constexpr size_t SsidLengthMax = 32; | ||
| 15 | constexpr size_t AdvertiseDataSizeMax = 384; | ||
| 16 | constexpr size_t UserNameBytesMax = 32; | ||
| 17 | constexpr int NodeCountMax = 8; | ||
| 18 | constexpr int StationCountMax = NodeCountMax - 1; | ||
| 19 | constexpr size_t PassphraseLengthMax = 64; | ||
| 20 | |||
| 21 | enum class SecurityMode : u16 { | ||
| 22 | All, | ||
| 23 | Retail, | ||
| 24 | Debug, | ||
| 25 | }; | ||
| 26 | |||
| 27 | enum class NodeStateChange : u8 { | ||
| 28 | None, | ||
| 29 | Connect, | ||
| 30 | Disconnect, | ||
| 31 | DisconnectAndConnect, | ||
| 32 | }; | ||
| 33 | |||
| 34 | enum class ScanFilterFlag : u32 { | ||
| 35 | None = 0, | ||
| 36 | LocalCommunicationId = 1 << 0, | ||
| 37 | SessionId = 1 << 1, | ||
| 38 | NetworkType = 1 << 2, | ||
| 39 | Ssid = 1 << 4, | ||
| 40 | SceneId = 1 << 5, | ||
| 41 | IntentId = LocalCommunicationId | SceneId, | ||
| 42 | NetworkId = IntentId | SessionId, | ||
| 43 | }; | ||
| 44 | |||
| 45 | enum class NetworkType : u32 { | ||
| 46 | None, | ||
| 47 | General, | ||
| 48 | Ldn, | ||
| 49 | All, | ||
| 50 | }; | ||
| 51 | |||
| 52 | enum class PackedNetworkType : u8 { | ||
| 53 | None, | ||
| 54 | General, | ||
| 55 | Ldn, | ||
| 56 | All, | ||
| 57 | }; | ||
| 58 | |||
| 59 | enum class State : u32 { | ||
| 60 | None, | ||
| 61 | Initialized, | ||
| 62 | AccessPointOpened, | ||
| 63 | AccessPointCreated, | ||
| 64 | StationOpened, | ||
| 65 | StationConnected, | ||
| 66 | Error, | ||
| 67 | }; | ||
| 68 | |||
| 69 | enum class DisconnectReason : s16 { | ||
| 70 | Unknown = -1, | ||
| 71 | None, | ||
| 72 | DisconnectedByUser, | ||
| 73 | DisconnectedBySystem, | ||
| 74 | DestroyedByUser, | ||
| 75 | DestroyedBySystem, | ||
| 76 | Rejected, | ||
| 77 | SignalLost, | ||
| 78 | }; | ||
| 79 | |||
| 80 | enum class NetworkError { | ||
| 81 | Unknown = -1, | ||
| 82 | None = 0, | ||
| 83 | PortUnreachable, | ||
| 84 | TooManyPlayers, | ||
| 85 | VersionTooLow, | ||
| 86 | VersionTooHigh, | ||
| 87 | ConnectFailure, | ||
| 88 | ConnectNotFound, | ||
| 89 | ConnectTimeout, | ||
| 90 | ConnectRejected, | ||
| 91 | RejectFailed, | ||
| 92 | }; | ||
| 93 | |||
| 94 | enum class AcceptPolicy : u8 { | ||
| 95 | AcceptAll, | ||
| 96 | RejectAll, | ||
| 97 | BlackList, | ||
| 98 | WhiteList, | ||
| 99 | }; | ||
| 100 | |||
| 101 | enum class WifiChannel : s16 { | ||
| 102 | Default = 0, | ||
| 103 | wifi24_1 = 1, | ||
| 104 | wifi24_6 = 6, | ||
| 105 | wifi24_11 = 11, | ||
| 106 | wifi50_36 = 36, | ||
| 107 | wifi50_40 = 40, | ||
| 108 | wifi50_44 = 44, | ||
| 109 | wifi50_48 = 48, | ||
| 110 | }; | ||
| 111 | |||
| 112 | enum class LinkLevel : s8 { | ||
| 113 | Bad, | ||
| 114 | Low, | ||
| 115 | Good, | ||
| 116 | Excellent, | ||
| 117 | }; | ||
| 118 | |||
| 119 | struct NodeLatestUpdate { | ||
| 120 | NodeStateChange state_change; | ||
| 121 | INSERT_PADDING_BYTES(0x7); // Unknown | ||
| 122 | }; | ||
| 123 | static_assert(sizeof(NodeLatestUpdate) == 0x8, "NodeLatestUpdate is an invalid size"); | ||
| 124 | |||
| 125 | struct SessionId { | ||
| 126 | u64 high; | ||
| 127 | u64 low; | ||
| 128 | |||
| 129 | bool operator==(const SessionId&) const = default; | ||
| 130 | }; | ||
| 131 | static_assert(sizeof(SessionId) == 0x10, "SessionId is an invalid size"); | ||
| 132 | |||
| 133 | struct IntentId { | ||
| 134 | u64 local_communication_id; | ||
| 135 | INSERT_PADDING_BYTES(0x2); // Reserved | ||
| 136 | u16 scene_id; | ||
| 137 | INSERT_PADDING_BYTES(0x4); // Reserved | ||
| 138 | }; | ||
| 139 | static_assert(sizeof(IntentId) == 0x10, "IntentId is an invalid size"); | ||
| 140 | |||
| 141 | struct NetworkId { | ||
| 142 | IntentId intent_id; | ||
| 143 | SessionId session_id; | ||
| 144 | }; | ||
| 145 | static_assert(sizeof(NetworkId) == 0x20, "NetworkId is an invalid size"); | ||
| 146 | |||
| 147 | struct Ssid { | ||
| 148 | u8 length{}; | ||
| 149 | std::array<char, SsidLengthMax + 1> raw{}; | ||
| 150 | |||
| 151 | Ssid() = default; | ||
| 152 | |||
| 153 | explicit Ssid(std::string_view data) { | ||
| 154 | length = static_cast<u8>(std::min(data.size(), SsidLengthMax)); | ||
| 155 | data.copy(raw.data(), length); | ||
| 156 | raw[length] = 0; | ||
| 157 | } | ||
| 158 | |||
| 159 | std::string GetStringValue() const { | ||
| 160 | return std::string(raw.data()); | ||
| 161 | } | ||
| 162 | }; | ||
| 163 | static_assert(sizeof(Ssid) == 0x22, "Ssid is an invalid size"); | ||
| 164 | |||
| 165 | struct Ipv4Address { | ||
| 166 | union { | ||
| 167 | u32 raw{}; | ||
| 168 | std::array<u8, 4> bytes; | ||
| 169 | }; | ||
| 170 | |||
| 171 | std::string GetStringValue() const { | ||
| 172 | return fmt::format("{}.{}.{}.{}", bytes[3], bytes[2], bytes[1], bytes[0]); | ||
| 173 | } | ||
| 174 | }; | ||
| 175 | static_assert(sizeof(Ipv4Address) == 0x4, "Ipv4Address is an invalid size"); | ||
| 176 | |||
| 177 | struct MacAddress { | ||
| 178 | std::array<u8, 6> raw{}; | ||
| 179 | |||
| 180 | friend bool operator==(const MacAddress& lhs, const MacAddress& rhs) = default; | ||
| 181 | }; | ||
| 182 | static_assert(sizeof(MacAddress) == 0x6, "MacAddress is an invalid size"); | ||
| 183 | |||
| 184 | struct ScanFilter { | ||
| 185 | NetworkId network_id; | ||
| 186 | NetworkType network_type; | ||
| 187 | MacAddress mac_address; | ||
| 188 | Ssid ssid; | ||
| 189 | INSERT_PADDING_BYTES(0x10); | ||
| 190 | ScanFilterFlag flag; | ||
| 191 | }; | ||
| 192 | static_assert(sizeof(ScanFilter) == 0x60, "ScanFilter is an invalid size"); | ||
| 193 | |||
| 194 | struct CommonNetworkInfo { | ||
| 195 | MacAddress bssid; | ||
| 196 | Ssid ssid; | ||
| 197 | WifiChannel channel; | ||
| 198 | LinkLevel link_level; | ||
| 199 | PackedNetworkType network_type; | ||
| 200 | INSERT_PADDING_BYTES(0x4); | ||
| 201 | }; | ||
| 202 | static_assert(sizeof(CommonNetworkInfo) == 0x30, "CommonNetworkInfo is an invalid size"); | ||
| 203 | |||
| 204 | struct NodeInfo { | ||
| 205 | Ipv4Address ipv4_address; | ||
| 206 | MacAddress mac_address; | ||
| 207 | s8 node_id; | ||
| 208 | u8 is_connected; | ||
| 209 | std::array<u8, UserNameBytesMax + 1> user_name; | ||
| 210 | INSERT_PADDING_BYTES(0x1); // Reserved | ||
| 211 | s16 local_communication_version; | ||
| 212 | INSERT_PADDING_BYTES(0x10); // Reserved | ||
| 213 | }; | ||
| 214 | static_assert(sizeof(NodeInfo) == 0x40, "NodeInfo is an invalid size"); | ||
| 215 | |||
| 216 | struct LdnNetworkInfo { | ||
| 217 | std::array<u8, 0x10> security_parameter; | ||
| 218 | SecurityMode security_mode; | ||
| 219 | AcceptPolicy station_accept_policy; | ||
| 220 | u8 has_action_frame; | ||
| 221 | INSERT_PADDING_BYTES(0x2); // Padding | ||
| 222 | u8 node_count_max; | ||
| 223 | u8 node_count; | ||
| 224 | std::array<NodeInfo, NodeCountMax> nodes; | ||
| 225 | INSERT_PADDING_BYTES(0x2); // Reserved | ||
| 226 | u16 advertise_data_size; | ||
| 227 | std::array<u8, AdvertiseDataSizeMax> advertise_data; | ||
| 228 | INSERT_PADDING_BYTES(0x8C); // Reserved | ||
| 229 | u64 random_authentication_id; | ||
| 230 | }; | ||
| 231 | static_assert(sizeof(LdnNetworkInfo) == 0x430, "LdnNetworkInfo is an invalid size"); | ||
| 232 | |||
| 233 | struct NetworkInfo { | ||
| 234 | NetworkId network_id; | ||
| 235 | CommonNetworkInfo common; | ||
| 236 | LdnNetworkInfo ldn; | ||
| 237 | }; | ||
| 238 | static_assert(sizeof(NetworkInfo) == 0x480, "NetworkInfo is an invalid size"); | ||
| 239 | |||
| 240 | struct SecurityConfig { | ||
| 241 | SecurityMode security_mode; | ||
| 242 | u16 passphrase_size; | ||
| 243 | std::array<u8, PassphraseLengthMax> passphrase; | ||
| 244 | }; | ||
| 245 | static_assert(sizeof(SecurityConfig) == 0x44, "SecurityConfig is an invalid size"); | ||
| 246 | |||
| 247 | struct UserConfig { | ||
| 248 | std::array<u8, UserNameBytesMax + 1> user_name; | ||
| 249 | INSERT_PADDING_BYTES(0xF); // Reserved | ||
| 250 | }; | ||
| 251 | static_assert(sizeof(UserConfig) == 0x30, "UserConfig is an invalid size"); | ||
| 252 | |||
| 253 | #pragma pack(push, 4) | ||
| 254 | struct ConnectRequest { | ||
| 255 | SecurityConfig security_config; | ||
| 256 | UserConfig user_config; | ||
| 257 | u32 local_communication_version; | ||
| 258 | u32 option_unknown; | ||
| 259 | NetworkInfo network_info; | ||
| 260 | }; | ||
| 261 | static_assert(sizeof(ConnectRequest) == 0x4FC, "ConnectRequest is an invalid size"); | ||
| 262 | #pragma pack(pop) | ||
| 263 | |||
| 264 | struct SecurityParameter { | ||
| 265 | std::array<u8, 0x10> data; // Data, used with the same key derivation as SecurityConfig | ||
| 266 | SessionId session_id; | ||
| 267 | }; | ||
| 268 | static_assert(sizeof(SecurityParameter) == 0x20, "SecurityParameter is an invalid size"); | ||
| 269 | |||
| 270 | struct NetworkConfig { | ||
| 271 | IntentId intent_id; | ||
| 272 | WifiChannel channel; | ||
| 273 | u8 node_count_max; | ||
| 274 | INSERT_PADDING_BYTES(0x1); // Reserved | ||
| 275 | u16 local_communication_version; | ||
| 276 | INSERT_PADDING_BYTES(0xA); // Reserved | ||
| 277 | }; | ||
| 278 | static_assert(sizeof(NetworkConfig) == 0x20, "NetworkConfig is an invalid size"); | ||
| 279 | |||
| 280 | struct AddressEntry { | ||
| 281 | Ipv4Address ipv4_address; | ||
| 282 | MacAddress mac_address; | ||
| 283 | INSERT_PADDING_BYTES(0x2); // Reserved | ||
| 284 | }; | ||
| 285 | static_assert(sizeof(AddressEntry) == 0xC, "AddressEntry is an invalid size"); | ||
| 286 | |||
| 287 | struct AddressList { | ||
| 288 | std::array<AddressEntry, 0x8> addresses; | ||
| 289 | }; | ||
| 290 | static_assert(sizeof(AddressList) == 0x60, "AddressList is an invalid size"); | ||
| 291 | |||
| 292 | } // namespace Service::LDN | ||
diff --git a/src/core/hle/service/mm/mm_u.cpp b/src/core/hle/service/mm/mm_u.cpp index 5ebb124a7..ba8c0e230 100644 --- a/src/core/hle/service/mm/mm_u.cpp +++ b/src/core/hle/service/mm/mm_u.cpp | |||
| @@ -46,7 +46,7 @@ private: | |||
| 46 | IPC::RequestParser rp{ctx}; | 46 | IPC::RequestParser rp{ctx}; |
| 47 | min = rp.Pop<u32>(); | 47 | min = rp.Pop<u32>(); |
| 48 | max = rp.Pop<u32>(); | 48 | max = rp.Pop<u32>(); |
| 49 | LOG_WARNING(Service_MM, "(STUBBED) called, min=0x{:X}, max=0x{:X}", min, max); | 49 | LOG_DEBUG(Service_MM, "(STUBBED) called, min=0x{:X}, max=0x{:X}", min, max); |
| 50 | 50 | ||
| 51 | current = min; | 51 | current = min; |
| 52 | IPC::ResponseBuilder rb{ctx, 2}; | 52 | IPC::ResponseBuilder rb{ctx, 2}; |
| @@ -54,7 +54,7 @@ private: | |||
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | void GetOld(Kernel::HLERequestContext& ctx) { | 56 | void GetOld(Kernel::HLERequestContext& ctx) { |
| 57 | LOG_WARNING(Service_MM, "(STUBBED) called"); | 57 | LOG_DEBUG(Service_MM, "(STUBBED) called"); |
| 58 | 58 | ||
| 59 | IPC::ResponseBuilder rb{ctx, 3}; | 59 | IPC::ResponseBuilder rb{ctx, 3}; |
| 60 | rb.Push(ResultSuccess); | 60 | rb.Push(ResultSuccess); |
| @@ -81,8 +81,8 @@ private: | |||
| 81 | u32 input_id = rp.Pop<u32>(); | 81 | u32 input_id = rp.Pop<u32>(); |
| 82 | min = rp.Pop<u32>(); | 82 | min = rp.Pop<u32>(); |
| 83 | max = rp.Pop<u32>(); | 83 | max = rp.Pop<u32>(); |
| 84 | LOG_WARNING(Service_MM, "(STUBBED) called, input_id=0x{:X}, min=0x{:X}, max=0x{:X}", | 84 | LOG_DEBUG(Service_MM, "(STUBBED) called, input_id=0x{:X}, min=0x{:X}, max=0x{:X}", input_id, |
| 85 | input_id, min, max); | 85 | min, max); |
| 86 | 86 | ||
| 87 | current = min; | 87 | current = min; |
| 88 | IPC::ResponseBuilder rb{ctx, 2}; | 88 | IPC::ResponseBuilder rb{ctx, 2}; |
| @@ -90,7 +90,7 @@ private: | |||
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | void Get(Kernel::HLERequestContext& ctx) { | 92 | void Get(Kernel::HLERequestContext& ctx) { |
| 93 | LOG_WARNING(Service_MM, "(STUBBED) called"); | 93 | LOG_DEBUG(Service_MM, "(STUBBED) called"); |
| 94 | 94 | ||
| 95 | IPC::ResponseBuilder rb{ctx, 3}; | 95 | IPC::ResponseBuilder rb{ctx, 3}; |
| 96 | rb.Push(ResultSuccess); | 96 | rb.Push(ResultSuccess); |
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp index 2889973e4..e3ef06481 100644 --- a/src/core/hle/service/nifm/nifm.cpp +++ b/src/core/hle/service/nifm/nifm.cpp | |||
| @@ -6,7 +6,6 @@ | |||
| 6 | #include "core/hle/kernel/k_event.h" | 6 | #include "core/hle/kernel/k_event.h" |
| 7 | #include "core/hle/service/kernel_helpers.h" | 7 | #include "core/hle/service/kernel_helpers.h" |
| 8 | #include "core/hle/service/nifm/nifm.h" | 8 | #include "core/hle/service/nifm/nifm.h" |
| 9 | #include "core/hle/service/service.h" | ||
| 10 | 9 | ||
| 11 | namespace { | 10 | namespace { |
| 12 | 11 | ||
| @@ -271,213 +270,228 @@ public: | |||
| 271 | } | 270 | } |
| 272 | }; | 271 | }; |
| 273 | 272 | ||
| 274 | class IGeneralService final : public ServiceFramework<IGeneralService> { | 273 | void IGeneralService::GetClientId(Kernel::HLERequestContext& ctx) { |
| 275 | public: | 274 | static constexpr u32 client_id = 1; |
| 276 | explicit IGeneralService(Core::System& system_); | 275 | LOG_WARNING(Service_NIFM, "(STUBBED) called"); |
| 277 | 276 | ||
| 278 | private: | 277 | IPC::ResponseBuilder rb{ctx, 4}; |
| 279 | void GetClientId(Kernel::HLERequestContext& ctx) { | 278 | rb.Push(ResultSuccess); |
| 280 | static constexpr u32 client_id = 1; | 279 | rb.Push<u64>(client_id); // Client ID needs to be non zero otherwise it's considered invalid |
| 281 | LOG_WARNING(Service_NIFM, "(STUBBED) called"); | 280 | } |
| 282 | 281 | ||
| 283 | IPC::ResponseBuilder rb{ctx, 4}; | 282 | void IGeneralService::CreateScanRequest(Kernel::HLERequestContext& ctx) { |
| 284 | rb.Push(ResultSuccess); | 283 | LOG_DEBUG(Service_NIFM, "called"); |
| 285 | rb.Push<u64>(client_id); // Client ID needs to be non zero otherwise it's considered invalid | ||
| 286 | } | ||
| 287 | 284 | ||
| 288 | void CreateScanRequest(Kernel::HLERequestContext& ctx) { | 285 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 289 | LOG_DEBUG(Service_NIFM, "called"); | ||
| 290 | 286 | ||
| 291 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 287 | rb.Push(ResultSuccess); |
| 288 | rb.PushIpcInterface<IScanRequest>(system); | ||
| 289 | } | ||
| 292 | 290 | ||
| 293 | rb.Push(ResultSuccess); | 291 | void IGeneralService::CreateRequest(Kernel::HLERequestContext& ctx) { |
| 294 | rb.PushIpcInterface<IScanRequest>(system); | 292 | LOG_DEBUG(Service_NIFM, "called"); |
| 295 | } | ||
| 296 | 293 | ||
| 297 | void CreateRequest(Kernel::HLERequestContext& ctx) { | 294 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 298 | LOG_DEBUG(Service_NIFM, "called"); | ||
| 299 | 295 | ||
| 300 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 296 | rb.Push(ResultSuccess); |
| 297 | rb.PushIpcInterface<IRequest>(system); | ||
| 298 | } | ||
| 301 | 299 | ||
| 302 | rb.Push(ResultSuccess); | 300 | void IGeneralService::GetCurrentNetworkProfile(Kernel::HLERequestContext& ctx) { |
| 303 | rb.PushIpcInterface<IRequest>(system); | 301 | LOG_WARNING(Service_NIFM, "(STUBBED) called"); |
| 304 | } | ||
| 305 | 302 | ||
| 306 | void GetCurrentNetworkProfile(Kernel::HLERequestContext& ctx) { | 303 | const auto net_iface = Network::GetSelectedNetworkInterface(); |
| 307 | LOG_WARNING(Service_NIFM, "(STUBBED) called"); | ||
| 308 | 304 | ||
| 309 | const auto net_iface = Network::GetSelectedNetworkInterface(); | 305 | SfNetworkProfileData network_profile_data = [&net_iface] { |
| 310 | 306 | if (!net_iface) { | |
| 311 | const SfNetworkProfileData network_profile_data = [&net_iface] { | 307 | return SfNetworkProfileData{}; |
| 312 | if (!net_iface) { | 308 | } |
| 313 | return SfNetworkProfileData{}; | 309 | |
| 314 | } | 310 | return SfNetworkProfileData{ |
| 315 | 311 | .ip_setting_data{ | |
| 316 | return SfNetworkProfileData{ | 312 | .ip_address_setting{ |
| 317 | .ip_setting_data{ | 313 | .is_automatic{true}, |
| 318 | .ip_address_setting{ | 314 | .current_address{Network::TranslateIPv4(net_iface->ip_address)}, |
| 319 | .is_automatic{true}, | 315 | .subnet_mask{Network::TranslateIPv4(net_iface->subnet_mask)}, |
| 320 | .current_address{Network::TranslateIPv4(net_iface->ip_address)}, | 316 | .gateway{Network::TranslateIPv4(net_iface->gateway)}, |
| 321 | .subnet_mask{Network::TranslateIPv4(net_iface->subnet_mask)}, | ||
| 322 | .gateway{Network::TranslateIPv4(net_iface->gateway)}, | ||
| 323 | }, | ||
| 324 | .dns_setting{ | ||
| 325 | .is_automatic{true}, | ||
| 326 | .primary_dns{1, 1, 1, 1}, | ||
| 327 | .secondary_dns{1, 0, 0, 1}, | ||
| 328 | }, | ||
| 329 | .proxy_setting{ | ||
| 330 | .enabled{false}, | ||
| 331 | .port{}, | ||
| 332 | .proxy_server{}, | ||
| 333 | .automatic_auth_enabled{}, | ||
| 334 | .user{}, | ||
| 335 | .password{}, | ||
| 336 | }, | ||
| 337 | .mtu{1500}, | ||
| 338 | }, | 317 | }, |
| 339 | .uuid{0xdeadbeef, 0xdeadbeef}, | 318 | .dns_setting{ |
| 340 | .network_name{"yuzu Network"}, | 319 | .is_automatic{true}, |
| 341 | .wireless_setting_data{ | 320 | .primary_dns{1, 1, 1, 1}, |
| 342 | .ssid_length{12}, | 321 | .secondary_dns{1, 0, 0, 1}, |
| 343 | .ssid{"yuzu Network"}, | ||
| 344 | .passphrase{"yuzupassword"}, | ||
| 345 | }, | 322 | }, |
| 346 | }; | 323 | .proxy_setting{ |
| 347 | }(); | 324 | .enabled{false}, |
| 348 | 325 | .port{}, | |
| 349 | ctx.WriteBuffer(network_profile_data); | 326 | .proxy_server{}, |
| 327 | .automatic_auth_enabled{}, | ||
| 328 | .user{}, | ||
| 329 | .password{}, | ||
| 330 | }, | ||
| 331 | .mtu{1500}, | ||
| 332 | }, | ||
| 333 | .uuid{0xdeadbeef, 0xdeadbeef}, | ||
| 334 | .network_name{"yuzu Network"}, | ||
| 335 | .wireless_setting_data{ | ||
| 336 | .ssid_length{12}, | ||
| 337 | .ssid{"yuzu Network"}, | ||
| 338 | .passphrase{"yuzupassword"}, | ||
| 339 | }, | ||
| 340 | }; | ||
| 341 | }(); | ||
| 350 | 342 | ||
| 351 | IPC::ResponseBuilder rb{ctx, 2}; | 343 | // When we're connected to a room, spoof the hosts IP address |
| 352 | rb.Push(ResultSuccess); | 344 | if (auto room_member = network.GetRoomMember().lock()) { |
| 345 | if (room_member->IsConnected()) { | ||
| 346 | network_profile_data.ip_setting_data.ip_address_setting.current_address = | ||
| 347 | room_member->GetFakeIpAddress(); | ||
| 348 | } | ||
| 353 | } | 349 | } |
| 354 | 350 | ||
| 355 | void RemoveNetworkProfile(Kernel::HLERequestContext& ctx) { | 351 | ctx.WriteBuffer(network_profile_data); |
| 356 | LOG_WARNING(Service_NIFM, "(STUBBED) called"); | ||
| 357 | 352 | ||
| 358 | IPC::ResponseBuilder rb{ctx, 2}; | 353 | IPC::ResponseBuilder rb{ctx, 2}; |
| 359 | rb.Push(ResultSuccess); | 354 | rb.Push(ResultSuccess); |
| 360 | } | 355 | } |
| 361 | 356 | ||
| 362 | void GetCurrentIpAddress(Kernel::HLERequestContext& ctx) { | 357 | void IGeneralService::RemoveNetworkProfile(Kernel::HLERequestContext& ctx) { |
| 363 | LOG_WARNING(Service_NIFM, "(STUBBED) called"); | 358 | LOG_WARNING(Service_NIFM, "(STUBBED) called"); |
| 364 | 359 | ||
| 365 | auto ipv4 = Network::GetHostIPv4Address(); | 360 | IPC::ResponseBuilder rb{ctx, 2}; |
| 366 | if (!ipv4) { | 361 | rb.Push(ResultSuccess); |
| 367 | LOG_ERROR(Service_NIFM, "Couldn't get host IPv4 address, defaulting to 0.0.0.0"); | 362 | } |
| 368 | ipv4.emplace(Network::IPv4Address{0, 0, 0, 0}); | ||
| 369 | } | ||
| 370 | 363 | ||
| 371 | IPC::ResponseBuilder rb{ctx, 3}; | 364 | void IGeneralService::GetCurrentIpAddress(Kernel::HLERequestContext& ctx) { |
| 372 | rb.Push(ResultSuccess); | 365 | LOG_WARNING(Service_NIFM, "(STUBBED) called"); |
| 373 | rb.PushRaw(*ipv4); | 366 | |
| 367 | auto ipv4 = Network::GetHostIPv4Address(); | ||
| 368 | if (!ipv4) { | ||
| 369 | LOG_ERROR(Service_NIFM, "Couldn't get host IPv4 address, defaulting to 0.0.0.0"); | ||
| 370 | ipv4.emplace(Network::IPv4Address{0, 0, 0, 0}); | ||
| 374 | } | 371 | } |
| 375 | 372 | ||
| 376 | void CreateTemporaryNetworkProfile(Kernel::HLERequestContext& ctx) { | 373 | // When we're connected to a room, spoof the hosts IP address |
| 377 | LOG_DEBUG(Service_NIFM, "called"); | 374 | if (auto room_member = network.GetRoomMember().lock()) { |
| 375 | if (room_member->IsConnected()) { | ||
| 376 | ipv4 = room_member->GetFakeIpAddress(); | ||
| 377 | } | ||
| 378 | } | ||
| 378 | 379 | ||
| 379 | ASSERT_MSG(ctx.GetReadBufferSize() == 0x17c, | 380 | IPC::ResponseBuilder rb{ctx, 3}; |
| 380 | "SfNetworkProfileData is not the correct size"); | 381 | rb.Push(ResultSuccess); |
| 381 | u128 uuid{}; | 382 | rb.PushRaw(*ipv4); |
| 382 | auto buffer = ctx.ReadBuffer(); | 383 | } |
| 383 | std::memcpy(&uuid, buffer.data() + 8, sizeof(u128)); | ||
| 384 | 384 | ||
| 385 | IPC::ResponseBuilder rb{ctx, 6, 0, 1}; | 385 | void IGeneralService::CreateTemporaryNetworkProfile(Kernel::HLERequestContext& ctx) { |
| 386 | LOG_DEBUG(Service_NIFM, "called"); | ||
| 386 | 387 | ||
| 387 | rb.Push(ResultSuccess); | 388 | ASSERT_MSG(ctx.GetReadBufferSize() == 0x17c, "SfNetworkProfileData is not the correct size"); |
| 388 | rb.PushIpcInterface<INetworkProfile>(system); | 389 | u128 uuid{}; |
| 389 | rb.PushRaw<u128>(uuid); | 390 | auto buffer = ctx.ReadBuffer(); |
| 390 | } | 391 | std::memcpy(&uuid, buffer.data() + 8, sizeof(u128)); |
| 391 | 392 | ||
| 392 | void GetCurrentIpConfigInfo(Kernel::HLERequestContext& ctx) { | 393 | IPC::ResponseBuilder rb{ctx, 6, 0, 1}; |
| 393 | LOG_WARNING(Service_NIFM, "(STUBBED) called"); | ||
| 394 | 394 | ||
| 395 | struct IpConfigInfo { | 395 | rb.Push(ResultSuccess); |
| 396 | IpAddressSetting ip_address_setting{}; | 396 | rb.PushIpcInterface<INetworkProfile>(system); |
| 397 | DnsSetting dns_setting{}; | 397 | rb.PushRaw<u128>(uuid); |
| 398 | }; | 398 | } |
| 399 | static_assert(sizeof(IpConfigInfo) == sizeof(IpAddressSetting) + sizeof(DnsSetting), | ||
| 400 | "IpConfigInfo has incorrect size."); | ||
| 401 | 399 | ||
| 402 | const auto net_iface = Network::GetSelectedNetworkInterface(); | 400 | void IGeneralService::GetCurrentIpConfigInfo(Kernel::HLERequestContext& ctx) { |
| 401 | LOG_WARNING(Service_NIFM, "(STUBBED) called"); | ||
| 403 | 402 | ||
| 404 | const IpConfigInfo ip_config_info = [&net_iface] { | 403 | struct IpConfigInfo { |
| 405 | if (!net_iface) { | 404 | IpAddressSetting ip_address_setting{}; |
| 406 | return IpConfigInfo{}; | 405 | DnsSetting dns_setting{}; |
| 407 | } | 406 | }; |
| 407 | static_assert(sizeof(IpConfigInfo) == sizeof(IpAddressSetting) + sizeof(DnsSetting), | ||
| 408 | "IpConfigInfo has incorrect size."); | ||
| 408 | 409 | ||
| 409 | return IpConfigInfo{ | 410 | const auto net_iface = Network::GetSelectedNetworkInterface(); |
| 410 | .ip_address_setting{ | ||
| 411 | .is_automatic{true}, | ||
| 412 | .current_address{Network::TranslateIPv4(net_iface->ip_address)}, | ||
| 413 | .subnet_mask{Network::TranslateIPv4(net_iface->subnet_mask)}, | ||
| 414 | .gateway{Network::TranslateIPv4(net_iface->gateway)}, | ||
| 415 | }, | ||
| 416 | .dns_setting{ | ||
| 417 | .is_automatic{true}, | ||
| 418 | .primary_dns{1, 1, 1, 1}, | ||
| 419 | .secondary_dns{1, 0, 0, 1}, | ||
| 420 | }, | ||
| 421 | }; | ||
| 422 | }(); | ||
| 423 | 411 | ||
| 424 | IPC::ResponseBuilder rb{ctx, 2 + (sizeof(IpConfigInfo) + 3) / sizeof(u32)}; | 412 | IpConfigInfo ip_config_info = [&net_iface] { |
| 425 | rb.Push(ResultSuccess); | 413 | if (!net_iface) { |
| 426 | rb.PushRaw<IpConfigInfo>(ip_config_info); | 414 | return IpConfigInfo{}; |
| 427 | } | 415 | } |
| 428 | 416 | ||
| 429 | void IsWirelessCommunicationEnabled(Kernel::HLERequestContext& ctx) { | 417 | return IpConfigInfo{ |
| 430 | LOG_WARNING(Service_NIFM, "(STUBBED) called"); | 418 | .ip_address_setting{ |
| 419 | .is_automatic{true}, | ||
| 420 | .current_address{Network::TranslateIPv4(net_iface->ip_address)}, | ||
| 421 | .subnet_mask{Network::TranslateIPv4(net_iface->subnet_mask)}, | ||
| 422 | .gateway{Network::TranslateIPv4(net_iface->gateway)}, | ||
| 423 | }, | ||
| 424 | .dns_setting{ | ||
| 425 | .is_automatic{true}, | ||
| 426 | .primary_dns{1, 1, 1, 1}, | ||
| 427 | .secondary_dns{1, 0, 0, 1}, | ||
| 428 | }, | ||
| 429 | }; | ||
| 430 | }(); | ||
| 431 | 431 | ||
| 432 | IPC::ResponseBuilder rb{ctx, 3}; | 432 | // When we're connected to a room, spoof the hosts IP address |
| 433 | rb.Push(ResultSuccess); | 433 | if (auto room_member = network.GetRoomMember().lock()) { |
| 434 | rb.Push<u8>(0); | 434 | if (room_member->IsConnected()) { |
| 435 | ip_config_info.ip_address_setting.current_address = room_member->GetFakeIpAddress(); | ||
| 436 | } | ||
| 435 | } | 437 | } |
| 436 | 438 | ||
| 437 | void GetInternetConnectionStatus(Kernel::HLERequestContext& ctx) { | 439 | IPC::ResponseBuilder rb{ctx, 2 + (sizeof(IpConfigInfo) + 3) / sizeof(u32)}; |
| 438 | LOG_WARNING(Service_NIFM, "(STUBBED) called"); | 440 | rb.Push(ResultSuccess); |
| 441 | rb.PushRaw<IpConfigInfo>(ip_config_info); | ||
| 442 | } | ||
| 439 | 443 | ||
| 440 | struct Output { | 444 | void IGeneralService::IsWirelessCommunicationEnabled(Kernel::HLERequestContext& ctx) { |
| 441 | InternetConnectionType type{InternetConnectionType::WiFi}; | 445 | LOG_WARNING(Service_NIFM, "(STUBBED) called"); |
| 442 | u8 wifi_strength{3}; | ||
| 443 | InternetConnectionStatus state{InternetConnectionStatus::Connected}; | ||
| 444 | }; | ||
| 445 | static_assert(sizeof(Output) == 0x3, "Output has incorrect size."); | ||
| 446 | 446 | ||
| 447 | constexpr Output out{}; | 447 | IPC::ResponseBuilder rb{ctx, 3}; |
| 448 | rb.Push(ResultSuccess); | ||
| 449 | rb.Push<u8>(1); | ||
| 450 | } | ||
| 448 | 451 | ||
| 449 | IPC::ResponseBuilder rb{ctx, 3}; | 452 | void IGeneralService::GetInternetConnectionStatus(Kernel::HLERequestContext& ctx) { |
| 450 | rb.Push(ResultSuccess); | 453 | LOG_WARNING(Service_NIFM, "(STUBBED) called"); |
| 451 | rb.PushRaw(out); | ||
| 452 | } | ||
| 453 | 454 | ||
| 454 | void IsEthernetCommunicationEnabled(Kernel::HLERequestContext& ctx) { | 455 | struct Output { |
| 455 | LOG_WARNING(Service_NIFM, "(STUBBED) called"); | 456 | InternetConnectionType type{InternetConnectionType::WiFi}; |
| 457 | u8 wifi_strength{3}; | ||
| 458 | InternetConnectionStatus state{InternetConnectionStatus::Connected}; | ||
| 459 | }; | ||
| 460 | static_assert(sizeof(Output) == 0x3, "Output has incorrect size."); | ||
| 456 | 461 | ||
| 457 | IPC::ResponseBuilder rb{ctx, 3}; | 462 | constexpr Output out{}; |
| 458 | rb.Push(ResultSuccess); | 463 | |
| 459 | if (Network::GetHostIPv4Address().has_value()) { | 464 | IPC::ResponseBuilder rb{ctx, 3}; |
| 460 | rb.Push<u8>(1); | 465 | rb.Push(ResultSuccess); |
| 461 | } else { | 466 | rb.PushRaw(out); |
| 462 | rb.Push<u8>(0); | 467 | } |
| 463 | } | 468 | |
| 469 | void IGeneralService::IsEthernetCommunicationEnabled(Kernel::HLERequestContext& ctx) { | ||
| 470 | LOG_WARNING(Service_NIFM, "(STUBBED) called"); | ||
| 471 | |||
| 472 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 473 | rb.Push(ResultSuccess); | ||
| 474 | if (Network::GetHostIPv4Address().has_value()) { | ||
| 475 | rb.Push<u8>(1); | ||
| 476 | } else { | ||
| 477 | rb.Push<u8>(0); | ||
| 464 | } | 478 | } |
| 479 | } | ||
| 465 | 480 | ||
| 466 | void IsAnyInternetRequestAccepted(Kernel::HLERequestContext& ctx) { | 481 | void IGeneralService::IsAnyInternetRequestAccepted(Kernel::HLERequestContext& ctx) { |
| 467 | LOG_WARNING(Service_NIFM, "(STUBBED) called"); | 482 | LOG_ERROR(Service_NIFM, "(STUBBED) called"); |
| 468 | 483 | ||
| 469 | IPC::ResponseBuilder rb{ctx, 3}; | 484 | IPC::ResponseBuilder rb{ctx, 3}; |
| 470 | rb.Push(ResultSuccess); | 485 | rb.Push(ResultSuccess); |
| 471 | if (Network::GetHostIPv4Address().has_value()) { | 486 | if (Network::GetHostIPv4Address().has_value()) { |
| 472 | rb.Push<u8>(1); | 487 | rb.Push<u8>(1); |
| 473 | } else { | 488 | } else { |
| 474 | rb.Push<u8>(0); | 489 | rb.Push<u8>(0); |
| 475 | } | ||
| 476 | } | 490 | } |
| 477 | }; | 491 | } |
| 478 | 492 | ||
| 479 | IGeneralService::IGeneralService(Core::System& system_) | 493 | IGeneralService::IGeneralService(Core::System& system_) |
| 480 | : ServiceFramework{system_, "IGeneralService"} { | 494 | : ServiceFramework{system_, "IGeneralService"}, network{system_.GetRoomNetwork()} { |
| 481 | // clang-format off | 495 | // clang-format off |
| 482 | static const FunctionInfo functions[] = { | 496 | static const FunctionInfo functions[] = { |
| 483 | {1, &IGeneralService::GetClientId, "GetClientId"}, | 497 | {1, &IGeneralService::GetClientId, "GetClientId"}, |
| @@ -528,6 +542,8 @@ IGeneralService::IGeneralService(Core::System& system_) | |||
| 528 | RegisterHandlers(functions); | 542 | RegisterHandlers(functions); |
| 529 | } | 543 | } |
| 530 | 544 | ||
| 545 | IGeneralService::~IGeneralService() = default; | ||
| 546 | |||
| 531 | class NetworkInterface final : public ServiceFramework<NetworkInterface> { | 547 | class NetworkInterface final : public ServiceFramework<NetworkInterface> { |
| 532 | public: | 548 | public: |
| 533 | explicit NetworkInterface(const char* name, Core::System& system_) | 549 | explicit NetworkInterface(const char* name, Core::System& system_) |
diff --git a/src/core/hle/service/nifm/nifm.h b/src/core/hle/service/nifm/nifm.h index 5f62d0014..48161be28 100644 --- a/src/core/hle/service/nifm/nifm.h +++ b/src/core/hle/service/nifm/nifm.h | |||
| @@ -3,6 +3,11 @@ | |||
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include "core/hle/service/service.h" | ||
| 7 | #include "network/network.h" | ||
| 8 | #include "network/room.h" | ||
| 9 | #include "network/room_member.h" | ||
| 10 | |||
| 6 | namespace Core { | 11 | namespace Core { |
| 7 | class System; | 12 | class System; |
| 8 | } | 13 | } |
| @@ -16,4 +21,26 @@ namespace Service::NIFM { | |||
| 16 | /// Registers all NIFM services with the specified service manager. | 21 | /// Registers all NIFM services with the specified service manager. |
| 17 | void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); | 22 | void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); |
| 18 | 23 | ||
| 24 | class IGeneralService final : public ServiceFramework<IGeneralService> { | ||
| 25 | public: | ||
| 26 | explicit IGeneralService(Core::System& system_); | ||
| 27 | ~IGeneralService() override; | ||
| 28 | |||
| 29 | private: | ||
| 30 | void GetClientId(Kernel::HLERequestContext& ctx); | ||
| 31 | void CreateScanRequest(Kernel::HLERequestContext& ctx); | ||
| 32 | void CreateRequest(Kernel::HLERequestContext& ctx); | ||
| 33 | void GetCurrentNetworkProfile(Kernel::HLERequestContext& ctx); | ||
| 34 | void RemoveNetworkProfile(Kernel::HLERequestContext& ctx); | ||
| 35 | void GetCurrentIpAddress(Kernel::HLERequestContext& ctx); | ||
| 36 | void CreateTemporaryNetworkProfile(Kernel::HLERequestContext& ctx); | ||
| 37 | void GetCurrentIpConfigInfo(Kernel::HLERequestContext& ctx); | ||
| 38 | void IsWirelessCommunicationEnabled(Kernel::HLERequestContext& ctx); | ||
| 39 | void GetInternetConnectionStatus(Kernel::HLERequestContext& ctx); | ||
| 40 | void IsEthernetCommunicationEnabled(Kernel::HLERequestContext& ctx); | ||
| 41 | void IsAnyInternetRequestAccepted(Kernel::HLERequestContext& ctx); | ||
| 42 | |||
| 43 | Network::RoomNetwork& network; | ||
| 44 | }; | ||
| 45 | |||
| 19 | } // namespace Service::NIFM | 46 | } // namespace Service::NIFM |
diff --git a/src/core/hle/service/ns/pl_u.cpp b/src/core/hle/service/ns/iplatform_service_manager.cpp index cc11f3e08..fd047ff26 100644 --- a/src/core/hle/service/ns/pl_u.cpp +++ b/src/core/hle/service/ns/iplatform_service_manager.cpp | |||
| @@ -20,7 +20,7 @@ | |||
| 20 | #include "core/hle/kernel/kernel.h" | 20 | #include "core/hle/kernel/kernel.h" |
| 21 | #include "core/hle/kernel/physical_memory.h" | 21 | #include "core/hle/kernel/physical_memory.h" |
| 22 | #include "core/hle/service/filesystem/filesystem.h" | 22 | #include "core/hle/service/filesystem/filesystem.h" |
| 23 | #include "core/hle/service/ns/pl_u.h" | 23 | #include "core/hle/service/ns/iplatform_service_manager.h" |
| 24 | 24 | ||
| 25 | namespace Service::NS { | 25 | namespace Service::NS { |
| 26 | 26 | ||
| @@ -99,7 +99,7 @@ static u32 GetU32Swapped(const u8* data) { | |||
| 99 | return Common::swap32(value); | 99 | return Common::swap32(value); |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | struct PL_U::Impl { | 102 | struct IPlatformServiceManager::Impl { |
| 103 | const FontRegion& GetSharedFontRegion(std::size_t index) const { | 103 | const FontRegion& GetSharedFontRegion(std::size_t index) const { |
| 104 | if (index >= shared_font_regions.size() || shared_font_regions.empty()) { | 104 | if (index >= shared_font_regions.size() || shared_font_regions.empty()) { |
| 105 | // No font fallback | 105 | // No font fallback |
| @@ -134,16 +134,16 @@ struct PL_U::Impl { | |||
| 134 | std::vector<FontRegion> shared_font_regions; | 134 | std::vector<FontRegion> shared_font_regions; |
| 135 | }; | 135 | }; |
| 136 | 136 | ||
| 137 | PL_U::PL_U(Core::System& system_) | 137 | IPlatformServiceManager::IPlatformServiceManager(Core::System& system_, const char* service_name_) |
| 138 | : ServiceFramework{system_, "pl:u"}, impl{std::make_unique<Impl>()} { | 138 | : ServiceFramework{system_, service_name_}, impl{std::make_unique<Impl>()} { |
| 139 | // clang-format off | 139 | // clang-format off |
| 140 | static const FunctionInfo functions[] = { | 140 | static const FunctionInfo functions[] = { |
| 141 | {0, &PL_U::RequestLoad, "RequestLoad"}, | 141 | {0, &IPlatformServiceManager::RequestLoad, "RequestLoad"}, |
| 142 | {1, &PL_U::GetLoadState, "GetLoadState"}, | 142 | {1, &IPlatformServiceManager::GetLoadState, "GetLoadState"}, |
| 143 | {2, &PL_U::GetSize, "GetSize"}, | 143 | {2, &IPlatformServiceManager::GetSize, "GetSize"}, |
| 144 | {3, &PL_U::GetSharedMemoryAddressOffset, "GetSharedMemoryAddressOffset"}, | 144 | {3, &IPlatformServiceManager::GetSharedMemoryAddressOffset, "GetSharedMemoryAddressOffset"}, |
| 145 | {4, &PL_U::GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"}, | 145 | {4, &IPlatformServiceManager::GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"}, |
| 146 | {5, &PL_U::GetSharedFontInOrderOfPriority, "GetSharedFontInOrderOfPriority"}, | 146 | {5, &IPlatformServiceManager::GetSharedFontInOrderOfPriority, "GetSharedFontInOrderOfPriority"}, |
| 147 | {6, nullptr, "GetSharedFontInOrderOfPriorityForSystem"}, | 147 | {6, nullptr, "GetSharedFontInOrderOfPriorityForSystem"}, |
| 148 | {100, nullptr, "RequestApplicationFunctionAuthorization"}, | 148 | {100, nullptr, "RequestApplicationFunctionAuthorization"}, |
| 149 | {101, nullptr, "RequestApplicationFunctionAuthorizationByProcessId"}, | 149 | {101, nullptr, "RequestApplicationFunctionAuthorizationByProcessId"}, |
| @@ -206,9 +206,9 @@ PL_U::PL_U(Core::System& system_) | |||
| 206 | } | 206 | } |
| 207 | } | 207 | } |
| 208 | 208 | ||
| 209 | PL_U::~PL_U() = default; | 209 | IPlatformServiceManager::~IPlatformServiceManager() = default; |
| 210 | 210 | ||
| 211 | void PL_U::RequestLoad(Kernel::HLERequestContext& ctx) { | 211 | void IPlatformServiceManager::RequestLoad(Kernel::HLERequestContext& ctx) { |
| 212 | IPC::RequestParser rp{ctx}; | 212 | IPC::RequestParser rp{ctx}; |
| 213 | const u32 shared_font_type{rp.Pop<u32>()}; | 213 | const u32 shared_font_type{rp.Pop<u32>()}; |
| 214 | // Games don't call this so all fonts should be loaded | 214 | // Games don't call this so all fonts should be loaded |
| @@ -218,7 +218,7 @@ void PL_U::RequestLoad(Kernel::HLERequestContext& ctx) { | |||
| 218 | rb.Push(ResultSuccess); | 218 | rb.Push(ResultSuccess); |
| 219 | } | 219 | } |
| 220 | 220 | ||
| 221 | void PL_U::GetLoadState(Kernel::HLERequestContext& ctx) { | 221 | void IPlatformServiceManager::GetLoadState(Kernel::HLERequestContext& ctx) { |
| 222 | IPC::RequestParser rp{ctx}; | 222 | IPC::RequestParser rp{ctx}; |
| 223 | const u32 font_id{rp.Pop<u32>()}; | 223 | const u32 font_id{rp.Pop<u32>()}; |
| 224 | LOG_DEBUG(Service_NS, "called, font_id={}", font_id); | 224 | LOG_DEBUG(Service_NS, "called, font_id={}", font_id); |
| @@ -228,7 +228,7 @@ void PL_U::GetLoadState(Kernel::HLERequestContext& ctx) { | |||
| 228 | rb.Push<u32>(static_cast<u32>(LoadState::Done)); | 228 | rb.Push<u32>(static_cast<u32>(LoadState::Done)); |
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | void PL_U::GetSize(Kernel::HLERequestContext& ctx) { | 231 | void IPlatformServiceManager::GetSize(Kernel::HLERequestContext& ctx) { |
| 232 | IPC::RequestParser rp{ctx}; | 232 | IPC::RequestParser rp{ctx}; |
| 233 | const u32 font_id{rp.Pop<u32>()}; | 233 | const u32 font_id{rp.Pop<u32>()}; |
| 234 | LOG_DEBUG(Service_NS, "called, font_id={}", font_id); | 234 | LOG_DEBUG(Service_NS, "called, font_id={}", font_id); |
| @@ -238,7 +238,7 @@ void PL_U::GetSize(Kernel::HLERequestContext& ctx) { | |||
| 238 | rb.Push<u32>(impl->GetSharedFontRegion(font_id).size); | 238 | rb.Push<u32>(impl->GetSharedFontRegion(font_id).size); |
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | void PL_U::GetSharedMemoryAddressOffset(Kernel::HLERequestContext& ctx) { | 241 | void IPlatformServiceManager::GetSharedMemoryAddressOffset(Kernel::HLERequestContext& ctx) { |
| 242 | IPC::RequestParser rp{ctx}; | 242 | IPC::RequestParser rp{ctx}; |
| 243 | const u32 font_id{rp.Pop<u32>()}; | 243 | const u32 font_id{rp.Pop<u32>()}; |
| 244 | LOG_DEBUG(Service_NS, "called, font_id={}", font_id); | 244 | LOG_DEBUG(Service_NS, "called, font_id={}", font_id); |
| @@ -248,7 +248,7 @@ void PL_U::GetSharedMemoryAddressOffset(Kernel::HLERequestContext& ctx) { | |||
| 248 | rb.Push<u32>(impl->GetSharedFontRegion(font_id).offset); | 248 | rb.Push<u32>(impl->GetSharedFontRegion(font_id).offset); |
| 249 | } | 249 | } |
| 250 | 250 | ||
| 251 | void PL_U::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) { | 251 | void IPlatformServiceManager::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) { |
| 252 | // Map backing memory for the font data | 252 | // Map backing memory for the font data |
| 253 | LOG_DEBUG(Service_NS, "called"); | 253 | LOG_DEBUG(Service_NS, "called"); |
| 254 | 254 | ||
| @@ -261,7 +261,7 @@ void PL_U::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) { | |||
| 261 | rb.PushCopyObjects(&kernel.GetFontSharedMem()); | 261 | rb.PushCopyObjects(&kernel.GetFontSharedMem()); |
| 262 | } | 262 | } |
| 263 | 263 | ||
| 264 | void PL_U::GetSharedFontInOrderOfPriority(Kernel::HLERequestContext& ctx) { | 264 | void IPlatformServiceManager::GetSharedFontInOrderOfPriority(Kernel::HLERequestContext& ctx) { |
| 265 | IPC::RequestParser rp{ctx}; | 265 | IPC::RequestParser rp{ctx}; |
| 266 | const u64 language_code{rp.Pop<u64>()}; // TODO(ogniK): Find out what this is used for | 266 | const u64 language_code{rp.Pop<u64>()}; // TODO(ogniK): Find out what this is used for |
| 267 | LOG_DEBUG(Service_NS, "called, language_code={:X}", language_code); | 267 | LOG_DEBUG(Service_NS, "called, language_code={:X}", language_code); |
diff --git a/src/core/hle/service/ns/pl_u.h b/src/core/hle/service/ns/iplatform_service_manager.h index 07d0ac934..ed6eda89f 100644 --- a/src/core/hle/service/ns/pl_u.h +++ b/src/core/hle/service/ns/iplatform_service_manager.h | |||
| @@ -36,10 +36,10 @@ constexpr std::array<std::pair<FontArchives, const char*>, 7> SHARED_FONTS{ | |||
| 36 | void DecryptSharedFontToTTF(const std::vector<u32>& input, std::vector<u8>& output); | 36 | void DecryptSharedFontToTTF(const std::vector<u32>& input, std::vector<u8>& output); |
| 37 | void EncryptSharedFont(const std::vector<u32>& input, std::vector<u8>& output, std::size_t& offset); | 37 | void EncryptSharedFont(const std::vector<u32>& input, std::vector<u8>& output, std::size_t& offset); |
| 38 | 38 | ||
| 39 | class PL_U final : public ServiceFramework<PL_U> { | 39 | class IPlatformServiceManager final : public ServiceFramework<IPlatformServiceManager> { |
| 40 | public: | 40 | public: |
| 41 | explicit PL_U(Core::System& system_); | 41 | explicit IPlatformServiceManager(Core::System& system_, const char* service_name_); |
| 42 | ~PL_U() override; | 42 | ~IPlatformServiceManager() override; |
| 43 | 43 | ||
| 44 | private: | 44 | private: |
| 45 | void RequestLoad(Kernel::HLERequestContext& ctx); | 45 | void RequestLoad(Kernel::HLERequestContext& ctx); |
diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp index aafc8fe03..f7318c3cb 100644 --- a/src/core/hle/service/ns/ns.cpp +++ b/src/core/hle/service/ns/ns.cpp | |||
| @@ -9,10 +9,10 @@ | |||
| 9 | #include "core/file_sys/vfs.h" | 9 | #include "core/file_sys/vfs.h" |
| 10 | #include "core/hle/ipc_helpers.h" | 10 | #include "core/hle/ipc_helpers.h" |
| 11 | #include "core/hle/service/ns/errors.h" | 11 | #include "core/hle/service/ns/errors.h" |
| 12 | #include "core/hle/service/ns/iplatform_service_manager.h" | ||
| 12 | #include "core/hle/service/ns/language.h" | 13 | #include "core/hle/service/ns/language.h" |
| 13 | #include "core/hle/service/ns/ns.h" | 14 | #include "core/hle/service/ns/ns.h" |
| 14 | #include "core/hle/service/ns/pdm_qry.h" | 15 | #include "core/hle/service/ns/pdm_qry.h" |
| 15 | #include "core/hle/service/ns/pl_u.h" | ||
| 16 | #include "core/hle/service/set/set.h" | 16 | #include "core/hle/service/set/set.h" |
| 17 | 17 | ||
| 18 | namespace Service::NS { | 18 | namespace Service::NS { |
| @@ -764,7 +764,8 @@ void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system | |||
| 764 | 764 | ||
| 765 | std::make_shared<PDM_QRY>(system)->InstallAsService(service_manager); | 765 | std::make_shared<PDM_QRY>(system)->InstallAsService(service_manager); |
| 766 | 766 | ||
| 767 | std::make_shared<PL_U>(system)->InstallAsService(service_manager); | 767 | std::make_shared<IPlatformServiceManager>(system, "pl:s")->InstallAsService(service_manager); |
| 768 | std::make_shared<IPlatformServiceManager>(system, "pl:u")->InstallAsService(service_manager); | ||
| 768 | } | 769 | } |
| 769 | 770 | ||
| 770 | } // namespace Service::NS | 771 | } // namespace Service::NS |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp index 2a5128c60..a7385fce8 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "audio_core/audio_core.h" | ||
| 4 | #include "common/assert.h" | 5 | #include "common/assert.h" |
| 5 | #include "common/logging/log.h" | 6 | #include "common/logging/log.h" |
| 6 | #include "core/core.h" | 7 | #include "core/core.h" |
| @@ -65,7 +66,10 @@ NvResult nvhost_nvdec::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& | |||
| 65 | return NvResult::NotImplemented; | 66 | return NvResult::NotImplemented; |
| 66 | } | 67 | } |
| 67 | 68 | ||
| 68 | void nvhost_nvdec::OnOpen(DeviceFD fd) {} | 69 | void nvhost_nvdec::OnOpen(DeviceFD fd) { |
| 70 | LOG_INFO(Service_NVDRV, "NVDEC video stream started"); | ||
| 71 | system.AudioCore().SetNVDECActive(true); | ||
| 72 | } | ||
| 69 | 73 | ||
| 70 | void nvhost_nvdec::OnClose(DeviceFD fd) { | 74 | void nvhost_nvdec::OnClose(DeviceFD fd) { |
| 71 | LOG_INFO(Service_NVDRV, "NVDEC video stream ended"); | 75 | LOG_INFO(Service_NVDRV, "NVDEC video stream ended"); |
| @@ -73,6 +77,7 @@ void nvhost_nvdec::OnClose(DeviceFD fd) { | |||
| 73 | if (iter != fd_to_id.end()) { | 77 | if (iter != fd_to_id.end()) { |
| 74 | system.GPU().ClearCdmaInstance(iter->second); | 78 | system.GPU().ClearCdmaInstance(iter->second); |
| 75 | } | 79 | } |
| 80 | system.AudioCore().SetNVDECActive(false); | ||
| 76 | } | 81 | } |
| 77 | 82 | ||
| 78 | } // namespace Service::Nvidia::Devices | 83 | } // namespace Service::Nvidia::Devices |
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp index 728bfa00b..d8518149d 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.cpp +++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp | |||
| @@ -198,7 +198,7 @@ NvResult nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) | |||
| 198 | IocParamParams params; | 198 | IocParamParams params; |
| 199 | std::memcpy(¶ms, input.data(), sizeof(params)); | 199 | std::memcpy(¶ms, input.data(), sizeof(params)); |
| 200 | 200 | ||
| 201 | LOG_WARNING(Service_NVDRV, "(STUBBED) called type={}", params.param); | 201 | LOG_DEBUG(Service_NVDRV, "(STUBBED) called type={}", params.param); |
| 202 | 202 | ||
| 203 | auto object = GetObject(params.handle); | 203 | auto object = GetObject(params.handle); |
| 204 | if (!object) { | 204 | if (!object) { |
| @@ -243,7 +243,7 @@ NvResult nvmap::IocFree(const std::vector<u8>& input, std::vector<u8>& output) { | |||
| 243 | IocFreeParams params; | 243 | IocFreeParams params; |
| 244 | std::memcpy(¶ms, input.data(), sizeof(params)); | 244 | std::memcpy(¶ms, input.data(), sizeof(params)); |
| 245 | 245 | ||
| 246 | LOG_WARNING(Service_NVDRV, "(STUBBED) called"); | 246 | LOG_DEBUG(Service_NVDRV, "(STUBBED) called"); |
| 247 | 247 | ||
| 248 | auto itr = handles.find(params.handle); | 248 | auto itr = handles.find(params.handle); |
| 249 | if (itr == handles.end()) { | 249 | if (itr == handles.end()) { |
diff --git a/src/core/hle/service/pcv/pcv.cpp b/src/core/hle/service/pcv/pcv.cpp index 0989474be..f7a497a14 100644 --- a/src/core/hle/service/pcv/pcv.cpp +++ b/src/core/hle/service/pcv/pcv.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #include <memory> | 4 | #include <memory> |
| 5 | 5 | ||
| 6 | #include "core/hle/ipc_helpers.h" | ||
| 6 | #include "core/hle/service/pcv/pcv.h" | 7 | #include "core/hle/service/pcv/pcv.h" |
| 7 | #include "core/hle/service/service.h" | 8 | #include "core/hle/service/service.h" |
| 8 | #include "core/hle/service/sm/sm.h" | 9 | #include "core/hle/service/sm/sm.h" |
| @@ -77,10 +78,102 @@ public: | |||
| 77 | } | 78 | } |
| 78 | }; | 79 | }; |
| 79 | 80 | ||
| 81 | class IClkrstSession final : public ServiceFramework<IClkrstSession> { | ||
| 82 | public: | ||
| 83 | explicit IClkrstSession(Core::System& system_, DeviceCode deivce_code_) | ||
| 84 | : ServiceFramework{system_, "IClkrstSession"}, deivce_code(deivce_code_) { | ||
| 85 | // clang-format off | ||
| 86 | static const FunctionInfo functions[] = { | ||
| 87 | {0, nullptr, "SetClockEnabled"}, | ||
| 88 | {1, nullptr, "SetClockDisabled"}, | ||
| 89 | {2, nullptr, "SetResetAsserted"}, | ||
| 90 | {3, nullptr, "SetResetDeasserted"}, | ||
| 91 | {4, nullptr, "SetPowerEnabled"}, | ||
| 92 | {5, nullptr, "SetPowerDisabled"}, | ||
| 93 | {6, nullptr, "GetState"}, | ||
| 94 | {7, &IClkrstSession::SetClockRate, "SetClockRate"}, | ||
| 95 | {8, &IClkrstSession::GetClockRate, "GetClockRate"}, | ||
| 96 | {9, nullptr, "SetMinVClockRate"}, | ||
| 97 | {10, nullptr, "GetPossibleClockRates"}, | ||
| 98 | {11, nullptr, "GetDvfsTable"}, | ||
| 99 | }; | ||
| 100 | // clang-format on | ||
| 101 | RegisterHandlers(functions); | ||
| 102 | } | ||
| 103 | |||
| 104 | private: | ||
| 105 | void SetClockRate(Kernel::HLERequestContext& ctx) { | ||
| 106 | IPC::RequestParser rp{ctx}; | ||
| 107 | clock_rate = rp.Pop<u32>(); | ||
| 108 | LOG_DEBUG(Service_PCV, "(STUBBED) called, clock_rate={}", clock_rate); | ||
| 109 | |||
| 110 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 111 | rb.Push(ResultSuccess); | ||
| 112 | } | ||
| 113 | |||
| 114 | void GetClockRate(Kernel::HLERequestContext& ctx) { | ||
| 115 | LOG_DEBUG(Service_PCV, "(STUBBED) called"); | ||
| 116 | |||
| 117 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 118 | rb.Push(ResultSuccess); | ||
| 119 | rb.Push<u32>(clock_rate); | ||
| 120 | } | ||
| 121 | |||
| 122 | DeviceCode deivce_code; | ||
| 123 | u32 clock_rate{}; | ||
| 124 | }; | ||
| 125 | |||
| 126 | class CLKRST final : public ServiceFramework<CLKRST> { | ||
| 127 | public: | ||
| 128 | explicit CLKRST(Core::System& system_, const char* name) : ServiceFramework{system_, name} { | ||
| 129 | // clang-format off | ||
| 130 | static const FunctionInfo functions[] = { | ||
| 131 | {0, &CLKRST::OpenSession, "OpenSession"}, | ||
| 132 | {1, nullptr, "GetTemperatureThresholds"}, | ||
| 133 | {2, nullptr, "SetTemperature"}, | ||
| 134 | {3, nullptr, "GetModuleStateTable"}, | ||
| 135 | {4, nullptr, "GetModuleStateTableEvent"}, | ||
| 136 | {5, nullptr, "GetModuleStateTableMaxCount"}, | ||
| 137 | }; | ||
| 138 | // clang-format on | ||
| 139 | |||
| 140 | RegisterHandlers(functions); | ||
| 141 | } | ||
| 142 | |||
| 143 | private: | ||
| 144 | void OpenSession(Kernel::HLERequestContext& ctx) { | ||
| 145 | IPC::RequestParser rp{ctx}; | ||
| 146 | const auto device_code = static_cast<DeviceCode>(rp.Pop<u32>()); | ||
| 147 | const auto unkonwn_input = rp.Pop<u32>(); | ||
| 148 | |||
| 149 | LOG_DEBUG(Service_PCV, "called, device_code={}, input={}", device_code, unkonwn_input); | ||
| 150 | |||
| 151 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 152 | rb.Push(ResultSuccess); | ||
| 153 | rb.PushIpcInterface<IClkrstSession>(system, device_code); | ||
| 154 | } | ||
| 155 | }; | ||
| 156 | |||
| 157 | class CLKRST_A final : public ServiceFramework<CLKRST_A> { | ||
| 158 | public: | ||
| 159 | explicit CLKRST_A(Core::System& system_) : ServiceFramework{system_, "clkrst:a"} { | ||
| 160 | // clang-format off | ||
| 161 | static const FunctionInfo functions[] = { | ||
| 162 | {0, nullptr, "ReleaseControl"}, | ||
| 163 | }; | ||
| 164 | // clang-format on | ||
| 165 | |||
| 166 | RegisterHandlers(functions); | ||
| 167 | } | ||
| 168 | }; | ||
| 169 | |||
| 80 | void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { | 170 | void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { |
| 81 | std::make_shared<PCV>(system)->InstallAsService(sm); | 171 | std::make_shared<PCV>(system)->InstallAsService(sm); |
| 82 | std::make_shared<PCV_ARB>(system)->InstallAsService(sm); | 172 | std::make_shared<PCV_ARB>(system)->InstallAsService(sm); |
| 83 | std::make_shared<PCV_IMM>(system)->InstallAsService(sm); | 173 | std::make_shared<PCV_IMM>(system)->InstallAsService(sm); |
| 174 | std::make_shared<CLKRST>(system, "clkrst")->InstallAsService(sm); | ||
| 175 | std::make_shared<CLKRST>(system, "clkrst:i")->InstallAsService(sm); | ||
| 176 | std::make_shared<CLKRST_A>(system)->InstallAsService(sm); | ||
| 84 | } | 177 | } |
| 85 | 178 | ||
| 86 | } // namespace Service::PCV | 179 | } // namespace Service::PCV |
diff --git a/src/core/hle/service/pcv/pcv.h b/src/core/hle/service/pcv/pcv.h index a42e6f8f6..6b26b6fa7 100644 --- a/src/core/hle/service/pcv/pcv.h +++ b/src/core/hle/service/pcv/pcv.h | |||
| @@ -13,6 +13,97 @@ class ServiceManager; | |||
| 13 | 13 | ||
| 14 | namespace Service::PCV { | 14 | namespace Service::PCV { |
| 15 | 15 | ||
| 16 | enum class DeviceCode : u32 { | ||
| 17 | Cpu = 0x40000001, | ||
| 18 | Gpu = 0x40000002, | ||
| 19 | I2s1 = 0x40000003, | ||
| 20 | I2s2 = 0x40000004, | ||
| 21 | I2s3 = 0x40000005, | ||
| 22 | Pwm = 0x40000006, | ||
| 23 | I2c1 = 0x02000001, | ||
| 24 | I2c2 = 0x02000002, | ||
| 25 | I2c3 = 0x02000003, | ||
| 26 | I2c4 = 0x02000004, | ||
| 27 | I2c5 = 0x02000005, | ||
| 28 | I2c6 = 0x02000006, | ||
| 29 | Spi1 = 0x07000000, | ||
| 30 | Spi2 = 0x07000001, | ||
| 31 | Spi3 = 0x07000002, | ||
| 32 | Spi4 = 0x07000003, | ||
| 33 | Disp1 = 0x40000011, | ||
| 34 | Disp2 = 0x40000012, | ||
| 35 | Isp = 0x40000013, | ||
| 36 | Vi = 0x40000014, | ||
| 37 | Sdmmc1 = 0x40000015, | ||
| 38 | Sdmmc2 = 0x40000016, | ||
| 39 | Sdmmc3 = 0x40000017, | ||
| 40 | Sdmmc4 = 0x40000018, | ||
| 41 | Owr = 0x40000019, | ||
| 42 | Csite = 0x4000001A, | ||
| 43 | Tsec = 0x4000001B, | ||
| 44 | Mselect = 0x4000001C, | ||
| 45 | Hda2codec2x = 0x4000001D, | ||
| 46 | Actmon = 0x4000001E, | ||
| 47 | I2cSlow = 0x4000001F, | ||
| 48 | Sor1 = 0x40000020, | ||
| 49 | Sata = 0x40000021, | ||
| 50 | Hda = 0x40000022, | ||
| 51 | XusbCoreHostSrc = 0x40000023, | ||
| 52 | XusbFalconSrc = 0x40000024, | ||
| 53 | XusbFsSrc = 0x40000025, | ||
| 54 | XusbCoreDevSrc = 0x40000026, | ||
| 55 | XusbSsSrc = 0x40000027, | ||
| 56 | UartA = 0x03000001, | ||
| 57 | UartB = 0x35000405, | ||
| 58 | UartC = 0x3500040F, | ||
| 59 | UartD = 0x37000001, | ||
| 60 | Host1x = 0x4000002C, | ||
| 61 | Entropy = 0x4000002D, | ||
| 62 | SocTherm = 0x4000002E, | ||
| 63 | Vic = 0x4000002F, | ||
| 64 | Nvenc = 0x40000030, | ||
| 65 | Nvjpg = 0x40000031, | ||
| 66 | Nvdec = 0x40000032, | ||
| 67 | Qspi = 0x40000033, | ||
| 68 | ViI2c = 0x40000034, | ||
| 69 | Tsecb = 0x40000035, | ||
| 70 | Ape = 0x40000036, | ||
| 71 | AudioDsp = 0x40000037, | ||
| 72 | AudioUart = 0x40000038, | ||
| 73 | Emc = 0x40000039, | ||
| 74 | Plle = 0x4000003A, | ||
| 75 | PlleHwSeq = 0x4000003B, | ||
| 76 | Dsi = 0x4000003C, | ||
| 77 | Maud = 0x4000003D, | ||
| 78 | Dpaux1 = 0x4000003E, | ||
| 79 | MipiCal = 0x4000003F, | ||
| 80 | UartFstMipiCal = 0x40000040, | ||
| 81 | Osc = 0x40000041, | ||
| 82 | SysBus = 0x40000042, | ||
| 83 | SorSafe = 0x40000043, | ||
| 84 | XusbSs = 0x40000044, | ||
| 85 | XusbHost = 0x40000045, | ||
| 86 | XusbDevice = 0x40000046, | ||
| 87 | Extperiph1 = 0x40000047, | ||
| 88 | Ahub = 0x40000048, | ||
| 89 | Hda2hdmicodec = 0x40000049, | ||
| 90 | Gpuaux = 0x4000004A, | ||
| 91 | UsbD = 0x4000004B, | ||
| 92 | Usb2 = 0x4000004C, | ||
| 93 | Pcie = 0x4000004D, | ||
| 94 | Afi = 0x4000004E, | ||
| 95 | PciExClk = 0x4000004F, | ||
| 96 | PExUsbPhy = 0x40000050, | ||
| 97 | XUsbPadCtl = 0x40000051, | ||
| 98 | Apbdma = 0x40000052, | ||
| 99 | Usb2TrkClk = 0x40000053, | ||
| 100 | XUsbIoPll = 0x40000054, | ||
| 101 | XUsbIoPllHwSeq = 0x40000055, | ||
| 102 | Cec = 0x40000056, | ||
| 103 | Extperiph2 = 0x40000057, | ||
| 104 | OscClk = 0x40000080 | ||
| 105 | }; | ||
| 106 | |||
| 16 | void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); | 107 | void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); |
| 17 | 108 | ||
| 18 | } // namespace Service::PCV | 109 | } // namespace Service::PCV |
diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp index c7194731e..cc679cc81 100644 --- a/src/core/hle/service/sockets/bsd.cpp +++ b/src/core/hle/service/sockets/bsd.cpp | |||
| @@ -9,12 +9,16 @@ | |||
| 9 | #include <fmt/format.h> | 9 | #include <fmt/format.h> |
| 10 | 10 | ||
| 11 | #include "common/microprofile.h" | 11 | #include "common/microprofile.h" |
| 12 | #include "common/socket_types.h" | ||
| 13 | #include "core/core.h" | ||
| 12 | #include "core/hle/ipc_helpers.h" | 14 | #include "core/hle/ipc_helpers.h" |
| 13 | #include "core/hle/kernel/k_thread.h" | 15 | #include "core/hle/kernel/k_thread.h" |
| 14 | #include "core/hle/service/sockets/bsd.h" | 16 | #include "core/hle/service/sockets/bsd.h" |
| 15 | #include "core/hle/service/sockets/sockets_translate.h" | 17 | #include "core/hle/service/sockets/sockets_translate.h" |
| 16 | #include "core/internal_network/network.h" | 18 | #include "core/internal_network/network.h" |
| 19 | #include "core/internal_network/socket_proxy.h" | ||
| 17 | #include "core/internal_network/sockets.h" | 20 | #include "core/internal_network/sockets.h" |
| 21 | #include "network/network.h" | ||
| 18 | 22 | ||
| 19 | namespace Service::Sockets { | 23 | namespace Service::Sockets { |
| 20 | 24 | ||
| @@ -472,7 +476,13 @@ std::pair<s32, Errno> BSD::SocketImpl(Domain domain, Type type, Protocol protoco | |||
| 472 | 476 | ||
| 473 | LOG_INFO(Service, "New socket fd={}", fd); | 477 | LOG_INFO(Service, "New socket fd={}", fd); |
| 474 | 478 | ||
| 475 | descriptor.socket = std::make_unique<Network::Socket>(); | 479 | auto room_member = room_network.GetRoomMember().lock(); |
| 480 | if (room_member && room_member->IsConnected()) { | ||
| 481 | descriptor.socket = std::make_unique<Network::ProxySocket>(room_network); | ||
| 482 | } else { | ||
| 483 | descriptor.socket = std::make_unique<Network::Socket>(); | ||
| 484 | } | ||
| 485 | |||
| 476 | descriptor.socket->Initialize(Translate(domain), Translate(type), Translate(type, protocol)); | 486 | descriptor.socket->Initialize(Translate(domain), Translate(type), Translate(type, protocol)); |
| 477 | descriptor.is_connection_based = IsConnectionBased(type); | 487 | descriptor.is_connection_based = IsConnectionBased(type); |
| 478 | 488 | ||
| @@ -648,7 +658,7 @@ std::pair<s32, Errno> BSD::FcntlImpl(s32 fd, FcntlCmd cmd, s32 arg) { | |||
| 648 | ASSERT(arg == 0); | 658 | ASSERT(arg == 0); |
| 649 | return {descriptor.flags, Errno::SUCCESS}; | 659 | return {descriptor.flags, Errno::SUCCESS}; |
| 650 | case FcntlCmd::SETFL: { | 660 | case FcntlCmd::SETFL: { |
| 651 | const bool enable = (arg & FLAG_O_NONBLOCK) != 0; | 661 | const bool enable = (arg & Network::FLAG_O_NONBLOCK) != 0; |
| 652 | const Errno bsd_errno = Translate(descriptor.socket->SetNonBlock(enable)); | 662 | const Errno bsd_errno = Translate(descriptor.socket->SetNonBlock(enable)); |
| 653 | if (bsd_errno != Errno::SUCCESS) { | 663 | if (bsd_errno != Errno::SUCCESS) { |
| 654 | return {-1, bsd_errno}; | 664 | return {-1, bsd_errno}; |
| @@ -669,7 +679,7 @@ Errno BSD::SetSockOptImpl(s32 fd, u32 level, OptName optname, size_t optlen, con | |||
| 669 | return Errno::BADF; | 679 | return Errno::BADF; |
| 670 | } | 680 | } |
| 671 | 681 | ||
| 672 | Network::Socket* const socket = file_descriptors[fd]->socket.get(); | 682 | Network::SocketBase* const socket = file_descriptors[fd]->socket.get(); |
| 673 | 683 | ||
| 674 | if (optname == OptName::LINGER) { | 684 | if (optname == OptName::LINGER) { |
| 675 | ASSERT(optlen == sizeof(Linger)); | 685 | ASSERT(optlen == sizeof(Linger)); |
| @@ -724,6 +734,8 @@ std::pair<s32, Errno> BSD::RecvImpl(s32 fd, u32 flags, std::vector<u8>& message) | |||
| 724 | FileDescriptor& descriptor = *file_descriptors[fd]; | 734 | FileDescriptor& descriptor = *file_descriptors[fd]; |
| 725 | 735 | ||
| 726 | // Apply flags | 736 | // Apply flags |
| 737 | using Network::FLAG_MSG_DONTWAIT; | ||
| 738 | using Network::FLAG_O_NONBLOCK; | ||
| 727 | if ((flags & FLAG_MSG_DONTWAIT) != 0) { | 739 | if ((flags & FLAG_MSG_DONTWAIT) != 0) { |
| 728 | flags &= ~FLAG_MSG_DONTWAIT; | 740 | flags &= ~FLAG_MSG_DONTWAIT; |
| 729 | if ((descriptor.flags & FLAG_O_NONBLOCK) == 0) { | 741 | if ((descriptor.flags & FLAG_O_NONBLOCK) == 0) { |
| @@ -759,6 +771,8 @@ std::pair<s32, Errno> BSD::RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& mess | |||
| 759 | } | 771 | } |
| 760 | 772 | ||
| 761 | // Apply flags | 773 | // Apply flags |
| 774 | using Network::FLAG_MSG_DONTWAIT; | ||
| 775 | using Network::FLAG_O_NONBLOCK; | ||
| 762 | if ((flags & FLAG_MSG_DONTWAIT) != 0) { | 776 | if ((flags & FLAG_MSG_DONTWAIT) != 0) { |
| 763 | flags &= ~FLAG_MSG_DONTWAIT; | 777 | flags &= ~FLAG_MSG_DONTWAIT; |
| 764 | if ((descriptor.flags & FLAG_O_NONBLOCK) == 0) { | 778 | if ((descriptor.flags & FLAG_O_NONBLOCK) == 0) { |
| @@ -857,8 +871,19 @@ void BSD::BuildErrnoResponse(Kernel::HLERequestContext& ctx, Errno bsd_errno) co | |||
| 857 | rb.PushEnum(bsd_errno); | 871 | rb.PushEnum(bsd_errno); |
| 858 | } | 872 | } |
| 859 | 873 | ||
| 874 | void BSD::OnProxyPacketReceived(const Network::ProxyPacket& packet) { | ||
| 875 | for (auto& optional_descriptor : file_descriptors) { | ||
| 876 | if (!optional_descriptor.has_value()) { | ||
| 877 | continue; | ||
| 878 | } | ||
| 879 | FileDescriptor& descriptor = *optional_descriptor; | ||
| 880 | descriptor.socket.get()->HandleProxyPacket(packet); | ||
| 881 | } | ||
| 882 | } | ||
| 883 | |||
| 860 | BSD::BSD(Core::System& system_, const char* name) | 884 | BSD::BSD(Core::System& system_, const char* name) |
| 861 | : ServiceFramework{system_, name, ServiceThreadType::CreateNew} { | 885 | : ServiceFramework{system_, name, ServiceThreadType::CreateNew}, room_network{ |
| 886 | system_.GetRoomNetwork()} { | ||
| 862 | // clang-format off | 887 | // clang-format off |
| 863 | static const FunctionInfo functions[] = { | 888 | static const FunctionInfo functions[] = { |
| 864 | {0, &BSD::RegisterClient, "RegisterClient"}, | 889 | {0, &BSD::RegisterClient, "RegisterClient"}, |
| @@ -899,9 +924,20 @@ BSD::BSD(Core::System& system_, const char* name) | |||
| 899 | // clang-format on | 924 | // clang-format on |
| 900 | 925 | ||
| 901 | RegisterHandlers(functions); | 926 | RegisterHandlers(functions); |
| 927 | |||
| 928 | if (auto room_member = room_network.GetRoomMember().lock()) { | ||
| 929 | proxy_packet_received = room_member->BindOnProxyPacketReceived( | ||
| 930 | [this](const Network::ProxyPacket& packet) { OnProxyPacketReceived(packet); }); | ||
| 931 | } else { | ||
| 932 | LOG_ERROR(Service, "Network isn't initalized"); | ||
| 933 | } | ||
| 902 | } | 934 | } |
| 903 | 935 | ||
| 904 | BSD::~BSD() = default; | 936 | BSD::~BSD() { |
| 937 | if (auto room_member = room_network.GetRoomMember().lock()) { | ||
| 938 | room_member->Unbind(proxy_packet_received); | ||
| 939 | } | ||
| 940 | } | ||
| 905 | 941 | ||
| 906 | BSDCFG::BSDCFG(Core::System& system_) : ServiceFramework{system_, "bsdcfg"} { | 942 | BSDCFG::BSDCFG(Core::System& system_) : ServiceFramework{system_, "bsdcfg"} { |
| 907 | // clang-format off | 943 | // clang-format off |
diff --git a/src/core/hle/service/sockets/bsd.h b/src/core/hle/service/sockets/bsd.h index 9ea36428d..81e855e0f 100644 --- a/src/core/hle/service/sockets/bsd.h +++ b/src/core/hle/service/sockets/bsd.h | |||
| @@ -7,14 +7,17 @@ | |||
| 7 | #include <vector> | 7 | #include <vector> |
| 8 | 8 | ||
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "common/socket_types.h" | ||
| 10 | #include "core/hle/service/service.h" | 11 | #include "core/hle/service/service.h" |
| 11 | #include "core/hle/service/sockets/sockets.h" | 12 | #include "core/hle/service/sockets/sockets.h" |
| 13 | #include "network/network.h" | ||
| 12 | 14 | ||
| 13 | namespace Core { | 15 | namespace Core { |
| 14 | class System; | 16 | class System; |
| 15 | } | 17 | } |
| 16 | 18 | ||
| 17 | namespace Network { | 19 | namespace Network { |
| 20 | class SocketBase; | ||
| 18 | class Socket; | 21 | class Socket; |
| 19 | } // namespace Network | 22 | } // namespace Network |
| 20 | 23 | ||
| @@ -30,7 +33,7 @@ private: | |||
| 30 | static constexpr size_t MAX_FD = 128; | 33 | static constexpr size_t MAX_FD = 128; |
| 31 | 34 | ||
| 32 | struct FileDescriptor { | 35 | struct FileDescriptor { |
| 33 | std::unique_ptr<Network::Socket> socket; | 36 | std::unique_ptr<Network::SocketBase> socket; |
| 34 | s32 flags = 0; | 37 | s32 flags = 0; |
| 35 | bool is_connection_based = false; | 38 | bool is_connection_based = false; |
| 36 | }; | 39 | }; |
| @@ -165,6 +168,14 @@ private: | |||
| 165 | void BuildErrnoResponse(Kernel::HLERequestContext& ctx, Errno bsd_errno) const noexcept; | 168 | void BuildErrnoResponse(Kernel::HLERequestContext& ctx, Errno bsd_errno) const noexcept; |
| 166 | 169 | ||
| 167 | std::array<std::optional<FileDescriptor>, MAX_FD> file_descriptors; | 170 | std::array<std::optional<FileDescriptor>, MAX_FD> file_descriptors; |
| 171 | |||
| 172 | Network::RoomNetwork& room_network; | ||
| 173 | |||
| 174 | /// Callback to parse and handle a received wifi packet. | ||
| 175 | void OnProxyPacketReceived(const Network::ProxyPacket& packet); | ||
| 176 | |||
| 177 | // Callback identifier for the OnProxyPacketReceived event. | ||
| 178 | Network::RoomMember::CallbackHandle<Network::ProxyPacket> proxy_packet_received; | ||
| 168 | }; | 179 | }; |
| 169 | 180 | ||
| 170 | class BSDCFG final : public ServiceFramework<BSDCFG> { | 181 | class BSDCFG final : public ServiceFramework<BSDCFG> { |
diff --git a/src/core/hle/service/sockets/sockets.h b/src/core/hle/service/sockets/sockets.h index b735b00fc..31b7dad33 100644 --- a/src/core/hle/service/sockets/sockets.h +++ b/src/core/hle/service/sockets/sockets.h | |||
| @@ -22,7 +22,9 @@ enum class Errno : u32 { | |||
| 22 | AGAIN = 11, | 22 | AGAIN = 11, |
| 23 | INVAL = 22, | 23 | INVAL = 22, |
| 24 | MFILE = 24, | 24 | MFILE = 24, |
| 25 | MSGSIZE = 90, | ||
| 25 | NOTCONN = 107, | 26 | NOTCONN = 107, |
| 27 | TIMEDOUT = 110, | ||
| 26 | }; | 28 | }; |
| 27 | 29 | ||
| 28 | enum class Domain : u32 { | 30 | enum class Domain : u32 { |
| @@ -96,10 +98,6 @@ struct Linger { | |||
| 96 | u32 linger; | 98 | u32 linger; |
| 97 | }; | 99 | }; |
| 98 | 100 | ||
| 99 | constexpr u32 FLAG_MSG_DONTWAIT = 0x80; | ||
| 100 | |||
| 101 | constexpr u32 FLAG_O_NONBLOCK = 0x800; | ||
| 102 | |||
| 103 | /// Registers all Sockets services with the specified service manager. | 101 | /// Registers all Sockets services with the specified service manager. |
| 104 | void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); | 102 | void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); |
| 105 | 103 | ||
diff --git a/src/core/hle/service/sockets/sockets_translate.cpp b/src/core/hle/service/sockets/sockets_translate.cpp index 2db10ec81..023aa0486 100644 --- a/src/core/hle/service/sockets/sockets_translate.cpp +++ b/src/core/hle/service/sockets/sockets_translate.cpp | |||
| @@ -25,6 +25,8 @@ Errno Translate(Network::Errno value) { | |||
| 25 | return Errno::MFILE; | 25 | return Errno::MFILE; |
| 26 | case Network::Errno::NOTCONN: | 26 | case Network::Errno::NOTCONN: |
| 27 | return Errno::NOTCONN; | 27 | return Errno::NOTCONN; |
| 28 | case Network::Errno::TIMEDOUT: | ||
| 29 | return Errno::TIMEDOUT; | ||
| 28 | default: | 30 | default: |
| 29 | UNIMPLEMENTED_MSG("Unimplemented errno={}", value); | 31 | UNIMPLEMENTED_MSG("Unimplemented errno={}", value); |
| 30 | return Errno::SUCCESS; | 32 | return Errno::SUCCESS; |
diff --git a/src/core/internal_network/network.cpp b/src/core/internal_network/network.cpp index 36c43cc8f..cdf38a2a4 100644 --- a/src/core/internal_network/network.cpp +++ b/src/core/internal_network/network.cpp | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include "core/internal_network/network.h" | 32 | #include "core/internal_network/network.h" |
| 33 | #include "core/internal_network/network_interface.h" | 33 | #include "core/internal_network/network_interface.h" |
| 34 | #include "core/internal_network/sockets.h" | 34 | #include "core/internal_network/sockets.h" |
| 35 | #include "network/network.h" | ||
| 35 | 36 | ||
| 36 | namespace Network { | 37 | namespace Network { |
| 37 | 38 | ||
| @@ -114,7 +115,10 @@ Errno TranslateNativeError(int e) { | |||
| 114 | return Errno::NETDOWN; | 115 | return Errno::NETDOWN; |
| 115 | case WSAENETUNREACH: | 116 | case WSAENETUNREACH: |
| 116 | return Errno::NETUNREACH; | 117 | return Errno::NETUNREACH; |
| 118 | case WSAEMSGSIZE: | ||
| 119 | return Errno::MSGSIZE; | ||
| 117 | default: | 120 | default: |
| 121 | UNIMPLEMENTED_MSG("Unimplemented errno={}", e); | ||
| 118 | return Errno::OTHER; | 122 | return Errno::OTHER; |
| 119 | } | 123 | } |
| 120 | } | 124 | } |
| @@ -125,7 +129,6 @@ using SOCKET = int; | |||
| 125 | using WSAPOLLFD = pollfd; | 129 | using WSAPOLLFD = pollfd; |
| 126 | using ULONG = u64; | 130 | using ULONG = u64; |
| 127 | 131 | ||
| 128 | constexpr SOCKET INVALID_SOCKET = -1; | ||
| 129 | constexpr SOCKET SOCKET_ERROR = -1; | 132 | constexpr SOCKET SOCKET_ERROR = -1; |
| 130 | 133 | ||
| 131 | constexpr int SD_RECEIVE = SHUT_RD; | 134 | constexpr int SD_RECEIVE = SHUT_RD; |
| @@ -206,7 +209,10 @@ Errno TranslateNativeError(int e) { | |||
| 206 | return Errno::NETDOWN; | 209 | return Errno::NETDOWN; |
| 207 | case ENETUNREACH: | 210 | case ENETUNREACH: |
| 208 | return Errno::NETUNREACH; | 211 | return Errno::NETUNREACH; |
| 212 | case EMSGSIZE: | ||
| 213 | return Errno::MSGSIZE; | ||
| 209 | default: | 214 | default: |
| 215 | UNIMPLEMENTED_MSG("Unimplemented errno={}", e); | ||
| 210 | return Errno::OTHER; | 216 | return Errno::OTHER; |
| 211 | } | 217 | } |
| 212 | } | 218 | } |
| @@ -329,16 +335,6 @@ PollEvents TranslatePollRevents(short revents) { | |||
| 329 | return result; | 335 | return result; |
| 330 | } | 336 | } |
| 331 | 337 | ||
| 332 | template <typename T> | ||
| 333 | Errno SetSockOpt(SOCKET fd, int option, T value) { | ||
| 334 | const int result = | ||
| 335 | setsockopt(fd, SOL_SOCKET, option, reinterpret_cast<const char*>(&value), sizeof(value)); | ||
| 336 | if (result != SOCKET_ERROR) { | ||
| 337 | return Errno::SUCCESS; | ||
| 338 | } | ||
| 339 | return GetAndLogLastError(); | ||
| 340 | } | ||
| 341 | |||
| 342 | } // Anonymous namespace | 338 | } // Anonymous namespace |
| 343 | 339 | ||
| 344 | NetworkInstance::NetworkInstance() { | 340 | NetworkInstance::NetworkInstance() { |
| @@ -350,26 +346,16 @@ NetworkInstance::~NetworkInstance() { | |||
| 350 | } | 346 | } |
| 351 | 347 | ||
| 352 | std::optional<IPv4Address> GetHostIPv4Address() { | 348 | std::optional<IPv4Address> GetHostIPv4Address() { |
| 353 | const std::string& selected_network_interface = Settings::values.network_interface.GetValue(); | 349 | const auto network_interface = Network::GetSelectedNetworkInterface(); |
| 354 | const auto network_interfaces = Network::GetAvailableNetworkInterfaces(); | 350 | if (!network_interface.has_value()) { |
| 355 | if (network_interfaces.size() == 0) { | 351 | LOG_ERROR(Network, "GetSelectedNetworkInterface returned no interface"); |
| 356 | LOG_ERROR(Network, "GetAvailableNetworkInterfaces returned no interfaces"); | ||
| 357 | return {}; | 352 | return {}; |
| 358 | } | 353 | } |
| 359 | 354 | ||
| 360 | const auto res = | 355 | std::array<char, 16> ip_addr = {}; |
| 361 | std::ranges::find_if(network_interfaces, [&selected_network_interface](const auto& iface) { | 356 | ASSERT(inet_ntop(AF_INET, &network_interface->ip_address, ip_addr.data(), sizeof(ip_addr)) != |
| 362 | return iface.name == selected_network_interface; | 357 | nullptr); |
| 363 | }); | 358 | return TranslateIPv4(network_interface->ip_address); |
| 364 | |||
| 365 | if (res != network_interfaces.end()) { | ||
| 366 | char ip_addr[16] = {}; | ||
| 367 | ASSERT(inet_ntop(AF_INET, &res->ip_address, ip_addr, sizeof(ip_addr)) != nullptr); | ||
| 368 | return TranslateIPv4(res->ip_address); | ||
| 369 | } else { | ||
| 370 | LOG_ERROR(Network, "Couldn't find selected interface \"{}\"", selected_network_interface); | ||
| 371 | return {}; | ||
| 372 | } | ||
| 373 | } | 359 | } |
| 374 | 360 | ||
| 375 | std::pair<s32, Errno> Poll(std::vector<PollFD>& pollfds, s32 timeout) { | 361 | std::pair<s32, Errno> Poll(std::vector<PollFD>& pollfds, s32 timeout) { |
| @@ -412,7 +398,19 @@ Socket::~Socket() { | |||
| 412 | fd = INVALID_SOCKET; | 398 | fd = INVALID_SOCKET; |
| 413 | } | 399 | } |
| 414 | 400 | ||
| 415 | Socket::Socket(Socket&& rhs) noexcept : fd{std::exchange(rhs.fd, INVALID_SOCKET)} {} | 401 | Socket::Socket(Socket&& rhs) noexcept { |
| 402 | fd = std::exchange(rhs.fd, INVALID_SOCKET); | ||
| 403 | } | ||
| 404 | |||
| 405 | template <typename T> | ||
| 406 | Errno Socket::SetSockOpt(SOCKET fd_, int option, T value) { | ||
| 407 | const int result = | ||
| 408 | setsockopt(fd_, SOL_SOCKET, option, reinterpret_cast<const char*>(&value), sizeof(value)); | ||
| 409 | if (result != SOCKET_ERROR) { | ||
| 410 | return Errno::SUCCESS; | ||
| 411 | } | ||
| 412 | return GetAndLogLastError(); | ||
| 413 | } | ||
| 416 | 414 | ||
| 417 | Errno Socket::Initialize(Domain domain, Type type, Protocol protocol) { | 415 | Errno Socket::Initialize(Domain domain, Type type, Protocol protocol) { |
| 418 | fd = socket(TranslateDomain(domain), TranslateType(type), TranslateProtocol(protocol)); | 416 | fd = socket(TranslateDomain(domain), TranslateType(type), TranslateProtocol(protocol)); |
| @@ -423,7 +421,7 @@ Errno Socket::Initialize(Domain domain, Type type, Protocol protocol) { | |||
| 423 | return GetAndLogLastError(); | 421 | return GetAndLogLastError(); |
| 424 | } | 422 | } |
| 425 | 423 | ||
| 426 | std::pair<Socket::AcceptResult, Errno> Socket::Accept() { | 424 | std::pair<SocketBase::AcceptResult, Errno> Socket::Accept() { |
| 427 | sockaddr addr; | 425 | sockaddr addr; |
| 428 | socklen_t addrlen = sizeof(addr); | 426 | socklen_t addrlen = sizeof(addr); |
| 429 | const SOCKET new_socket = accept(fd, &addr, &addrlen); | 427 | const SOCKET new_socket = accept(fd, &addr, &addrlen); |
| @@ -634,4 +632,8 @@ bool Socket::IsOpened() const { | |||
| 634 | return fd != INVALID_SOCKET; | 632 | return fd != INVALID_SOCKET; |
| 635 | } | 633 | } |
| 636 | 634 | ||
| 635 | void Socket::HandleProxyPacket(const ProxyPacket& packet) { | ||
| 636 | LOG_WARNING(Network, "ProxyPacket received, but not in Proxy mode!"); | ||
| 637 | } | ||
| 638 | |||
| 637 | } // namespace Network | 639 | } // namespace Network |
diff --git a/src/core/internal_network/network.h b/src/core/internal_network/network.h index 10e5ef10d..36994c22e 100644 --- a/src/core/internal_network/network.h +++ b/src/core/internal_network/network.h | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | 8 | ||
| 9 | #include "common/common_funcs.h" | 9 | #include "common/common_funcs.h" |
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "common/socket_types.h" | ||
| 11 | 12 | ||
| 12 | #ifdef _WIN32 | 13 | #ifdef _WIN32 |
| 13 | #include <winsock2.h> | 14 | #include <winsock2.h> |
| @@ -17,6 +18,7 @@ | |||
| 17 | 18 | ||
| 18 | namespace Network { | 19 | namespace Network { |
| 19 | 20 | ||
| 21 | class SocketBase; | ||
| 20 | class Socket; | 22 | class Socket; |
| 21 | 23 | ||
| 22 | /// Error code for network functions | 24 | /// Error code for network functions |
| @@ -31,46 +33,11 @@ enum class Errno { | |||
| 31 | HOSTUNREACH, | 33 | HOSTUNREACH, |
| 32 | NETDOWN, | 34 | NETDOWN, |
| 33 | NETUNREACH, | 35 | NETUNREACH, |
| 36 | TIMEDOUT, | ||
| 37 | MSGSIZE, | ||
| 34 | OTHER, | 38 | OTHER, |
| 35 | }; | 39 | }; |
| 36 | 40 | ||
| 37 | /// Address families | ||
| 38 | enum class Domain { | ||
| 39 | INET, ///< Address family for IPv4 | ||
| 40 | }; | ||
| 41 | |||
| 42 | /// Socket types | ||
| 43 | enum class Type { | ||
| 44 | STREAM, | ||
| 45 | DGRAM, | ||
| 46 | RAW, | ||
| 47 | SEQPACKET, | ||
| 48 | }; | ||
| 49 | |||
| 50 | /// Protocol values for sockets | ||
| 51 | enum class Protocol { | ||
| 52 | ICMP, | ||
| 53 | TCP, | ||
| 54 | UDP, | ||
| 55 | }; | ||
| 56 | |||
| 57 | /// Shutdown mode | ||
| 58 | enum class ShutdownHow { | ||
| 59 | RD, | ||
| 60 | WR, | ||
| 61 | RDWR, | ||
| 62 | }; | ||
| 63 | |||
| 64 | /// Array of IPv4 address | ||
| 65 | using IPv4Address = std::array<u8, 4>; | ||
| 66 | |||
| 67 | /// Cross-platform sockaddr structure | ||
| 68 | struct SockAddrIn { | ||
| 69 | Domain family; | ||
| 70 | IPv4Address ip; | ||
| 71 | u16 portno; | ||
| 72 | }; | ||
| 73 | |||
| 74 | /// Cross-platform poll fd structure | 41 | /// Cross-platform poll fd structure |
| 75 | 42 | ||
| 76 | enum class PollEvents : u16 { | 43 | enum class PollEvents : u16 { |
| @@ -86,7 +53,7 @@ enum class PollEvents : u16 { | |||
| 86 | DECLARE_ENUM_FLAG_OPERATORS(PollEvents); | 53 | DECLARE_ENUM_FLAG_OPERATORS(PollEvents); |
| 87 | 54 | ||
| 88 | struct PollFD { | 55 | struct PollFD { |
| 89 | Socket* socket; | 56 | SocketBase* socket; |
| 90 | PollEvents events; | 57 | PollEvents events; |
| 91 | PollEvents revents; | 58 | PollEvents revents; |
| 92 | }; | 59 | }; |
diff --git a/src/core/internal_network/socket_proxy.cpp b/src/core/internal_network/socket_proxy.cpp new file mode 100644 index 000000000..0c746bd82 --- /dev/null +++ b/src/core/internal_network/socket_proxy.cpp | |||
| @@ -0,0 +1,290 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include <chrono> | ||
| 5 | #include <thread> | ||
| 6 | |||
| 7 | #include "common/assert.h" | ||
| 8 | #include "common/logging/log.h" | ||
| 9 | #include "core/internal_network/network.h" | ||
| 10 | #include "core/internal_network/network_interface.h" | ||
| 11 | #include "core/internal_network/socket_proxy.h" | ||
| 12 | |||
| 13 | namespace Network { | ||
| 14 | |||
| 15 | ProxySocket::ProxySocket(RoomNetwork& room_network_) noexcept : room_network{room_network_} {} | ||
| 16 | |||
| 17 | ProxySocket::~ProxySocket() { | ||
| 18 | if (fd == INVALID_SOCKET) { | ||
| 19 | return; | ||
| 20 | } | ||
| 21 | fd = INVALID_SOCKET; | ||
| 22 | } | ||
| 23 | |||
| 24 | void ProxySocket::HandleProxyPacket(const ProxyPacket& packet) { | ||
| 25 | if (protocol != packet.protocol || local_endpoint.portno != packet.remote_endpoint.portno || | ||
| 26 | closed) { | ||
| 27 | return; | ||
| 28 | } | ||
| 29 | |||
| 30 | if (!broadcast && packet.broadcast) { | ||
| 31 | LOG_INFO(Network, "Received broadcast packet, but not configured for broadcast mode"); | ||
| 32 | return; | ||
| 33 | } | ||
| 34 | |||
| 35 | std::lock_guard guard(packets_mutex); | ||
| 36 | received_packets.push(packet); | ||
| 37 | } | ||
| 38 | |||
| 39 | template <typename T> | ||
| 40 | Errno ProxySocket::SetSockOpt(SOCKET fd_, int option, T value) { | ||
| 41 | LOG_DEBUG(Network, "(STUBBED) called"); | ||
| 42 | return Errno::SUCCESS; | ||
| 43 | } | ||
| 44 | |||
| 45 | Errno ProxySocket::Initialize(Domain domain, Type type, Protocol socket_protocol) { | ||
| 46 | protocol = socket_protocol; | ||
| 47 | SetSockOpt(fd, SO_TYPE, type); | ||
| 48 | |||
| 49 | return Errno::SUCCESS; | ||
| 50 | } | ||
| 51 | |||
| 52 | std::pair<ProxySocket::AcceptResult, Errno> ProxySocket::Accept() { | ||
| 53 | LOG_WARNING(Network, "(STUBBED) called"); | ||
| 54 | return {AcceptResult{}, Errno::SUCCESS}; | ||
| 55 | } | ||
| 56 | |||
| 57 | Errno ProxySocket::Connect(SockAddrIn addr_in) { | ||
| 58 | LOG_WARNING(Network, "(STUBBED) called"); | ||
| 59 | return Errno::SUCCESS; | ||
| 60 | } | ||
| 61 | |||
| 62 | std::pair<SockAddrIn, Errno> ProxySocket::GetPeerName() { | ||
| 63 | LOG_WARNING(Network, "(STUBBED) called"); | ||
| 64 | return {SockAddrIn{}, Errno::SUCCESS}; | ||
| 65 | } | ||
| 66 | |||
| 67 | std::pair<SockAddrIn, Errno> ProxySocket::GetSockName() { | ||
| 68 | LOG_WARNING(Network, "(STUBBED) called"); | ||
| 69 | return {SockAddrIn{}, Errno::SUCCESS}; | ||
| 70 | } | ||
| 71 | |||
| 72 | Errno ProxySocket::Bind(SockAddrIn addr) { | ||
| 73 | if (is_bound) { | ||
| 74 | LOG_WARNING(Network, "Rebinding Socket is unimplemented!"); | ||
| 75 | return Errno::SUCCESS; | ||
| 76 | } | ||
| 77 | local_endpoint = addr; | ||
| 78 | is_bound = true; | ||
| 79 | |||
| 80 | return Errno::SUCCESS; | ||
| 81 | } | ||
| 82 | |||
| 83 | Errno ProxySocket::Listen(s32 backlog) { | ||
| 84 | LOG_WARNING(Network, "(STUBBED) called"); | ||
| 85 | return Errno::SUCCESS; | ||
| 86 | } | ||
| 87 | |||
| 88 | Errno ProxySocket::Shutdown(ShutdownHow how) { | ||
| 89 | LOG_WARNING(Network, "(STUBBED) called"); | ||
| 90 | return Errno::SUCCESS; | ||
| 91 | } | ||
| 92 | |||
| 93 | std::pair<s32, Errno> ProxySocket::Recv(int flags, std::vector<u8>& message) { | ||
| 94 | LOG_WARNING(Network, "(STUBBED) called"); | ||
| 95 | ASSERT(flags == 0); | ||
| 96 | ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max())); | ||
| 97 | |||
| 98 | return {static_cast<s32>(0), Errno::SUCCESS}; | ||
| 99 | } | ||
| 100 | |||
| 101 | std::pair<s32, Errno> ProxySocket::RecvFrom(int flags, std::vector<u8>& message, SockAddrIn* addr) { | ||
| 102 | ASSERT(flags == 0); | ||
| 103 | ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max())); | ||
| 104 | |||
| 105 | // TODO (flTobi): Verify the timeout behavior and break when connection is lost | ||
| 106 | const auto timestamp = std::chrono::steady_clock::now(); | ||
| 107 | // When receive_timeout is set to zero, the socket is supposed to wait indefinitely until a | ||
| 108 | // packet arrives. In order to prevent lost packets from hanging the emulation thread, we set | ||
| 109 | // the timeout to 5s instead | ||
| 110 | const auto timeout = receive_timeout == 0 ? 5000 : receive_timeout; | ||
| 111 | while (true) { | ||
| 112 | { | ||
| 113 | std::lock_guard guard(packets_mutex); | ||
| 114 | if (received_packets.size() > 0) { | ||
| 115 | return ReceivePacket(flags, message, addr, message.size()); | ||
| 116 | } | ||
| 117 | } | ||
| 118 | |||
| 119 | if (!blocking) { | ||
| 120 | return {-1, Errno::AGAIN}; | ||
| 121 | } | ||
| 122 | |||
| 123 | std::this_thread::yield(); | ||
| 124 | |||
| 125 | const auto time_diff = std::chrono::steady_clock::now() - timestamp; | ||
| 126 | const auto time_diff_ms = | ||
| 127 | std::chrono::duration_cast<std::chrono::milliseconds>(time_diff).count(); | ||
| 128 | |||
| 129 | if (time_diff_ms > timeout) { | ||
| 130 | return {-1, Errno::TIMEDOUT}; | ||
| 131 | } | ||
| 132 | } | ||
| 133 | } | ||
| 134 | |||
| 135 | std::pair<s32, Errno> ProxySocket::ReceivePacket(int flags, std::vector<u8>& message, | ||
| 136 | SockAddrIn* addr, std::size_t max_length) { | ||
| 137 | ProxyPacket& packet = received_packets.front(); | ||
| 138 | if (addr) { | ||
| 139 | addr->family = Domain::INET; | ||
| 140 | addr->ip = packet.local_endpoint.ip; // The senders ip address | ||
| 141 | addr->portno = packet.local_endpoint.portno; // The senders port number | ||
| 142 | } | ||
| 143 | |||
| 144 | bool peek = (flags & FLAG_MSG_PEEK) != 0; | ||
| 145 | std::size_t read_bytes; | ||
| 146 | if (packet.data.size() > max_length) { | ||
| 147 | read_bytes = max_length; | ||
| 148 | message.clear(); | ||
| 149 | std::copy(packet.data.begin(), packet.data.begin() + read_bytes, | ||
| 150 | std::back_inserter(message)); | ||
| 151 | message.resize(max_length); | ||
| 152 | |||
| 153 | if (protocol == Protocol::UDP) { | ||
| 154 | if (!peek) { | ||
| 155 | received_packets.pop(); | ||
| 156 | } | ||
| 157 | return {-1, Errno::MSGSIZE}; | ||
| 158 | } else if (protocol == Protocol::TCP) { | ||
| 159 | std::vector<u8> numArray(packet.data.size() - max_length); | ||
| 160 | std::copy(packet.data.begin() + max_length, packet.data.end(), | ||
| 161 | std::back_inserter(numArray)); | ||
| 162 | packet.data = numArray; | ||
| 163 | } | ||
| 164 | } else { | ||
| 165 | read_bytes = packet.data.size(); | ||
| 166 | message.clear(); | ||
| 167 | std::copy(packet.data.begin(), packet.data.end(), std::back_inserter(message)); | ||
| 168 | message.resize(max_length); | ||
| 169 | if (!peek) { | ||
| 170 | received_packets.pop(); | ||
| 171 | } | ||
| 172 | } | ||
| 173 | |||
| 174 | return {static_cast<u32>(read_bytes), Errno::SUCCESS}; | ||
| 175 | } | ||
| 176 | |||
| 177 | std::pair<s32, Errno> ProxySocket::Send(const std::vector<u8>& message, int flags) { | ||
| 178 | LOG_WARNING(Network, "(STUBBED) called"); | ||
| 179 | ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max())); | ||
| 180 | ASSERT(flags == 0); | ||
| 181 | |||
| 182 | return {static_cast<s32>(0), Errno::SUCCESS}; | ||
| 183 | } | ||
| 184 | |||
| 185 | void ProxySocket::SendPacket(ProxyPacket& packet) { | ||
| 186 | if (auto room_member = room_network.GetRoomMember().lock()) { | ||
| 187 | if (room_member->IsConnected()) { | ||
| 188 | room_member->SendProxyPacket(packet); | ||
| 189 | } | ||
| 190 | } | ||
| 191 | } | ||
| 192 | |||
| 193 | std::pair<s32, Errno> ProxySocket::SendTo(u32 flags, const std::vector<u8>& message, | ||
| 194 | const SockAddrIn* addr) { | ||
| 195 | ASSERT(flags == 0); | ||
| 196 | |||
| 197 | if (!is_bound) { | ||
| 198 | LOG_ERROR(Network, "ProxySocket is not bound!"); | ||
| 199 | return {static_cast<s32>(message.size()), Errno::SUCCESS}; | ||
| 200 | } | ||
| 201 | |||
| 202 | if (auto room_member = room_network.GetRoomMember().lock()) { | ||
| 203 | if (!room_member->IsConnected()) { | ||
| 204 | return {static_cast<s32>(message.size()), Errno::SUCCESS}; | ||
| 205 | } | ||
| 206 | } | ||
| 207 | |||
| 208 | ProxyPacket packet; | ||
| 209 | packet.local_endpoint = local_endpoint; | ||
| 210 | packet.remote_endpoint = *addr; | ||
| 211 | packet.protocol = protocol; | ||
| 212 | packet.broadcast = broadcast && packet.remote_endpoint.ip[3] == 255; | ||
| 213 | |||
| 214 | auto& ip = local_endpoint.ip; | ||
| 215 | auto ipv4 = Network::GetHostIPv4Address(); | ||
| 216 | // If the ip is all zeroes (INADDR_ANY) or if it matches the hosts ip address, | ||
| 217 | // replace it with a "fake" routing address | ||
| 218 | if (std::all_of(ip.begin(), ip.end(), [](u8 i) { return i == 0; }) || (ipv4 && ipv4 == ip)) { | ||
| 219 | if (auto room_member = room_network.GetRoomMember().lock()) { | ||
| 220 | packet.local_endpoint.ip = room_member->GetFakeIpAddress(); | ||
| 221 | } | ||
| 222 | } | ||
| 223 | |||
| 224 | packet.data.clear(); | ||
| 225 | std::copy(message.begin(), message.end(), std::back_inserter(packet.data)); | ||
| 226 | |||
| 227 | SendPacket(packet); | ||
| 228 | |||
| 229 | return {static_cast<s32>(message.size()), Errno::SUCCESS}; | ||
| 230 | } | ||
| 231 | |||
| 232 | Errno ProxySocket::Close() { | ||
| 233 | fd = INVALID_SOCKET; | ||
| 234 | closed = true; | ||
| 235 | |||
| 236 | return Errno::SUCCESS; | ||
| 237 | } | ||
| 238 | |||
| 239 | Errno ProxySocket::SetLinger(bool enable, u32 linger) { | ||
| 240 | struct Linger { | ||
| 241 | u16 linger_enable; | ||
| 242 | u16 linger_time; | ||
| 243 | } values; | ||
| 244 | values.linger_enable = enable ? 1 : 0; | ||
| 245 | values.linger_time = static_cast<u16>(linger); | ||
| 246 | |||
| 247 | return SetSockOpt(fd, SO_LINGER, values); | ||
| 248 | } | ||
| 249 | |||
| 250 | Errno ProxySocket::SetReuseAddr(bool enable) { | ||
| 251 | return SetSockOpt<u32>(fd, SO_REUSEADDR, enable ? 1 : 0); | ||
| 252 | } | ||
| 253 | |||
| 254 | Errno ProxySocket::SetBroadcast(bool enable) { | ||
| 255 | broadcast = enable; | ||
| 256 | return SetSockOpt<u32>(fd, SO_BROADCAST, enable ? 1 : 0); | ||
| 257 | } | ||
| 258 | |||
| 259 | Errno ProxySocket::SetSndBuf(u32 value) { | ||
| 260 | return SetSockOpt(fd, SO_SNDBUF, value); | ||
| 261 | } | ||
| 262 | |||
| 263 | Errno ProxySocket::SetKeepAlive(bool enable) { | ||
| 264 | return Errno::SUCCESS; | ||
| 265 | } | ||
| 266 | |||
| 267 | Errno ProxySocket::SetRcvBuf(u32 value) { | ||
| 268 | return SetSockOpt(fd, SO_RCVBUF, value); | ||
| 269 | } | ||
| 270 | |||
| 271 | Errno ProxySocket::SetSndTimeo(u32 value) { | ||
| 272 | send_timeout = value; | ||
| 273 | return SetSockOpt(fd, SO_SNDTIMEO, static_cast<int>(value)); | ||
| 274 | } | ||
| 275 | |||
| 276 | Errno ProxySocket::SetRcvTimeo(u32 value) { | ||
| 277 | receive_timeout = value; | ||
| 278 | return SetSockOpt(fd, SO_RCVTIMEO, static_cast<int>(value)); | ||
| 279 | } | ||
| 280 | |||
| 281 | Errno ProxySocket::SetNonBlock(bool enable) { | ||
| 282 | blocking = !enable; | ||
| 283 | return Errno::SUCCESS; | ||
| 284 | } | ||
| 285 | |||
| 286 | bool ProxySocket::IsOpened() const { | ||
| 287 | return fd != INVALID_SOCKET; | ||
| 288 | } | ||
| 289 | |||
| 290 | } // namespace Network | ||
diff --git a/src/core/internal_network/socket_proxy.h b/src/core/internal_network/socket_proxy.h new file mode 100644 index 000000000..f12b5f567 --- /dev/null +++ b/src/core/internal_network/socket_proxy.h | |||
| @@ -0,0 +1,97 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <mutex> | ||
| 7 | #include <vector> | ||
| 8 | #include <queue> | ||
| 9 | |||
| 10 | #include "common/common_funcs.h" | ||
| 11 | #include "core/internal_network/sockets.h" | ||
| 12 | #include "network/network.h" | ||
| 13 | |||
| 14 | namespace Network { | ||
| 15 | |||
| 16 | class ProxySocket : public SocketBase { | ||
| 17 | public: | ||
| 18 | YUZU_NON_COPYABLE(ProxySocket); | ||
| 19 | YUZU_NON_MOVEABLE(ProxySocket); | ||
| 20 | |||
| 21 | explicit ProxySocket(RoomNetwork& room_network_) noexcept; | ||
| 22 | ~ProxySocket() override; | ||
| 23 | |||
| 24 | void HandleProxyPacket(const ProxyPacket& packet) override; | ||
| 25 | |||
| 26 | Errno Initialize(Domain domain, Type type, Protocol socket_protocol) override; | ||
| 27 | |||
| 28 | Errno Close() override; | ||
| 29 | |||
| 30 | std::pair<AcceptResult, Errno> Accept() override; | ||
| 31 | |||
| 32 | Errno Connect(SockAddrIn addr_in) override; | ||
| 33 | |||
| 34 | std::pair<SockAddrIn, Errno> GetPeerName() override; | ||
| 35 | |||
| 36 | std::pair<SockAddrIn, Errno> GetSockName() override; | ||
| 37 | |||
| 38 | Errno Bind(SockAddrIn addr) override; | ||
| 39 | |||
| 40 | Errno Listen(s32 backlog) override; | ||
| 41 | |||
| 42 | Errno Shutdown(ShutdownHow how) override; | ||
| 43 | |||
| 44 | std::pair<s32, Errno> Recv(int flags, std::vector<u8>& message) override; | ||
| 45 | |||
| 46 | std::pair<s32, Errno> RecvFrom(int flags, std::vector<u8>& message, SockAddrIn* addr) override; | ||
| 47 | |||
| 48 | std::pair<s32, Errno> ReceivePacket(int flags, std::vector<u8>& message, SockAddrIn* addr, | ||
| 49 | std::size_t max_length); | ||
| 50 | |||
| 51 | std::pair<s32, Errno> Send(const std::vector<u8>& message, int flags) override; | ||
| 52 | |||
| 53 | void SendPacket(ProxyPacket& packet); | ||
| 54 | |||
| 55 | std::pair<s32, Errno> SendTo(u32 flags, const std::vector<u8>& message, | ||
| 56 | const SockAddrIn* addr) override; | ||
| 57 | |||
| 58 | Errno SetLinger(bool enable, u32 linger) override; | ||
| 59 | |||
| 60 | Errno SetReuseAddr(bool enable) override; | ||
| 61 | |||
| 62 | Errno SetBroadcast(bool enable) override; | ||
| 63 | |||
| 64 | Errno SetKeepAlive(bool enable) override; | ||
| 65 | |||
| 66 | Errno SetSndBuf(u32 value) override; | ||
| 67 | |||
| 68 | Errno SetRcvBuf(u32 value) override; | ||
| 69 | |||
| 70 | Errno SetSndTimeo(u32 value) override; | ||
| 71 | |||
| 72 | Errno SetRcvTimeo(u32 value) override; | ||
| 73 | |||
| 74 | Errno SetNonBlock(bool enable) override; | ||
| 75 | |||
| 76 | template <typename T> | ||
| 77 | Errno SetSockOpt(SOCKET fd, int option, T value); | ||
| 78 | |||
| 79 | bool IsOpened() const override; | ||
| 80 | |||
| 81 | private: | ||
| 82 | bool broadcast = false; | ||
| 83 | bool closed = false; | ||
| 84 | u32 send_timeout = 0; | ||
| 85 | u32 receive_timeout = 0; | ||
| 86 | bool is_bound = false; | ||
| 87 | SockAddrIn local_endpoint{}; | ||
| 88 | bool blocking = true; | ||
| 89 | std::queue<ProxyPacket> received_packets; | ||
| 90 | Protocol protocol; | ||
| 91 | |||
| 92 | std::mutex packets_mutex; | ||
| 93 | |||
| 94 | RoomNetwork& room_network; | ||
| 95 | }; | ||
| 96 | |||
| 97 | } // namespace Network | ||
diff --git a/src/core/internal_network/sockets.h b/src/core/internal_network/sockets.h index 77e27e928..a70429b19 100644 --- a/src/core/internal_network/sockets.h +++ b/src/core/internal_network/sockets.h | |||
| @@ -14,20 +14,88 @@ | |||
| 14 | 14 | ||
| 15 | #include "common/common_types.h" | 15 | #include "common/common_types.h" |
| 16 | #include "core/internal_network/network.h" | 16 | #include "core/internal_network/network.h" |
| 17 | #include "network/network.h" | ||
| 17 | 18 | ||
| 18 | // TODO: C++20 Replace std::vector usages with std::span | 19 | // TODO: C++20 Replace std::vector usages with std::span |
| 19 | 20 | ||
| 20 | namespace Network { | 21 | namespace Network { |
| 21 | 22 | ||
| 22 | class Socket { | 23 | class SocketBase { |
| 23 | public: | 24 | public: |
| 25 | #ifdef YUZU_UNIX | ||
| 26 | using SOCKET = int; | ||
| 27 | static constexpr SOCKET INVALID_SOCKET = -1; | ||
| 28 | static constexpr SOCKET SOCKET_ERROR = -1; | ||
| 29 | #endif | ||
| 30 | |||
| 24 | struct AcceptResult { | 31 | struct AcceptResult { |
| 25 | std::unique_ptr<Socket> socket; | 32 | std::unique_ptr<SocketBase> socket; |
| 26 | SockAddrIn sockaddr_in; | 33 | SockAddrIn sockaddr_in; |
| 27 | }; | 34 | }; |
| 35 | virtual ~SocketBase() = default; | ||
| 36 | |||
| 37 | virtual SocketBase& operator=(const SocketBase&) = delete; | ||
| 38 | |||
| 39 | // Avoid closing sockets implicitly | ||
| 40 | virtual SocketBase& operator=(SocketBase&&) noexcept = delete; | ||
| 41 | |||
| 42 | virtual Errno Initialize(Domain domain, Type type, Protocol protocol) = 0; | ||
| 43 | |||
| 44 | virtual Errno Close() = 0; | ||
| 45 | |||
| 46 | virtual std::pair<AcceptResult, Errno> Accept() = 0; | ||
| 47 | |||
| 48 | virtual Errno Connect(SockAddrIn addr_in) = 0; | ||
| 49 | |||
| 50 | virtual std::pair<SockAddrIn, Errno> GetPeerName() = 0; | ||
| 51 | |||
| 52 | virtual std::pair<SockAddrIn, Errno> GetSockName() = 0; | ||
| 53 | |||
| 54 | virtual Errno Bind(SockAddrIn addr) = 0; | ||
| 55 | |||
| 56 | virtual Errno Listen(s32 backlog) = 0; | ||
| 57 | |||
| 58 | virtual Errno Shutdown(ShutdownHow how) = 0; | ||
| 59 | |||
| 60 | virtual std::pair<s32, Errno> Recv(int flags, std::vector<u8>& message) = 0; | ||
| 61 | |||
| 62 | virtual std::pair<s32, Errno> RecvFrom(int flags, std::vector<u8>& message, | ||
| 63 | SockAddrIn* addr) = 0; | ||
| 64 | |||
| 65 | virtual std::pair<s32, Errno> Send(const std::vector<u8>& message, int flags) = 0; | ||
| 66 | |||
| 67 | virtual std::pair<s32, Errno> SendTo(u32 flags, const std::vector<u8>& message, | ||
| 68 | const SockAddrIn* addr) = 0; | ||
| 69 | |||
| 70 | virtual Errno SetLinger(bool enable, u32 linger) = 0; | ||
| 28 | 71 | ||
| 29 | explicit Socket() = default; | 72 | virtual Errno SetReuseAddr(bool enable) = 0; |
| 30 | ~Socket(); | 73 | |
| 74 | virtual Errno SetKeepAlive(bool enable) = 0; | ||
| 75 | |||
| 76 | virtual Errno SetBroadcast(bool enable) = 0; | ||
| 77 | |||
| 78 | virtual Errno SetSndBuf(u32 value) = 0; | ||
| 79 | |||
| 80 | virtual Errno SetRcvBuf(u32 value) = 0; | ||
| 81 | |||
| 82 | virtual Errno SetSndTimeo(u32 value) = 0; | ||
| 83 | |||
| 84 | virtual Errno SetRcvTimeo(u32 value) = 0; | ||
| 85 | |||
| 86 | virtual Errno SetNonBlock(bool enable) = 0; | ||
| 87 | |||
| 88 | virtual bool IsOpened() const = 0; | ||
| 89 | |||
| 90 | virtual void HandleProxyPacket(const ProxyPacket& packet) = 0; | ||
| 91 | |||
| 92 | SOCKET fd = INVALID_SOCKET; | ||
| 93 | }; | ||
| 94 | |||
| 95 | class Socket : public SocketBase { | ||
| 96 | public: | ||
| 97 | Socket() = default; | ||
| 98 | ~Socket() override; | ||
| 31 | 99 | ||
| 32 | Socket(const Socket&) = delete; | 100 | Socket(const Socket&) = delete; |
| 33 | Socket& operator=(const Socket&) = delete; | 101 | Socket& operator=(const Socket&) = delete; |
| @@ -37,57 +105,57 @@ public: | |||
| 37 | // Avoid closing sockets implicitly | 105 | // Avoid closing sockets implicitly |
| 38 | Socket& operator=(Socket&&) noexcept = delete; | 106 | Socket& operator=(Socket&&) noexcept = delete; |
| 39 | 107 | ||
| 40 | Errno Initialize(Domain domain, Type type, Protocol protocol); | 108 | Errno Initialize(Domain domain, Type type, Protocol protocol) override; |
| 41 | 109 | ||
| 42 | Errno Close(); | 110 | Errno Close() override; |
| 43 | 111 | ||
| 44 | std::pair<AcceptResult, Errno> Accept(); | 112 | std::pair<AcceptResult, Errno> Accept() override; |
| 45 | 113 | ||
| 46 | Errno Connect(SockAddrIn addr_in); | 114 | Errno Connect(SockAddrIn addr_in) override; |
| 47 | 115 | ||
| 48 | std::pair<SockAddrIn, Errno> GetPeerName(); | 116 | std::pair<SockAddrIn, Errno> GetPeerName() override; |
| 49 | 117 | ||
| 50 | std::pair<SockAddrIn, Errno> GetSockName(); | 118 | std::pair<SockAddrIn, Errno> GetSockName() override; |
| 51 | 119 | ||
| 52 | Errno Bind(SockAddrIn addr); | 120 | Errno Bind(SockAddrIn addr) override; |
| 53 | 121 | ||
| 54 | Errno Listen(s32 backlog); | 122 | Errno Listen(s32 backlog) override; |
| 55 | 123 | ||
| 56 | Errno Shutdown(ShutdownHow how); | 124 | Errno Shutdown(ShutdownHow how) override; |
| 57 | 125 | ||
| 58 | std::pair<s32, Errno> Recv(int flags, std::vector<u8>& message); | 126 | std::pair<s32, Errno> Recv(int flags, std::vector<u8>& message) override; |
| 59 | 127 | ||
| 60 | std::pair<s32, Errno> RecvFrom(int flags, std::vector<u8>& message, SockAddrIn* addr); | 128 | std::pair<s32, Errno> RecvFrom(int flags, std::vector<u8>& message, SockAddrIn* addr) override; |
| 61 | 129 | ||
| 62 | std::pair<s32, Errno> Send(const std::vector<u8>& message, int flags); | 130 | std::pair<s32, Errno> Send(const std::vector<u8>& message, int flags) override; |
| 63 | 131 | ||
| 64 | std::pair<s32, Errno> SendTo(u32 flags, const std::vector<u8>& message, const SockAddrIn* addr); | 132 | std::pair<s32, Errno> SendTo(u32 flags, const std::vector<u8>& message, |
| 133 | const SockAddrIn* addr) override; | ||
| 65 | 134 | ||
| 66 | Errno SetLinger(bool enable, u32 linger); | 135 | Errno SetLinger(bool enable, u32 linger) override; |
| 67 | 136 | ||
| 68 | Errno SetReuseAddr(bool enable); | 137 | Errno SetReuseAddr(bool enable) override; |
| 69 | 138 | ||
| 70 | Errno SetKeepAlive(bool enable); | 139 | Errno SetKeepAlive(bool enable) override; |
| 71 | 140 | ||
| 72 | Errno SetBroadcast(bool enable); | 141 | Errno SetBroadcast(bool enable) override; |
| 73 | 142 | ||
| 74 | Errno SetSndBuf(u32 value); | 143 | Errno SetSndBuf(u32 value) override; |
| 75 | 144 | ||
| 76 | Errno SetRcvBuf(u32 value); | 145 | Errno SetRcvBuf(u32 value) override; |
| 77 | 146 | ||
| 78 | Errno SetSndTimeo(u32 value); | 147 | Errno SetSndTimeo(u32 value) override; |
| 79 | 148 | ||
| 80 | Errno SetRcvTimeo(u32 value); | 149 | Errno SetRcvTimeo(u32 value) override; |
| 81 | 150 | ||
| 82 | Errno SetNonBlock(bool enable); | 151 | Errno SetNonBlock(bool enable) override; |
| 83 | 152 | ||
| 84 | bool IsOpened() const; | 153 | template <typename T> |
| 154 | Errno SetSockOpt(SOCKET fd, int option, T value); | ||
| 85 | 155 | ||
| 86 | #if defined(_WIN32) | 156 | bool IsOpened() const override; |
| 87 | SOCKET fd = INVALID_SOCKET; | 157 | |
| 88 | #elif YUZU_UNIX | 158 | void HandleProxyPacket(const ProxyPacket& packet) override; |
| 89 | int fd = -1; | ||
| 90 | #endif | ||
| 91 | }; | 159 | }; |
| 92 | 160 | ||
| 93 | std::pair<s32, Errno> Poll(std::vector<PollFD>& poll_fds, s32 timeout); | 161 | std::pair<s32, Errno> Poll(std::vector<PollFD>& poll_fds, s32 timeout); |
diff --git a/src/core/loader/kip.cpp b/src/core/loader/kip.cpp index 9af46a0f7..d8a1bf82a 100644 --- a/src/core/loader/kip.cpp +++ b/src/core/loader/kip.cpp | |||
| @@ -14,7 +14,7 @@ namespace Loader { | |||
| 14 | 14 | ||
| 15 | namespace { | 15 | namespace { |
| 16 | constexpr u32 PageAlignSize(u32 size) { | 16 | constexpr u32 PageAlignSize(u32 size) { |
| 17 | return static_cast<u32>((size + Core::Memory::PAGE_MASK) & ~Core::Memory::PAGE_MASK); | 17 | return static_cast<u32>((size + Core::Memory::YUZU_PAGEMASK) & ~Core::Memory::YUZU_PAGEMASK); |
| 18 | } | 18 | } |
| 19 | } // Anonymous namespace | 19 | } // Anonymous namespace |
| 20 | 20 | ||
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp index 1b0bb0876..73d04d7ee 100644 --- a/src/core/loader/nro.cpp +++ b/src/core/loader/nro.cpp | |||
| @@ -125,7 +125,7 @@ FileType AppLoader_NRO::IdentifyType(const FileSys::VirtualFile& nro_file) { | |||
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | static constexpr u32 PageAlignSize(u32 size) { | 127 | static constexpr u32 PageAlignSize(u32 size) { |
| 128 | return static_cast<u32>((size + Core::Memory::PAGE_MASK) & ~Core::Memory::PAGE_MASK); | 128 | return static_cast<u32>((size + Core::Memory::YUZU_PAGEMASK) & ~Core::Memory::YUZU_PAGEMASK); |
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | static bool LoadNroImpl(Kernel::KProcess& process, const std::vector<u8>& data) { | 131 | static bool LoadNroImpl(Kernel::KProcess& process, const std::vector<u8>& data) { |
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index 8dd956fc6..4c3b3c655 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp | |||
| @@ -45,7 +45,7 @@ std::vector<u8> DecompressSegment(const std::vector<u8>& compressed_data, | |||
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | constexpr u32 PageAlignSize(u32 size) { | 47 | constexpr u32 PageAlignSize(u32 size) { |
| 48 | return static_cast<u32>((size + Core::Memory::PAGE_MASK) & ~Core::Memory::PAGE_MASK); | 48 | return static_cast<u32>((size + Core::Memory::YUZU_PAGEMASK) & ~Core::Memory::YUZU_PAGEMASK); |
| 49 | } | 49 | } |
| 50 | } // Anonymous namespace | 50 | } // Anonymous namespace |
| 51 | 51 | ||
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 1b44280b5..34ad7cadd 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -36,10 +36,11 @@ struct Memory::Impl { | |||
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, PAddr target) { | 38 | void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, PAddr target) { |
| 39 | ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:016X}", size); | 39 | ASSERT_MSG((size & YUZU_PAGEMASK) == 0, "non-page aligned size: {:016X}", size); |
| 40 | ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:016X}", base); | 40 | ASSERT_MSG((base & YUZU_PAGEMASK) == 0, "non-page aligned base: {:016X}", base); |
| 41 | ASSERT_MSG(target >= DramMemoryMap::Base, "Out of bounds target: {:016X}", target); | 41 | ASSERT_MSG(target >= DramMemoryMap::Base, "Out of bounds target: {:016X}", target); |
| 42 | MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, target, Common::PageType::Memory); | 42 | MapPages(page_table, base / YUZU_PAGESIZE, size / YUZU_PAGESIZE, target, |
| 43 | Common::PageType::Memory); | ||
| 43 | 44 | ||
| 44 | if (Settings::IsFastmemEnabled()) { | 45 | if (Settings::IsFastmemEnabled()) { |
| 45 | system.DeviceMemory().buffer.Map(base, target - DramMemoryMap::Base, size); | 46 | system.DeviceMemory().buffer.Map(base, target - DramMemoryMap::Base, size); |
| @@ -47,9 +48,10 @@ struct Memory::Impl { | |||
| 47 | } | 48 | } |
| 48 | 49 | ||
| 49 | void UnmapRegion(Common::PageTable& page_table, VAddr base, u64 size) { | 50 | void UnmapRegion(Common::PageTable& page_table, VAddr base, u64 size) { |
| 50 | ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:016X}", size); | 51 | ASSERT_MSG((size & YUZU_PAGEMASK) == 0, "non-page aligned size: {:016X}", size); |
| 51 | ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:016X}", base); | 52 | ASSERT_MSG((base & YUZU_PAGEMASK) == 0, "non-page aligned base: {:016X}", base); |
| 52 | MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, 0, Common::PageType::Unmapped); | 53 | MapPages(page_table, base / YUZU_PAGESIZE, size / YUZU_PAGESIZE, 0, |
| 54 | Common::PageType::Unmapped); | ||
| 53 | 55 | ||
| 54 | if (Settings::IsFastmemEnabled()) { | 56 | if (Settings::IsFastmemEnabled()) { |
| 55 | system.DeviceMemory().buffer.Unmap(base, size); | 57 | system.DeviceMemory().buffer.Unmap(base, size); |
| @@ -57,7 +59,7 @@ struct Memory::Impl { | |||
| 57 | } | 59 | } |
| 58 | 60 | ||
| 59 | [[nodiscard]] u8* GetPointerFromRasterizerCachedMemory(VAddr vaddr) const { | 61 | [[nodiscard]] u8* GetPointerFromRasterizerCachedMemory(VAddr vaddr) const { |
| 60 | const PAddr paddr{current_page_table->backing_addr[vaddr >> PAGE_BITS]}; | 62 | const PAddr paddr{current_page_table->backing_addr[vaddr >> YUZU_PAGEBITS]}; |
| 61 | 63 | ||
| 62 | if (!paddr) { | 64 | if (!paddr) { |
| 63 | return {}; | 65 | return {}; |
| @@ -67,7 +69,7 @@ struct Memory::Impl { | |||
| 67 | } | 69 | } |
| 68 | 70 | ||
| 69 | [[nodiscard]] u8* GetPointerFromDebugMemory(VAddr vaddr) const { | 71 | [[nodiscard]] u8* GetPointerFromDebugMemory(VAddr vaddr) const { |
| 70 | const PAddr paddr{current_page_table->backing_addr[vaddr >> PAGE_BITS]}; | 72 | const PAddr paddr{current_page_table->backing_addr[vaddr >> YUZU_PAGEBITS]}; |
| 71 | 73 | ||
| 72 | if (paddr == 0) { | 74 | if (paddr == 0) { |
| 73 | return {}; | 75 | return {}; |
| @@ -176,13 +178,14 @@ struct Memory::Impl { | |||
| 176 | auto on_unmapped, auto on_memory, auto on_rasterizer, auto increment) { | 178 | auto on_unmapped, auto on_memory, auto on_rasterizer, auto increment) { |
| 177 | const auto& page_table = process.PageTable().PageTableImpl(); | 179 | const auto& page_table = process.PageTable().PageTableImpl(); |
| 178 | std::size_t remaining_size = size; | 180 | std::size_t remaining_size = size; |
| 179 | std::size_t page_index = addr >> PAGE_BITS; | 181 | std::size_t page_index = addr >> YUZU_PAGEBITS; |
| 180 | std::size_t page_offset = addr & PAGE_MASK; | 182 | std::size_t page_offset = addr & YUZU_PAGEMASK; |
| 181 | 183 | ||
| 182 | while (remaining_size) { | 184 | while (remaining_size) { |
| 183 | const std::size_t copy_amount = | 185 | const std::size_t copy_amount = |
| 184 | std::min(static_cast<std::size_t>(PAGE_SIZE) - page_offset, remaining_size); | 186 | std::min(static_cast<std::size_t>(YUZU_PAGESIZE) - page_offset, remaining_size); |
| 185 | const auto current_vaddr = static_cast<VAddr>((page_index << PAGE_BITS) + page_offset); | 187 | const auto current_vaddr = |
| 188 | static_cast<VAddr>((page_index << YUZU_PAGEBITS) + page_offset); | ||
| 186 | 189 | ||
| 187 | const auto [pointer, type] = page_table.pointers[page_index].PointerType(); | 190 | const auto [pointer, type] = page_table.pointers[page_index].PointerType(); |
| 188 | switch (type) { | 191 | switch (type) { |
| @@ -192,7 +195,7 @@ struct Memory::Impl { | |||
| 192 | } | 195 | } |
| 193 | case Common::PageType::Memory: { | 196 | case Common::PageType::Memory: { |
| 194 | DEBUG_ASSERT(pointer); | 197 | DEBUG_ASSERT(pointer); |
| 195 | u8* mem_ptr = pointer + page_offset + (page_index << PAGE_BITS); | 198 | u8* mem_ptr = pointer + page_offset + (page_index << YUZU_PAGEBITS); |
| 196 | on_memory(copy_amount, mem_ptr); | 199 | on_memory(copy_amount, mem_ptr); |
| 197 | break; | 200 | break; |
| 198 | } | 201 | } |
| @@ -339,10 +342,10 @@ struct Memory::Impl { | |||
| 339 | // Iterate over a contiguous CPU address space, marking/unmarking the region. | 342 | // Iterate over a contiguous CPU address space, marking/unmarking the region. |
| 340 | // The region is at a granularity of CPU pages. | 343 | // The region is at a granularity of CPU pages. |
| 341 | 344 | ||
| 342 | const u64 num_pages = ((vaddr + size - 1) >> PAGE_BITS) - (vaddr >> PAGE_BITS) + 1; | 345 | const u64 num_pages = ((vaddr + size - 1) >> YUZU_PAGEBITS) - (vaddr >> YUZU_PAGEBITS) + 1; |
| 343 | for (u64 i = 0; i < num_pages; ++i, vaddr += PAGE_SIZE) { | 346 | for (u64 i = 0; i < num_pages; ++i, vaddr += YUZU_PAGESIZE) { |
| 344 | const Common::PageType page_type{ | 347 | const Common::PageType page_type{ |
| 345 | current_page_table->pointers[vaddr >> PAGE_BITS].Type()}; | 348 | current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Type()}; |
| 346 | if (debug) { | 349 | if (debug) { |
| 347 | // Switch page type to debug if now debug | 350 | // Switch page type to debug if now debug |
| 348 | switch (page_type) { | 351 | switch (page_type) { |
| @@ -354,7 +357,7 @@ struct Memory::Impl { | |||
| 354 | // Page is already marked. | 357 | // Page is already marked. |
| 355 | break; | 358 | break; |
| 356 | case Common::PageType::Memory: | 359 | case Common::PageType::Memory: |
| 357 | current_page_table->pointers[vaddr >> PAGE_BITS].Store( | 360 | current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store( |
| 358 | nullptr, Common::PageType::DebugMemory); | 361 | nullptr, Common::PageType::DebugMemory); |
| 359 | break; | 362 | break; |
| 360 | default: | 363 | default: |
| @@ -371,9 +374,9 @@ struct Memory::Impl { | |||
| 371 | // Don't mess with already non-debug or rasterizer memory. | 374 | // Don't mess with already non-debug or rasterizer memory. |
| 372 | break; | 375 | break; |
| 373 | case Common::PageType::DebugMemory: { | 376 | case Common::PageType::DebugMemory: { |
| 374 | u8* const pointer{GetPointerFromDebugMemory(vaddr & ~PAGE_MASK)}; | 377 | u8* const pointer{GetPointerFromDebugMemory(vaddr & ~YUZU_PAGEMASK)}; |
| 375 | current_page_table->pointers[vaddr >> PAGE_BITS].Store( | 378 | current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store( |
| 376 | pointer - (vaddr & ~PAGE_MASK), Common::PageType::Memory); | 379 | pointer - (vaddr & ~YUZU_PAGEMASK), Common::PageType::Memory); |
| 377 | break; | 380 | break; |
| 378 | } | 381 | } |
| 379 | default: | 382 | default: |
| @@ -398,10 +401,10 @@ struct Memory::Impl { | |||
| 398 | // granularity of CPU pages, hence why we iterate on a CPU page basis (note: GPU page size | 401 | // granularity of CPU pages, hence why we iterate on a CPU page basis (note: GPU page size |
| 399 | // is different). This assumes the specified GPU address region is contiguous as well. | 402 | // is different). This assumes the specified GPU address region is contiguous as well. |
| 400 | 403 | ||
| 401 | const u64 num_pages = ((vaddr + size - 1) >> PAGE_BITS) - (vaddr >> PAGE_BITS) + 1; | 404 | const u64 num_pages = ((vaddr + size - 1) >> YUZU_PAGEBITS) - (vaddr >> YUZU_PAGEBITS) + 1; |
| 402 | for (u64 i = 0; i < num_pages; ++i, vaddr += PAGE_SIZE) { | 405 | for (u64 i = 0; i < num_pages; ++i, vaddr += YUZU_PAGESIZE) { |
| 403 | const Common::PageType page_type{ | 406 | const Common::PageType page_type{ |
| 404 | current_page_table->pointers[vaddr >> PAGE_BITS].Type()}; | 407 | current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Type()}; |
| 405 | if (cached) { | 408 | if (cached) { |
| 406 | // Switch page type to cached if now cached | 409 | // Switch page type to cached if now cached |
| 407 | switch (page_type) { | 410 | switch (page_type) { |
| @@ -411,7 +414,7 @@ struct Memory::Impl { | |||
| 411 | break; | 414 | break; |
| 412 | case Common::PageType::DebugMemory: | 415 | case Common::PageType::DebugMemory: |
| 413 | case Common::PageType::Memory: | 416 | case Common::PageType::Memory: |
| 414 | current_page_table->pointers[vaddr >> PAGE_BITS].Store( | 417 | current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store( |
| 415 | nullptr, Common::PageType::RasterizerCachedMemory); | 418 | nullptr, Common::PageType::RasterizerCachedMemory); |
| 416 | break; | 419 | break; |
| 417 | case Common::PageType::RasterizerCachedMemory: | 420 | case Common::PageType::RasterizerCachedMemory: |
| @@ -434,16 +437,16 @@ struct Memory::Impl { | |||
| 434 | // that this area is already unmarked as cached. | 437 | // that this area is already unmarked as cached. |
| 435 | break; | 438 | break; |
| 436 | case Common::PageType::RasterizerCachedMemory: { | 439 | case Common::PageType::RasterizerCachedMemory: { |
| 437 | u8* const pointer{GetPointerFromRasterizerCachedMemory(vaddr & ~PAGE_MASK)}; | 440 | u8* const pointer{GetPointerFromRasterizerCachedMemory(vaddr & ~YUZU_PAGEMASK)}; |
| 438 | if (pointer == nullptr) { | 441 | if (pointer == nullptr) { |
| 439 | // It's possible that this function has been called while updating the | 442 | // It's possible that this function has been called while updating the |
| 440 | // pagetable after unmapping a VMA. In that case the underlying VMA will no | 443 | // pagetable after unmapping a VMA. In that case the underlying VMA will no |
| 441 | // longer exist, and we should just leave the pagetable entry blank. | 444 | // longer exist, and we should just leave the pagetable entry blank. |
| 442 | current_page_table->pointers[vaddr >> PAGE_BITS].Store( | 445 | current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store( |
| 443 | nullptr, Common::PageType::Unmapped); | 446 | nullptr, Common::PageType::Unmapped); |
| 444 | } else { | 447 | } else { |
| 445 | current_page_table->pointers[vaddr >> PAGE_BITS].Store( | 448 | current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store( |
| 446 | pointer - (vaddr & ~PAGE_MASK), Common::PageType::Memory); | 449 | pointer - (vaddr & ~YUZU_PAGEMASK), Common::PageType::Memory); |
| 447 | } | 450 | } |
| 448 | break; | 451 | break; |
| 449 | } | 452 | } |
| @@ -465,8 +468,8 @@ struct Memory::Impl { | |||
| 465 | */ | 468 | */ |
| 466 | void MapPages(Common::PageTable& page_table, VAddr base, u64 size, PAddr target, | 469 | void MapPages(Common::PageTable& page_table, VAddr base, u64 size, PAddr target, |
| 467 | Common::PageType type) { | 470 | Common::PageType type) { |
| 468 | LOG_DEBUG(HW_Memory, "Mapping {:016X} onto {:016X}-{:016X}", target, base * PAGE_SIZE, | 471 | LOG_DEBUG(HW_Memory, "Mapping {:016X} onto {:016X}-{:016X}", target, base * YUZU_PAGESIZE, |
| 469 | (base + size) * PAGE_SIZE); | 472 | (base + size) * YUZU_PAGESIZE); |
| 470 | 473 | ||
| 471 | // During boot, current_page_table might not be set yet, in which case we need not flush | 474 | // During boot, current_page_table might not be set yet, in which case we need not flush |
| 472 | if (system.IsPoweredOn()) { | 475 | if (system.IsPoweredOn()) { |
| @@ -474,7 +477,7 @@ struct Memory::Impl { | |||
| 474 | for (u64 i = 0; i < size; i++) { | 477 | for (u64 i = 0; i < size; i++) { |
| 475 | const auto page = base + i; | 478 | const auto page = base + i; |
| 476 | if (page_table.pointers[page].Type() == Common::PageType::RasterizerCachedMemory) { | 479 | if (page_table.pointers[page].Type() == Common::PageType::RasterizerCachedMemory) { |
| 477 | gpu.FlushAndInvalidateRegion(page << PAGE_BITS, PAGE_SIZE); | 480 | gpu.FlushAndInvalidateRegion(page << YUZU_PAGEBITS, YUZU_PAGESIZE); |
| 478 | } | 481 | } |
| 479 | } | 482 | } |
| 480 | } | 483 | } |
| @@ -485,7 +488,7 @@ struct Memory::Impl { | |||
| 485 | 488 | ||
| 486 | if (!target) { | 489 | if (!target) { |
| 487 | ASSERT_MSG(type != Common::PageType::Memory, | 490 | ASSERT_MSG(type != Common::PageType::Memory, |
| 488 | "Mapping memory page without a pointer @ {:016x}", base * PAGE_SIZE); | 491 | "Mapping memory page without a pointer @ {:016x}", base * YUZU_PAGESIZE); |
| 489 | 492 | ||
| 490 | while (base != end) { | 493 | while (base != end) { |
| 491 | page_table.pointers[base].Store(nullptr, type); | 494 | page_table.pointers[base].Store(nullptr, type); |
| @@ -496,14 +499,14 @@ struct Memory::Impl { | |||
| 496 | } else { | 499 | } else { |
| 497 | while (base != end) { | 500 | while (base != end) { |
| 498 | page_table.pointers[base].Store( | 501 | page_table.pointers[base].Store( |
| 499 | system.DeviceMemory().GetPointer(target) - (base << PAGE_BITS), type); | 502 | system.DeviceMemory().GetPointer(target) - (base << YUZU_PAGEBITS), type); |
| 500 | page_table.backing_addr[base] = target - (base << PAGE_BITS); | 503 | page_table.backing_addr[base] = target - (base << YUZU_PAGEBITS); |
| 501 | 504 | ||
| 502 | ASSERT_MSG(page_table.pointers[base].Pointer(), | 505 | ASSERT_MSG(page_table.pointers[base].Pointer(), |
| 503 | "memory mapping base yield a nullptr within the table"); | 506 | "memory mapping base yield a nullptr within the table"); |
| 504 | 507 | ||
| 505 | base += 1; | 508 | base += 1; |
| 506 | target += PAGE_SIZE; | 509 | target += YUZU_PAGESIZE; |
| 507 | } | 510 | } |
| 508 | } | 511 | } |
| 509 | } | 512 | } |
| @@ -518,7 +521,7 @@ struct Memory::Impl { | |||
| 518 | } | 521 | } |
| 519 | 522 | ||
| 520 | // Avoid adding any extra logic to this fast-path block | 523 | // Avoid adding any extra logic to this fast-path block |
| 521 | const uintptr_t raw_pointer = current_page_table->pointers[vaddr >> PAGE_BITS].Raw(); | 524 | const uintptr_t raw_pointer = current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Raw(); |
| 522 | if (u8* const pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) { | 525 | if (u8* const pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) { |
| 523 | return &pointer[vaddr]; | 526 | return &pointer[vaddr]; |
| 524 | } | 527 | } |
| @@ -657,7 +660,7 @@ void Memory::UnmapRegion(Common::PageTable& page_table, VAddr base, u64 size) { | |||
| 657 | bool Memory::IsValidVirtualAddress(const VAddr vaddr) const { | 660 | bool Memory::IsValidVirtualAddress(const VAddr vaddr) const { |
| 658 | const Kernel::KProcess& process = *system.CurrentProcess(); | 661 | const Kernel::KProcess& process = *system.CurrentProcess(); |
| 659 | const auto& page_table = process.PageTable().PageTableImpl(); | 662 | const auto& page_table = process.PageTable().PageTableImpl(); |
| 660 | const size_t page = vaddr >> PAGE_BITS; | 663 | const size_t page = vaddr >> YUZU_PAGEBITS; |
| 661 | if (page >= page_table.pointers.size()) { | 664 | if (page >= page_table.pointers.size()) { |
| 662 | return false; | 665 | return false; |
| 663 | } | 666 | } |
| @@ -668,9 +671,9 @@ bool Memory::IsValidVirtualAddress(const VAddr vaddr) const { | |||
| 668 | 671 | ||
| 669 | bool Memory::IsValidVirtualAddressRange(VAddr base, u64 size) const { | 672 | bool Memory::IsValidVirtualAddressRange(VAddr base, u64 size) const { |
| 670 | VAddr end = base + size; | 673 | VAddr end = base + size; |
| 671 | VAddr page = Common::AlignDown(base, PAGE_SIZE); | 674 | VAddr page = Common::AlignDown(base, YUZU_PAGESIZE); |
| 672 | 675 | ||
| 673 | for (; page < end; page += PAGE_SIZE) { | 676 | for (; page < end; page += YUZU_PAGESIZE) { |
| 674 | if (!IsValidVirtualAddress(page)) { | 677 | if (!IsValidVirtualAddress(page)) { |
| 675 | return false; | 678 | return false; |
| 676 | } | 679 | } |
diff --git a/src/core/memory.h b/src/core/memory.h index 2a21fbcfd..a11ff8766 100644 --- a/src/core/memory.h +++ b/src/core/memory.h | |||
| @@ -27,9 +27,9 @@ namespace Core::Memory { | |||
| 27 | * Page size used by the ARM architecture. This is the smallest granularity with which memory can | 27 | * Page size used by the ARM architecture. This is the smallest granularity with which memory can |
| 28 | * be mapped. | 28 | * be mapped. |
| 29 | */ | 29 | */ |
| 30 | constexpr std::size_t PAGE_BITS = 12; | 30 | constexpr std::size_t YUZU_PAGEBITS = 12; |
| 31 | constexpr u64 PAGE_SIZE = 1ULL << PAGE_BITS; | 31 | constexpr u64 YUZU_PAGESIZE = 1ULL << YUZU_PAGEBITS; |
| 32 | constexpr u64 PAGE_MASK = PAGE_SIZE - 1; | 32 | constexpr u64 YUZU_PAGEMASK = YUZU_PAGESIZE - 1; |
| 33 | 33 | ||
| 34 | /// Virtual user-space memory regions | 34 | /// Virtual user-space memory regions |
| 35 | enum : VAddr { | 35 | enum : VAddr { |