diff options
| -rw-r--r-- | src/core/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | src/core/hid/emulated_controller.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/service/am/am.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/service/nfp/nfp.cpp | 187 | ||||
| -rw-r--r-- | src/core/hle/service/nfp/nfp_device.cpp | 224 | ||||
| -rw-r--r-- | src/core/hle/service/nfp/nfp_device.h | 12 | ||||
| -rw-r--r-- | src/core/hle/service/nfp/nfp_interface.cpp (renamed from src/core/hle/service/nfp/nfp_user.cpp) | 495 | ||||
| -rw-r--r-- | src/core/hle/service/nfp/nfp_interface.h (renamed from src/core/hle/service/nfp/nfp_user.h) | 36 | ||||
| -rw-r--r-- | src/core/hle/service/nfp/nfp_types.h | 54 | ||||
| -rw-r--r-- | src/dedicated_room/yuzu_room.cpp | 16 | ||||
| -rw-r--r-- | src/video_core/engines/fermi_2d.cpp | 16 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.cpp | 10 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_master_semaphore.cpp | 139 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_master_semaphore.h | 48 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_scheduler.cpp | 36 | ||||
| -rw-r--r-- | src/video_core/vulkan_common/vulkan_device.h | 6 | 
16 files changed, 1135 insertions, 154 deletions
| diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 4e677f287..8817a99c9 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -570,10 +570,10 @@ add_library(core STATIC      hle/service/nfp/nfp.h      hle/service/nfp/nfp_device.cpp      hle/service/nfp/nfp_device.h +    hle/service/nfp/nfp_interface.cpp +    hle/service/nfp/nfp_interface.h      hle/service/nfp/nfp_result.h      hle/service/nfp/nfp_types.h -    hle/service/nfp/nfp_user.cpp -    hle/service/nfp/nfp_user.h      hle/service/ngct/ngct.cpp      hle/service/ngct/ngct.h      hle/service/nifm/nifm.cpp diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index a29c9a6f8..a70f8807c 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -280,6 +280,10 @@ void EmulatedController::LoadVirtualGamepadParams() {      virtual_stick_params[Settings::NativeAnalog::LStick].Set("axis_y", 1);      virtual_stick_params[Settings::NativeAnalog::RStick].Set("axis_x", 2);      virtual_stick_params[Settings::NativeAnalog::RStick].Set("axis_y", 3); +    virtual_stick_params[Settings::NativeAnalog::LStick].Set("deadzone", 0.0f); +    virtual_stick_params[Settings::NativeAnalog::LStick].Set("range", 1.0f); +    virtual_stick_params[Settings::NativeAnalog::RStick].Set("deadzone", 0.0f); +    virtual_stick_params[Settings::NativeAnalog::RStick].Set("range", 1.0f);  }  void EmulatedController::ReloadInput() { diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index a17c46121..e59de844c 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -1807,7 +1807,7 @@ void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(HLERequestCon  }  void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx) { -    LOG_WARNING(Service_AM, "(STUBBED) called"); +    LOG_DEBUG(Service_AM, "(STUBBED) called");      IPC::ResponseBuilder rb{ctx, 2};      rb.Push(AM::ResultNoDataInChannel); diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp index e262dc2f2..2714f4bea 100644 --- a/src/core/hle/service/nfp/nfp.cpp +++ b/src/core/hle/service/nfp/nfp.cpp @@ -4,11 +4,138 @@  #include "common/logging/log.h"  #include "core/hle/service/ipc_helpers.h"  #include "core/hle/service/nfp/nfp.h" -#include "core/hle/service/nfp/nfp_user.h" +#include "core/hle/service/nfp/nfp_interface.h"  #include "core/hle/service/server_manager.h"  namespace Service::NFP { +class IUser final : public Interface { +public: +    explicit IUser(Core::System& system_) : Interface(system_, "NFP:IUser") { +        // clang-format off +        static const FunctionInfo functions[] = { +            {0, &IUser::Initialize, "Initialize"}, +            {1, &IUser::Finalize, "Finalize"}, +            {2, &IUser::ListDevices, "ListDevices"}, +            {3, &IUser::StartDetection, "StartDetection"}, +            {4, &IUser::StopDetection, "StopDetection"}, +            {5, &IUser::Mount, "Mount"}, +            {6, &IUser::Unmount, "Unmount"}, +            {7, &IUser::OpenApplicationArea, "OpenApplicationArea"}, +            {8, &IUser::GetApplicationArea, "GetApplicationArea"}, +            {9, &IUser::SetApplicationArea, "SetApplicationArea"}, +            {10, &IUser::Flush, "Flush"}, +            {11, &IUser::Restore, "Restore"}, +            {12, &IUser::CreateApplicationArea, "CreateApplicationArea"}, +            {13, &IUser::GetTagInfo, "GetTagInfo"}, +            {14, &IUser::GetRegisterInfo, "GetRegisterInfo"}, +            {15, &IUser::GetCommonInfo, "GetCommonInfo"}, +            {16, &IUser::GetModelInfo, "GetModelInfo"}, +            {17, &IUser::AttachActivateEvent, "AttachActivateEvent"}, +            {18, &IUser::AttachDeactivateEvent, "AttachDeactivateEvent"}, +            {19, &IUser::GetState, "GetState"}, +            {20, &IUser::GetDeviceState, "GetDeviceState"}, +            {21, &IUser::GetNpadId, "GetNpadId"}, +            {22, &IUser::GetApplicationAreaSize, "GetApplicationAreaSize"}, +            {23, &IUser::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"}, +            {24, &IUser::RecreateApplicationArea, "RecreateApplicationArea"}, +        }; +        // clang-format on + +        RegisterHandlers(functions); +    } +}; + +class ISystem final : public Interface { +public: +    explicit ISystem(Core::System& system_) : Interface(system_, "NFP:ISystem") { +        // clang-format off +        static const FunctionInfo functions[] = { +            {0, &ISystem::InitializeSystem, "InitializeSystem"}, +            {1, &ISystem::FinalizeSystem, "FinalizeSystem"}, +            {2, &ISystem::ListDevices, "ListDevices"}, +            {3, &ISystem::StartDetection, "StartDetection"}, +            {4, &ISystem::StopDetection, "StopDetection"}, +            {5, &ISystem::Mount, "Mount"}, +            {6, &ISystem::Unmount, "Unmount"}, +            {10, &ISystem::Flush, "Flush"}, +            {11, &ISystem::Restore, "Restore"}, +            {12, &ISystem::CreateApplicationArea, "CreateApplicationArea"}, +            {13, &ISystem::GetTagInfo, "GetTagInfo"}, +            {14, &ISystem::GetRegisterInfo, "GetRegisterInfo"}, +            {15, &ISystem::GetCommonInfo, "GetCommonInfo"}, +            {16, &ISystem::GetModelInfo, "GetModelInfo"}, +            {17, &ISystem::AttachActivateEvent, "AttachActivateEvent"}, +            {18, &ISystem::AttachDeactivateEvent, "AttachDeactivateEvent"}, +            {19, &ISystem::GetState, "GetState"}, +            {20, &ISystem::GetDeviceState, "GetDeviceState"}, +            {21, &ISystem::GetNpadId, "GetNpadId"}, +            {23, &ISystem::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"}, +            {100, &ISystem::Format, "Format"}, +            {101, &ISystem::GetAdminInfo, "GetAdminInfo"}, +            {102, &ISystem::GetRegisterInfoPrivate, "GetRegisterInfoPrivate"}, +            {103, &ISystem::SetRegisterInfoPrivate, "SetRegisterInfoPrivate"}, +            {104, &ISystem::DeleteRegisterInfo, "DeleteRegisterInfo"}, +            {105, &ISystem::DeleteApplicationArea, "DeleteApplicationArea"}, +            {106, &ISystem::ExistsApplicationArea, "ExistsApplicationArea"}, +        }; +        // clang-format on + +        RegisterHandlers(functions); +    } +}; + +class IDebug final : public Interface { +public: +    explicit IDebug(Core::System& system_) : Interface(system_, "NFP:IDebug") { +        // clang-format off +        static const FunctionInfo functions[] = { +            {0, &IDebug::InitializeDebug, "InitializeDebug"}, +            {1, &IDebug::FinalizeDebug, "FinalizeDebug"}, +            {2, &IDebug::ListDevices, "ListDevices"}, +            {3, &IDebug::StartDetection, "StartDetection"}, +            {4, &IDebug::StopDetection, "StopDetection"}, +            {5, &IDebug::Mount, "Mount"}, +            {6, &IDebug::Unmount, "Unmount"}, +            {7, &IDebug::OpenApplicationArea, "OpenApplicationArea"}, +            {8, &IDebug::GetApplicationArea, "GetApplicationArea"}, +            {9, &IDebug::SetApplicationArea, "SetApplicationArea"}, +            {10, &IDebug::Flush, "Flush"}, +            {11, &IDebug::Restore, "Restore"}, +            {12, &IDebug::CreateApplicationArea, "CreateApplicationArea"}, +            {13, &IDebug::GetTagInfo, "GetTagInfo"}, +            {14, &IDebug::GetRegisterInfo, "GetRegisterInfo"}, +            {15, &IDebug::GetCommonInfo, "GetCommonInfo"}, +            {16, &IDebug::GetModelInfo, "GetModelInfo"}, +            {17, &IDebug::AttachActivateEvent, "AttachActivateEvent"}, +            {18, &IDebug::AttachDeactivateEvent, "AttachDeactivateEvent"}, +            {19, &IDebug::GetState, "GetState"}, +            {20, &IDebug::GetDeviceState, "GetDeviceState"}, +            {21, &IDebug::GetNpadId, "GetNpadId"}, +            {22, &IDebug::GetApplicationAreaSize, "GetApplicationAreaSize"}, +            {23, &IDebug::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"}, +            {24, &IDebug::RecreateApplicationArea, "RecreateApplicationArea"}, +            {100, &IDebug::Format, "Format"}, +            {101, &IDebug::GetAdminInfo, "GetAdminInfo"}, +            {102, &IDebug::GetRegisterInfoPrivate, "GetRegisterInfoPrivate"}, +            {103, &IDebug::SetRegisterInfoPrivate, "SetRegisterInfoPrivate"}, +            {104, &IDebug::DeleteRegisterInfo, "DeleteRegisterInfo"}, +            {105, &IDebug::DeleteApplicationArea, "DeleteApplicationArea"}, +            {106, &IDebug::ExistsApplicationArea, "ExistsApplicationArea"}, +            {200, &IDebug::GetAll, "GetAll"}, +            {201, &IDebug::SetAll, "SetAll"}, +            {202, &IDebug::FlushDebug, "FlushDebug"}, +            {203, &IDebug::BreakTag, "BreakTag"}, +            {204, nullptr, "ReadBackupData"}, +            {205, nullptr, "WriteBackupData"}, +            {206, nullptr, "WriteNtf"}, +        }; +        // clang-format on + +        RegisterHandlers(functions); +    } +}; +  class IUserManager final : public ServiceFramework<IUserManager> {  public:      explicit IUserManager(Core::System& system_) : ServiceFramework{system_, "nfp:user"} { @@ -37,10 +164,68 @@ private:      std::shared_ptr<IUser> user_interface;  }; +class ISystemManager final : public ServiceFramework<ISystemManager> { +public: +    explicit ISystemManager(Core::System& system_) : ServiceFramework{system_, "nfp:sys"} { +        // clang-format off +        static const FunctionInfo functions[] = { +            {0, &ISystemManager::CreateSystemInterface, "CreateSystemInterface"}, +        }; +        // clang-format on + +        RegisterHandlers(functions); +    } + +private: +    void CreateSystemInterface(HLERequestContext& ctx) { +        LOG_DEBUG(Service_NFP, "called"); + +        if (system_interface == nullptr) { +            system_interface = std::make_shared<ISystem>(system); +        } + +        IPC::ResponseBuilder rb{ctx, 2, 0, 1}; +        rb.Push(ResultSuccess); +        rb.PushIpcInterface<ISystem>(system_interface); +    } + +    std::shared_ptr<ISystem> system_interface; +}; + +class IDebugManager final : public ServiceFramework<IDebugManager> { +public: +    explicit IDebugManager(Core::System& system_) : ServiceFramework{system_, "nfp:dbg"} { +        // clang-format off +        static const FunctionInfo functions[] = { +            {0, &IDebugManager::CreateDebugInterface, "CreateDebugInterface"}, +        }; +        // clang-format on + +        RegisterHandlers(functions); +    } + +private: +    void CreateDebugInterface(HLERequestContext& ctx) { +        LOG_DEBUG(Service_NFP, "called"); + +        if (system_interface == nullptr) { +            system_interface = std::make_shared<IDebug>(system); +        } + +        IPC::ResponseBuilder rb{ctx, 2, 0, 1}; +        rb.Push(ResultSuccess); +        rb.PushIpcInterface<IDebug>(system_interface); +    } + +    std::shared_ptr<IDebug> system_interface; +}; +  void LoopProcess(Core::System& system) {      auto server_manager = std::make_unique<ServerManager>(system);      server_manager->RegisterNamedService("nfp:user", std::make_shared<IUserManager>(system)); +    server_manager->RegisterNamedService("nfp:sys", std::make_shared<ISystemManager>(system)); +    server_manager->RegisterNamedService("nfp:dbg", std::make_shared<IDebugManager>(system));      ServerManager::RunServer(std::move(server_manager));  } diff --git a/src/core/hle/service/nfp/nfp_device.cpp b/src/core/hle/service/nfp/nfp_device.cpp index 607e70968..3f9af53c8 100644 --- a/src/core/hle/service/nfp/nfp_device.cpp +++ b/src/core/hle/service/nfp/nfp_device.cpp @@ -29,7 +29,6 @@  #include "core/hle/service/nfp/amiibo_crypto.h"  #include "core/hle/service/nfp/nfp_device.h"  #include "core/hle/service/nfp/nfp_result.h" -#include "core/hle/service/nfp/nfp_user.h"  #include "core/hle/service/time/time_manager.h"  #include "core/hle/service/time/time_zone_content_manager.h"  #include "core/hle/service/time/time_zone_types.h" @@ -241,6 +240,42 @@ Result NfpDevice::Flush() {      tag_data.write_counter++; +    FlushWithBreak(BreakType::Normal); + +    is_data_moddified = false; + +    return ResultSuccess; +} + +Result NfpDevice::FlushDebug() { +    if (device_state != DeviceState::TagMounted) { +        LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); +        if (device_state == DeviceState::TagRemoved) { +            return TagRemoved; +        } +        return WrongDeviceState; +    } + +    if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { +        LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); +        return WrongDeviceState; +    } + +    tag_data.write_counter++; + +    FlushWithBreak(BreakType::Normal); + +    is_data_moddified = false; + +    return ResultSuccess; +} + +Result NfpDevice::FlushWithBreak(BreakType break_type) { +    if (break_type != BreakType::Normal) { +        LOG_ERROR(Service_NFC, "Break type not implemented {}", break_type); +        return WrongDeviceState; +    } +      std::vector<u8> data(sizeof(EncryptedNTAG215File));      if (is_plain_amiibo) {          memcpy(data.data(), &tag_data, sizeof(tag_data)); @@ -258,8 +293,6 @@ Result NfpDevice::Flush() {          return WriteAmiiboFailed;      } -    is_data_moddified = false; -      return ResultSuccess;  } @@ -417,6 +450,38 @@ Result NfpDevice::GetRegisterInfo(RegisterInfo& register_info) const {      return ResultSuccess;  } +Result NfpDevice::GetRegisterInfoPrivate(RegisterInfoPrivate& register_info) const { +    if (device_state != DeviceState::TagMounted) { +        LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); +        if (device_state == DeviceState::TagRemoved) { +            return TagRemoved; +        } +        return WrongDeviceState; +    } + +    if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { +        LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); +        return WrongDeviceState; +    } + +    if (tag_data.settings.settings.amiibo_initialized == 0) { +        return RegistrationIsNotInitialized; +    } + +    Service::Mii::MiiManager manager; +    const auto& settings = tag_data.settings; + +    // TODO: Validate and complete this data +    register_info = { +        .mii_store_data = {}, +        .creation_date = settings.init_date.GetWriteDate(), +        .amiibo_name = GetAmiiboName(settings), +        .font_region = settings.settings.font_region, +    }; + +    return ResultSuccess; +} +  Result NfpDevice::GetAdminInfo(AdminInfo& admin_info) const {      if (device_state != DeviceState::TagMounted) {          LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); @@ -807,6 +872,159 @@ Result NfpDevice::DeleteApplicationArea() {      return Flush();  } +Result NfpDevice::ExistApplicationArea(bool& has_application_area) { +    if (device_state != DeviceState::TagMounted) { +        LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); +        if (device_state == DeviceState::TagRemoved) { +            return TagRemoved; +        } +        return WrongDeviceState; +    } + +    if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { +        LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); +        return WrongDeviceState; +    } + +    has_application_area = tag_data.settings.settings.appdata_initialized.Value() != 0; + +    return ResultSuccess; +} + +Result NfpDevice::GetAll(NfpData& data) const { +    if (device_state != DeviceState::TagMounted) { +        LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); +        if (device_state == DeviceState::TagRemoved) { +            return TagRemoved; +        } +        return WrongDeviceState; +    } + +    if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { +        LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); +        return WrongDeviceState; +    } + +    CommonInfo common_info{}; +    Service::Mii::MiiManager manager; +    const u64 application_id = tag_data.application_id; + +    GetCommonInfo(common_info); + +    data = { +        .magic = tag_data.constant_value, +        .write_counter = tag_data.write_counter, +        .settings_crc = tag_data.settings.crc, +        .common_info = common_info, +        .mii_char_info = tag_data.owner_mii, +        .mii_store_data_extension = tag_data.mii_extension, +        .creation_date = tag_data.settings.init_date.GetWriteDate(), +        .amiibo_name = tag_data.settings.amiibo_name, +        .amiibo_name_null_terminated = 0, +        .settings = tag_data.settings.settings, +        .unknown1 = tag_data.unknown, +        .register_info_crc = tag_data.register_info_crc, +        .unknown2 = tag_data.unknown2, +        .application_id = application_id, +        .access_id = tag_data.application_area_id, +        .settings_crc_counter = tag_data.settings.crc_counter, +        .font_region = tag_data.settings.settings.font_region, +        .tag_type = PackedTagType::Type2, +        .console_type = +            static_cast<AppAreaVersion>(application_id >> application_id_version_offset & 0xf), +        .application_id_byte = tag_data.application_id_byte, +        .application_area = tag_data.application_area, +    }; + +    return ResultSuccess; +} + +Result NfpDevice::SetAll(const NfpData& data) { +    if (device_state != DeviceState::TagMounted) { +        LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); +        if (device_state == DeviceState::TagRemoved) { +            return TagRemoved; +        } +        return WrongDeviceState; +    } + +    if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { +        LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); +        return WrongDeviceState; +    } + +    tag_data.constant_value = data.magic; +    tag_data.write_counter = data.write_counter; +    tag_data.settings.crc = data.settings_crc; +    tag_data.settings.write_date.SetWriteDate(data.common_info.last_write_date); +    tag_data.write_counter = data.common_info.write_counter; +    tag_data.amiibo_version = data.common_info.version; +    tag_data.owner_mii = data.mii_char_info; +    tag_data.mii_extension = data.mii_store_data_extension; +    tag_data.settings.init_date.SetWriteDate(data.creation_date); +    tag_data.settings.amiibo_name = data.amiibo_name; +    tag_data.settings.settings = data.settings; +    tag_data.unknown = data.unknown1; +    tag_data.register_info_crc = data.register_info_crc; +    tag_data.unknown2 = data.unknown2; +    tag_data.application_id = data.application_id; +    tag_data.application_area_id = data.access_id; +    tag_data.settings.crc_counter = data.settings_crc_counter; +    tag_data.settings.settings.font_region.Assign(data.font_region); +    tag_data.application_id_byte = data.application_id_byte; +    tag_data.application_area = data.application_area; + +    return ResultSuccess; +} + +Result NfpDevice::BreakTag(BreakType break_type) { +    if (device_state != DeviceState::TagMounted) { +        LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); +        if (device_state == DeviceState::TagRemoved) { +            return TagRemoved; +        } +        return WrongDeviceState; +    } + +    if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { +        LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); +        return WrongDeviceState; +    } + +    // TODO: Complete this implementation + +    return FlushWithBreak(break_type); +} + +Result NfpDevice::ReadBackupData() { +    // Not implemented +    return ResultSuccess; +} + +Result NfpDevice::WriteBackupData() { +    // Not implemented +    return ResultSuccess; +} + +Result NfpDevice::WriteNtf() { +    if (device_state != DeviceState::TagMounted) { +        LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); +        if (device_state == DeviceState::TagRemoved) { +            return TagRemoved; +        } +        return WrongDeviceState; +    } + +    if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { +        LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); +        return WrongDeviceState; +    } + +    // Not implemented + +    return ResultSuccess; +} +  u64 NfpDevice::GetHandle() const {      // Generate a handle based of the npad id      return static_cast<u64>(npad_id); diff --git a/src/core/hle/service/nfp/nfp_device.h b/src/core/hle/service/nfp/nfp_device.h index 7f963730d..bab05538a 100644 --- a/src/core/hle/service/nfp/nfp_device.h +++ b/src/core/hle/service/nfp/nfp_device.h @@ -41,12 +41,16 @@ public:      Result StopDetection();      Result Mount(MountTarget mount_target);      Result Unmount(); +      Result Flush(); +    Result FlushDebug(); +    Result FlushWithBreak(BreakType break_type);      Result GetTagInfo(TagInfo& tag_info) const;      Result GetCommonInfo(CommonInfo& common_info) const;      Result GetModelInfo(ModelInfo& model_info) const;      Result GetRegisterInfo(RegisterInfo& register_info) const; +    Result GetRegisterInfoPrivate(RegisterInfoPrivate& register_info) const;      Result GetAdminInfo(AdminInfo& admin_info) const;      Result DeleteRegisterInfo(); @@ -61,6 +65,14 @@ public:      Result CreateApplicationArea(u32 access_id, std::span<const u8> data);      Result RecreateApplicationArea(u32 access_id, std::span<const u8> data);      Result DeleteApplicationArea(); +    Result ExistApplicationArea(bool& has_application_area); + +    Result GetAll(NfpData& data) const; +    Result SetAll(const NfpData& data); +    Result BreakTag(BreakType break_type); +    Result ReadBackupData(); +    Result WriteBackupData(); +    Result WriteNtf();      u64 GetHandle() const;      u32 GetApplicationAreaSize() const; diff --git a/src/core/hle/service/nfp/nfp_user.cpp b/src/core/hle/service/nfp/nfp_interface.cpp index 4e8534113..2ed8bb1ba 100644 --- a/src/core/hle/service/nfp/nfp_user.cpp +++ b/src/core/hle/service/nfp/nfp_interface.cpp @@ -7,42 +7,13 @@  #include "core/hle/kernel/k_event.h"  #include "core/hle/service/ipc_helpers.h"  #include "core/hle/service/nfp/nfp_device.h" +#include "core/hle/service/nfp/nfp_interface.h"  #include "core/hle/service/nfp/nfp_result.h" -#include "core/hle/service/nfp/nfp_user.h"  namespace Service::NFP { -IUser::IUser(Core::System& system_) -    : ServiceFramework{system_, "NFP::IUser"}, service_context{system_, service_name} { -    static const FunctionInfo functions[] = { -        {0, &IUser::Initialize, "Initialize"}, -        {1, &IUser::Finalize, "Finalize"}, -        {2, &IUser::ListDevices, "ListDevices"}, -        {3, &IUser::StartDetection, "StartDetection"}, -        {4, &IUser::StopDetection, "StopDetection"}, -        {5, &IUser::Mount, "Mount"}, -        {6, &IUser::Unmount, "Unmount"}, -        {7, &IUser::OpenApplicationArea, "OpenApplicationArea"}, -        {8, &IUser::GetApplicationArea, "GetApplicationArea"}, -        {9, &IUser::SetApplicationArea, "SetApplicationArea"}, -        {10, &IUser::Flush, "Flush"}, -        {11, &IUser::Restore, "Restore"}, -        {12, &IUser::CreateApplicationArea, "CreateApplicationArea"}, -        {13, &IUser::GetTagInfo, "GetTagInfo"}, -        {14, &IUser::GetRegisterInfo, "GetRegisterInfo"}, -        {15, &IUser::GetCommonInfo, "GetCommonInfo"}, -        {16, &IUser::GetModelInfo, "GetModelInfo"}, -        {17, &IUser::AttachActivateEvent, "AttachActivateEvent"}, -        {18, &IUser::AttachDeactivateEvent, "AttachDeactivateEvent"}, -        {19, &IUser::GetState, "GetState"}, -        {20, &IUser::GetDeviceState, "GetDeviceState"}, -        {21, &IUser::GetNpadId, "GetNpadId"}, -        {22, &IUser::GetApplicationAreaSize, "GetApplicationAreaSize"}, -        {23, &IUser::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"}, -        {24, &IUser::RecreateApplicationArea, "RecreateApplicationArea"}, -    }; -    RegisterHandlers(functions); - +Interface::Interface(Core::System& system_, const char* name) +    : ServiceFramework{system_, name}, service_context{system_, service_name} {      availability_change_event = service_context.CreateEvent("IUser:AvailabilityChangeEvent");      for (u32 device_index = 0; device_index < 10; device_index++) { @@ -52,11 +23,37 @@ IUser::IUser(Core::System& system_)      }  } -IUser ::~IUser() { +Interface::~Interface() {      availability_change_event->Close();  } -void IUser::Initialize(HLERequestContext& ctx) { +void Interface::Initialize(HLERequestContext& ctx) { +    LOG_INFO(Service_NFP, "called"); + +    state = State::Initialized; + +    for (auto& device : devices) { +        device->Initialize(); +    } + +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(ResultSuccess); +} + +void Interface::InitializeSystem(HLERequestContext& ctx) { +    LOG_INFO(Service_NFP, "called"); + +    state = State::Initialized; + +    for (auto& device : devices) { +        device->Initialize(); +    } + +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(ResultSuccess); +} + +void Interface::InitializeDebug(HLERequestContext& ctx) {      LOG_INFO(Service_NFP, "called");      state = State::Initialized; @@ -69,7 +66,7 @@ void IUser::Initialize(HLERequestContext& ctx) {      rb.Push(ResultSuccess);  } -void IUser::Finalize(HLERequestContext& ctx) { +void Interface::Finalize(HLERequestContext& ctx) {      LOG_INFO(Service_NFP, "called");      state = State::NonInitialized; @@ -82,7 +79,33 @@ void IUser::Finalize(HLERequestContext& ctx) {      rb.Push(ResultSuccess);  } -void IUser::ListDevices(HLERequestContext& ctx) { +void Interface::FinalizeSystem(HLERequestContext& ctx) { +    LOG_INFO(Service_NFP, "called"); + +    state = State::NonInitialized; + +    for (auto& device : devices) { +        device->Finalize(); +    } + +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(ResultSuccess); +} + +void Interface::FinalizeDebug(HLERequestContext& ctx) { +    LOG_INFO(Service_NFP, "called"); + +    state = State::NonInitialized; + +    for (auto& device : devices) { +        device->Finalize(); +    } + +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(ResultSuccess); +} + +void Interface::ListDevices(HLERequestContext& ctx) {      LOG_DEBUG(Service_NFP, "called");      if (state == State::NonInitialized) { @@ -128,7 +151,7 @@ void IUser::ListDevices(HLERequestContext& ctx) {      rb.Push(static_cast<s32>(nfp_devices.size()));  } -void IUser::StartDetection(HLERequestContext& ctx) { +void Interface::StartDetection(HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      const auto device_handle{rp.Pop<u64>()};      const auto nfp_protocol{rp.PopEnum<TagProtocol>()}; @@ -153,7 +176,7 @@ void IUser::StartDetection(HLERequestContext& ctx) {      rb.Push(result);  } -void IUser::StopDetection(HLERequestContext& ctx) { +void Interface::StopDetection(HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      const auto device_handle{rp.Pop<u64>()};      LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); @@ -177,7 +200,7 @@ void IUser::StopDetection(HLERequestContext& ctx) {      rb.Push(result);  } -void IUser::Mount(HLERequestContext& ctx) { +void Interface::Mount(HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      const auto device_handle{rp.Pop<u64>()};      const auto model_type{rp.PopEnum<ModelType>()}; @@ -204,7 +227,7 @@ void IUser::Mount(HLERequestContext& ctx) {      rb.Push(result);  } -void IUser::Unmount(HLERequestContext& ctx) { +void Interface::Unmount(HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      const auto device_handle{rp.Pop<u64>()};      LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); @@ -228,7 +251,7 @@ void IUser::Unmount(HLERequestContext& ctx) {      rb.Push(result);  } -void IUser::OpenApplicationArea(HLERequestContext& ctx) { +void Interface::OpenApplicationArea(HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      const auto device_handle{rp.Pop<u64>()};      const auto access_id{rp.Pop<u32>()}; @@ -253,7 +276,7 @@ void IUser::OpenApplicationArea(HLERequestContext& ctx) {      rb.Push(result);  } -void IUser::GetApplicationArea(HLERequestContext& ctx) { +void Interface::GetApplicationArea(HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      const auto device_handle{rp.Pop<u64>()};      const auto data_size = ctx.GetWriteBufferSize(); @@ -287,7 +310,7 @@ void IUser::GetApplicationArea(HLERequestContext& ctx) {      rb.Push(static_cast<u32>(data_size));  } -void IUser::SetApplicationArea(HLERequestContext& ctx) { +void Interface::SetApplicationArea(HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      const auto device_handle{rp.Pop<u64>()};      const auto data{ctx.ReadBuffer()}; @@ -318,7 +341,7 @@ void IUser::SetApplicationArea(HLERequestContext& ctx) {      rb.Push(result);  } -void IUser::Flush(HLERequestContext& ctx) { +void Interface::Flush(HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      const auto device_handle{rp.Pop<u64>()};      LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); @@ -342,7 +365,7 @@ void IUser::Flush(HLERequestContext& ctx) {      rb.Push(result);  } -void IUser::Restore(HLERequestContext& ctx) { +void Interface::Restore(HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      const auto device_handle{rp.Pop<u64>()};      LOG_WARNING(Service_NFP, "(STUBBED) called, device_handle={}", device_handle); @@ -366,7 +389,7 @@ void IUser::Restore(HLERequestContext& ctx) {      rb.Push(result);  } -void IUser::CreateApplicationArea(HLERequestContext& ctx) { +void Interface::CreateApplicationArea(HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      const auto device_handle{rp.Pop<u64>()};      const auto access_id{rp.Pop<u32>()}; @@ -399,7 +422,7 @@ void IUser::CreateApplicationArea(HLERequestContext& ctx) {      rb.Push(result);  } -void IUser::GetTagInfo(HLERequestContext& ctx) { +void Interface::GetTagInfo(HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      const auto device_handle{rp.Pop<u64>()};      LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); @@ -425,7 +448,7 @@ void IUser::GetTagInfo(HLERequestContext& ctx) {      rb.Push(result);  } -void IUser::GetRegisterInfo(HLERequestContext& ctx) { +void Interface::GetRegisterInfo(HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      const auto device_handle{rp.Pop<u64>()};      LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); @@ -451,7 +474,7 @@ void IUser::GetRegisterInfo(HLERequestContext& ctx) {      rb.Push(result);  } -void IUser::GetCommonInfo(HLERequestContext& ctx) { +void Interface::GetCommonInfo(HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      const auto device_handle{rp.Pop<u64>()};      LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); @@ -477,7 +500,7 @@ void IUser::GetCommonInfo(HLERequestContext& ctx) {      rb.Push(result);  } -void IUser::GetModelInfo(HLERequestContext& ctx) { +void Interface::GetModelInfo(HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      const auto device_handle{rp.Pop<u64>()};      LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); @@ -503,7 +526,7 @@ void IUser::GetModelInfo(HLERequestContext& ctx) {      rb.Push(result);  } -void IUser::AttachActivateEvent(HLERequestContext& ctx) { +void Interface::AttachActivateEvent(HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      const auto device_handle{rp.Pop<u64>()};      LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); @@ -527,7 +550,7 @@ void IUser::AttachActivateEvent(HLERequestContext& ctx) {      rb.PushCopyObjects(device.value()->GetActivateEvent());  } -void IUser::AttachDeactivateEvent(HLERequestContext& ctx) { +void Interface::AttachDeactivateEvent(HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      const auto device_handle{rp.Pop<u64>()};      LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); @@ -551,7 +574,7 @@ void IUser::AttachDeactivateEvent(HLERequestContext& ctx) {      rb.PushCopyObjects(device.value()->GetDeactivateEvent());  } -void IUser::GetState(HLERequestContext& ctx) { +void Interface::GetState(HLERequestContext& ctx) {      LOG_DEBUG(Service_NFP, "called");      IPC::ResponseBuilder rb{ctx, 3}; @@ -559,7 +582,7 @@ void IUser::GetState(HLERequestContext& ctx) {      rb.PushEnum(state);  } -void IUser::GetDeviceState(HLERequestContext& ctx) { +void Interface::GetDeviceState(HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      const auto device_handle{rp.Pop<u64>()};      LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); @@ -577,7 +600,7 @@ void IUser::GetDeviceState(HLERequestContext& ctx) {      rb.PushEnum(device.value()->GetCurrentState());  } -void IUser::GetNpadId(HLERequestContext& ctx) { +void Interface::GetNpadId(HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      const auto device_handle{rp.Pop<u64>()};      LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); @@ -601,7 +624,7 @@ void IUser::GetNpadId(HLERequestContext& ctx) {      rb.PushEnum(device.value()->GetNpadId());  } -void IUser::GetApplicationAreaSize(HLERequestContext& ctx) { +void Interface::GetApplicationAreaSize(HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      const auto device_handle{rp.Pop<u64>()};      LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); @@ -619,7 +642,7 @@ void IUser::GetApplicationAreaSize(HLERequestContext& ctx) {      rb.Push(device.value()->GetApplicationAreaSize());  } -void IUser::AttachAvailabilityChangeEvent(HLERequestContext& ctx) { +void Interface::AttachAvailabilityChangeEvent(HLERequestContext& ctx) {      LOG_INFO(Service_NFP, "called");      if (state == State::NonInitialized) { @@ -633,7 +656,7 @@ void IUser::AttachAvailabilityChangeEvent(HLERequestContext& ctx) {      rb.PushCopyObjects(availability_change_event->GetReadableEvent());  } -void IUser::RecreateApplicationArea(HLERequestContext& ctx) { +void Interface::RecreateApplicationArea(HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      const auto device_handle{rp.Pop<u64>()};      const auto access_id{rp.Pop<u32>()}; @@ -660,7 +683,361 @@ void IUser::RecreateApplicationArea(HLERequestContext& ctx) {      rb.Push(result);  } -std::optional<std::shared_ptr<NfpDevice>> IUser::GetNfpDevice(u64 handle) { +void Interface::Format(HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; +    const auto device_handle{rp.Pop<u64>()}; +    LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); + +    if (state == State::NonInitialized) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(NfcDisabled); +        return; +    } + +    auto device = GetNfpDevice(device_handle); + +    if (!device.has_value()) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(DeviceNotFound); +        return; +    } + +    const auto result = device.value()->Format(); +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(result); +} + +void Interface::GetAdminInfo(HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; +    const auto device_handle{rp.Pop<u64>()}; +    LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); + +    if (state == State::NonInitialized) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(NfcDisabled); +        return; +    } + +    auto device = GetNfpDevice(device_handle); + +    if (!device.has_value()) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(DeviceNotFound); +        return; +    } + +    AdminInfo admin_info{}; +    const auto result = device.value()->GetAdminInfo(admin_info); +    ctx.WriteBuffer(admin_info); +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(result); +} + +void Interface::GetRegisterInfoPrivate(HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; +    const auto device_handle{rp.Pop<u64>()}; +    LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); + +    if (state == State::NonInitialized) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(NfcDisabled); +        return; +    } + +    auto device = GetNfpDevice(device_handle); + +    if (!device.has_value()) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(DeviceNotFound); +        return; +    } + +    RegisterInfoPrivate register_info{}; +    const auto result = device.value()->GetRegisterInfoPrivate(register_info); +    ctx.WriteBuffer(register_info); +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(result); +} + +void Interface::SetRegisterInfoPrivate(HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; +    const auto device_handle{rp.Pop<u64>()}; +    const auto buffer{ctx.ReadBuffer()}; +    LOG_DEBUG(Service_NFP, "called, device_handle={}, buffer_size={}", device_handle, +              buffer.size()); + +    if (state == State::NonInitialized) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(NfcDisabled); +        return; +    } + +    auto device = GetNfpDevice(device_handle); + +    if (!device.has_value()) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(DeviceNotFound); +        return; +    } + +    const auto result = device.value()->SetRegisterInfoPrivate({}); +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(result); +} + +void Interface::DeleteRegisterInfo(HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; +    const auto device_handle{rp.Pop<u64>()}; +    LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); + +    if (state == State::NonInitialized) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(NfcDisabled); +        return; +    } + +    auto device = GetNfpDevice(device_handle); + +    if (!device.has_value()) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(DeviceNotFound); +        return; +    } + +    const auto result = device.value()->DeleteRegisterInfo(); +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(result); +} + +void Interface::DeleteApplicationArea(HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; +    const auto device_handle{rp.Pop<u64>()}; +    LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); + +    if (state == State::NonInitialized) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(NfcDisabled); +        return; +    } + +    auto device = GetNfpDevice(device_handle); + +    if (!device.has_value()) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(DeviceNotFound); +        return; +    } + +    const auto result = device.value()->DeleteApplicationArea(); +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(result); +} + +void Interface::ExistsApplicationArea(HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; +    const auto device_handle{rp.Pop<u64>()}; +    LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); + +    if (state == State::NonInitialized) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(NfcDisabled); +        return; +    } + +    auto device = GetNfpDevice(device_handle); + +    if (!device.has_value()) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(DeviceNotFound); +        return; +    } + +    bool has_application_area = false; +    const auto result = device.value()->ExistApplicationArea(has_application_area); +    IPC::ResponseBuilder rb{ctx, 3}; +    rb.Push(result); +    rb.Push(has_application_area); +} + +void Interface::GetAll(HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; +    const auto device_handle{rp.Pop<u64>()}; +    LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); + +    if (state == State::NonInitialized) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(NfcDisabled); +        return; +    } + +    auto device = GetNfpDevice(device_handle); + +    if (!device.has_value()) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(DeviceNotFound); +        return; +    } + +    NfpData data{}; +    const auto result = device.value()->GetAll(data); + +    ctx.WriteBuffer(data); + +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(result); +} + +void Interface::SetAll(HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; +    const auto device_handle{rp.Pop<u64>()}; +    const auto nfp_data{ctx.ReadBuffer()}; + +    LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); + +    if (state == State::NonInitialized) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(NfcDisabled); +        return; +    } + +    auto device = GetNfpDevice(device_handle); + +    if (!device.has_value()) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(DeviceNotFound); +        return; +    } + +    NfpData data{}; +    memcpy(&data, nfp_data.data(), sizeof(NfpData)); + +    const auto result = device.value()->SetAll(data); +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(result); +} + +void Interface::FlushDebug(HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; +    const auto device_handle{rp.Pop<u64>()}; +    LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); + +    if (state == State::NonInitialized) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(NfcDisabled); +        return; +    } + +    auto device = GetNfpDevice(device_handle); + +    if (!device.has_value()) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(DeviceNotFound); +        return; +    } + +    const auto result = device.value()->FlushDebug(); +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(result); +} + +void Interface::BreakTag(HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; +    const auto device_handle{rp.Pop<u64>()}; +    const auto break_type{rp.PopEnum<BreakType>()}; +    LOG_DEBUG(Service_NFP, "called, device_handle={}, break_type={}", device_handle, break_type); + +    if (state == State::NonInitialized) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(NfcDisabled); +        return; +    } + +    auto device = GetNfpDevice(device_handle); + +    if (!device.has_value()) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(DeviceNotFound); +        return; +    } + +    const auto result = device.value()->BreakTag(break_type); +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(result); +} + +void Interface::ReadBackupData(HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; +    const auto device_handle{rp.Pop<u64>()}; +    LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); + +    if (state == State::NonInitialized) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(NfcDisabled); +        return; +    } + +    auto device = GetNfpDevice(device_handle); + +    if (!device.has_value()) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(DeviceNotFound); +        return; +    } + +    const auto result = device.value()->ReadBackupData(); +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(result); +} + +void Interface::WriteBackupData(HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; +    const auto device_handle{rp.Pop<u64>()}; +    LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); + +    if (state == State::NonInitialized) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(NfcDisabled); +        return; +    } + +    auto device = GetNfpDevice(device_handle); + +    if (!device.has_value()) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(DeviceNotFound); +        return; +    } + +    const auto result = device.value()->WriteBackupData(); +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(result); +} + +void Interface::WriteNtf(HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; +    const auto device_handle{rp.Pop<u64>()}; +    LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); + +    if (state == State::NonInitialized) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(NfcDisabled); +        return; +    } + +    auto device = GetNfpDevice(device_handle); + +    if (!device.has_value()) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(DeviceNotFound); +        return; +    } + +    const auto result = device.value()->WriteNtf(); +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(result); +} + +std::optional<std::shared_ptr<NfpDevice>> Interface::GetNfpDevice(u64 handle) {      for (auto& device : devices) {          if (device->GetHandle() == handle) {              return device; diff --git a/src/core/hle/service/nfp/nfp_user.h b/src/core/hle/service/nfp/nfp_interface.h index 1f3ff2ea8..616c94b06 100644 --- a/src/core/hle/service/nfp/nfp_user.h +++ b/src/core/hle/service/nfp/nfp_interface.h @@ -13,19 +13,17 @@  namespace Service::NFP {  class NfpDevice; -class IUser final : public ServiceFramework<IUser> { +class Interface : public ServiceFramework<Interface> {  public: -    explicit IUser(Core::System& system_); -    ~IUser(); - -private: -    enum class State : u32 { -        NonInitialized, -        Initialized, -    }; +    explicit Interface(Core::System& system_, const char* name); +    ~Interface() override;      void Initialize(HLERequestContext& ctx); +    void InitializeSystem(HLERequestContext& ctx); +    void InitializeDebug(HLERequestContext& ctx);      void Finalize(HLERequestContext& ctx); +    void FinalizeSystem(HLERequestContext& ctx); +    void FinalizeDebug(HLERequestContext& ctx);      void ListDevices(HLERequestContext& ctx);      void StartDetection(HLERequestContext& ctx);      void StopDetection(HLERequestContext& ctx); @@ -49,6 +47,26 @@ private:      void GetApplicationAreaSize(HLERequestContext& ctx);      void AttachAvailabilityChangeEvent(HLERequestContext& ctx);      void RecreateApplicationArea(HLERequestContext& ctx); +    void Format(HLERequestContext& ctx); +    void GetAdminInfo(HLERequestContext& ctx); +    void GetRegisterInfoPrivate(HLERequestContext& ctx); +    void SetRegisterInfoPrivate(HLERequestContext& ctx); +    void DeleteRegisterInfo(HLERequestContext& ctx); +    void DeleteApplicationArea(HLERequestContext& ctx); +    void ExistsApplicationArea(HLERequestContext& ctx); +    void GetAll(HLERequestContext& ctx); +    void SetAll(HLERequestContext& ctx); +    void FlushDebug(HLERequestContext& ctx); +    void BreakTag(HLERequestContext& ctx); +    void ReadBackupData(HLERequestContext& ctx); +    void WriteBackupData(HLERequestContext& ctx); +    void WriteNtf(HLERequestContext& ctx); + +private: +    enum class State : u32 { +        NonInitialized, +        Initialized, +    };      std::optional<std::shared_ptr<NfpDevice>> GetNfpDevice(u64 handle); diff --git a/src/core/hle/service/nfp/nfp_types.h b/src/core/hle/service/nfp/nfp_types.h index 70c878552..1ef047cee 100644 --- a/src/core/hle/service/nfp/nfp_types.h +++ b/src/core/hle/service/nfp/nfp_types.h @@ -109,6 +109,12 @@ enum class AppAreaVersion : u8 {      NotSet = 0xFF,  }; +enum class BreakType : u32 { +    Normal, +    Unknown1, +    Unknown2, +}; +  enum class CabinetMode : u8 {      StartNicknameAndOwnerSettings,      StartGameDataEraser, @@ -181,6 +187,12 @@ struct AmiiboDate {          };      } +    void SetWriteDate(const WriteDate& write_date) { +        SetYear(write_date.year); +        SetMonth(write_date.month); +        SetDay(write_date.day); +    } +      void SetYear(u16 year) {          const u16 year_converted = static_cast<u16>((year - 2000) << 9);          raw_date = Common::swap16((GetValue() & ~0xFE00) | year_converted); @@ -354,6 +366,15 @@ struct RegisterInfo {  };  static_assert(sizeof(RegisterInfo) == 0x100, "RegisterInfo is an invalid size"); +struct RegisterInfoPrivate { +    Service::Mii::MiiStoreData mii_store_data; +    WriteDate creation_date; +    AmiiboName amiibo_name; +    u8 font_region; +    INSERT_PADDING_BYTES(0x8E); +}; +static_assert(sizeof(RegisterInfoPrivate) == 0x100, "RegisterInfoPrivate is an invalid size"); +  struct AdminInfo {      u64 application_id;      u32 application_area_id; @@ -366,6 +387,39 @@ struct AdminInfo {  };  static_assert(sizeof(AdminInfo) == 0x40, "AdminInfo is an invalid size"); +#pragma pack(1) +// This is nn::nfp::NfpData +struct NfpData { +    u8 magic; +    INSERT_PADDING_BYTES(0x1); +    u8 write_counter; +    INSERT_PADDING_BYTES(0x1); +    u32 settings_crc; +    INSERT_PADDING_BYTES(0x38); +    CommonInfo common_info; +    Service::Mii::Ver3StoreData mii_char_info; +    Service::Mii::NfpStoreDataExtension mii_store_data_extension; +    WriteDate creation_date; +    std::array<u16_be, amiibo_name_length> amiibo_name; +    u16 amiibo_name_null_terminated; +    Settings settings; +    u8 unknown1; +    u32 register_info_crc; +    std::array<u32, 5> unknown2; +    INSERT_PADDING_BYTES(0x64); +    u64 application_id; +    u32 access_id; +    u16 settings_crc_counter; +    u8 font_region; +    PackedTagType tag_type; +    AppAreaVersion console_type; +    u8 application_id_byte; +    INSERT_PADDING_BYTES(0x2E); +    ApplicationArea application_area; +}; +static_assert(sizeof(NfpData) == 0x298, "NfpData is an invalid size"); +#pragma pack() +  struct SectorKey {      MifareCmd command;      u8 unknown; // Usually 1 diff --git a/src/dedicated_room/yuzu_room.cpp b/src/dedicated_room/yuzu_room.cpp index 359891883..d707dabe2 100644 --- a/src/dedicated_room/yuzu_room.cpp +++ b/src/dedicated_room/yuzu_room.cpp @@ -49,6 +49,7 @@ static void PrintHelp(const char* argv0) {               " [options] <filename>\n"               "--room-name         The name of the room\n"               "--room-description  The room description\n" +             "--bind-address      The bind address for the room\n"               "--port              The port used for the room\n"               "--max_members       The maximum number of players for this room\n"               "--password          The password for the room\n" @@ -195,6 +196,7 @@ int main(int argc, char** argv) {      std::string web_api_url;      std::string ban_list_file;      std::string log_file = "yuzu-room.log"; +    std::string bind_address;      u64 preferred_game_id = 0;      u32 port = Network::DefaultRoomPort;      u32 max_members = 16; @@ -203,6 +205,7 @@ int main(int argc, char** argv) {      static struct option long_options[] = {          {"room-name", required_argument, 0, 'n'},          {"room-description", required_argument, 0, 'd'}, +        {"bind-address", required_argument, 0, 's'},          {"port", required_argument, 0, 'p'},          {"max_members", required_argument, 0, 'm'},          {"password", required_argument, 0, 'w'}, @@ -222,7 +225,8 @@ int main(int argc, char** argv) {      InitializeLogging(log_file);      while (optind < argc) { -        int arg = getopt_long(argc, argv, "n:d:p:m:w:g:u:t:a:i:l:hv", long_options, &option_index); +        int arg = +            getopt_long(argc, argv, "n:d:s:p:m:w:g:u:t:a:i:l:hv", long_options, &option_index);          if (arg != -1) {              switch (static_cast<char>(arg)) {              case 'n': @@ -231,6 +235,9 @@ int main(int argc, char** argv) {              case 'd':                  room_description.assign(optarg);                  break; +            case 's': +                bind_address.assign(optarg); +                break;              case 'p':                  port = strtoul(optarg, &endarg, 0);                  break; @@ -295,6 +302,9 @@ int main(int argc, char** argv) {          PrintHelp(argv[0]);          return -1;      } +    if (bind_address.empty()) { +        LOG_INFO(Network, "Bind address is empty: defaulting to 0.0.0.0"); +    }      if (port > UINT16_MAX) {          LOG_ERROR(Network, "Port needs to be in the range 0 - 65535!");          PrintHelp(argv[0]); @@ -358,8 +368,8 @@ int main(int argc, char** argv) {      if (auto room = network.GetRoom().lock()) {          AnnounceMultiplayerRoom::GameInfo preferred_game_info{.name = preferred_game,                                                                .id = preferred_game_id}; -        if (!room->Create(room_name, room_description, "", port, password, max_members, username, -                          preferred_game_info, std::move(verify_backend), ban_list, +        if (!room->Create(room_name, room_description, bind_address, port, password, max_members, +                          username, preferred_game_info, std::move(verify_backend), ban_list,                            enable_yuzu_mods)) {              LOG_INFO(Network, "Failed to create room: ");              return -1; diff --git a/src/video_core/engines/fermi_2d.cpp b/src/video_core/engines/fermi_2d.cpp index a126c359c..02e161270 100644 --- a/src/video_core/engines/fermi_2d.cpp +++ b/src/video_core/engines/fermi_2d.cpp @@ -77,6 +77,14 @@ void Fermi2D::Blit() {      const auto bytes_per_pixel = BytesPerBlock(PixelFormatFromRenderTargetFormat(src.format));      const bool delegate_to_gpu = src.width > 512 && src.height > 512 && bytes_per_pixel <= 8 &&                                   src.format != regs.dst.format; + +    auto srcX = args.src_x0; +    auto srcY = args.src_y0; +    if (args.sample_mode.origin == Origin::Corner) { +        srcX -= (args.du_dx >> 33) << 32; +        srcY -= (args.dv_dy >> 33) << 32; +    } +      Config config{          .operation = regs.operation,          .filter = args.sample_mode.filter, @@ -86,10 +94,10 @@ void Fermi2D::Blit() {          .dst_y0 = args.dst_y0,          .dst_x1 = args.dst_x0 + args.dst_width,          .dst_y1 = args.dst_y0 + args.dst_height, -        .src_x0 = static_cast<s32>(args.src_x0 >> 32), -        .src_y0 = static_cast<s32>(args.src_y0 >> 32), -        .src_x1 = static_cast<s32>((args.du_dx * args.dst_width + args.src_x0) >> 32), -        .src_y1 = static_cast<s32>((args.dv_dy * args.dst_height + args.src_y0) >> 32), +        .src_x0 = static_cast<s32>(srcX >> 32), +        .src_y0 = static_cast<s32>(srcY >> 32), +        .src_x1 = static_cast<s32>((srcX + args.du_dx * args.dst_width) >> 32), +        .src_y1 = static_cast<s32>((srcY + args.dv_dy * args.dst_height) >> 32),      };      const auto need_align_to_pitch = diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 614d61db4..0932fadc2 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -4,6 +4,7 @@  #include <cstring>  #include <optional>  #include "common/assert.h" +#include "common/bit_util.h"  #include "common/scope_exit.h"  #include "common/settings.h"  #include "core/core.h" @@ -259,12 +260,13 @@ u32 Maxwell3D::GetMaxCurrentVertices() {  size_t Maxwell3D::EstimateIndexBufferSize() {      GPUVAddr start_address = regs.index_buffer.StartAddress();      GPUVAddr end_address = regs.index_buffer.EndAddress(); -    static constexpr std::array<size_t, 4> max_sizes = { -        std::numeric_limits<u8>::max(), std::numeric_limits<u16>::max(), -        std::numeric_limits<u32>::max(), std::numeric_limits<u32>::max()}; +    static constexpr std::array<size_t, 3> max_sizes = {std::numeric_limits<u8>::max(), +                                                        std::numeric_limits<u16>::max(), +                                                        std::numeric_limits<u32>::max()};      const size_t byte_size = regs.index_buffer.FormatSizeInBytes(); +    const size_t log2_byte_size = Common::Log2Ceil64(byte_size);      return std::min<size_t>( -        memory_manager.GetMemoryLayoutSize(start_address, byte_size * max_sizes[byte_size]) / +        memory_manager.GetMemoryLayoutSize(start_address, byte_size * max_sizes[log2_byte_size]) /              byte_size,          static_cast<size_t>(end_address - start_address));  } diff --git a/src/video_core/renderer_vulkan/vk_master_semaphore.cpp b/src/video_core/renderer_vulkan/vk_master_semaphore.cpp index 8aa07ef9d..47c74e4d8 100644 --- a/src/video_core/renderer_vulkan/vk_master_semaphore.cpp +++ b/src/video_core/renderer_vulkan/vk_master_semaphore.cpp @@ -10,7 +10,14 @@  namespace Vulkan { -MasterSemaphore::MasterSemaphore(const Device& device) { +MasterSemaphore::MasterSemaphore(const Device& device_) : device(device_) { +    if (!device.HasTimelineSemaphore()) { +        static constexpr VkFenceCreateInfo fence_ci{ +            .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, .pNext = nullptr, .flags = 0}; +        fence = device.GetLogical().CreateFence(fence_ci); +        return; +    } +      static constexpr VkSemaphoreTypeCreateInfo semaphore_type_ci{          .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,          .pNext = nullptr, @@ -42,4 +49,134 @@ MasterSemaphore::MasterSemaphore(const Device& device) {  MasterSemaphore::~MasterSemaphore() = default; +void MasterSemaphore::Refresh() { +    if (!semaphore) { +        // If we don't support timeline semaphores, there's nothing to refresh +        return; +    } + +    u64 this_tick{}; +    u64 counter{}; +    do { +        this_tick = gpu_tick.load(std::memory_order_acquire); +        counter = semaphore.GetCounter(); +        if (counter < this_tick) { +            return; +        } +    } while (!gpu_tick.compare_exchange_weak(this_tick, counter, std::memory_order_release, +                                             std::memory_order_relaxed)); +} + +void MasterSemaphore::Wait(u64 tick) { +    if (!semaphore) { +        // If we don't support timeline semaphores, use an atomic wait +        while (true) { +            u64 current_value = gpu_tick.load(std::memory_order_relaxed); +            if (current_value >= tick) { +                return; +            } +            gpu_tick.wait(current_value); +        } + +        return; +    } + +    // No need to wait if the GPU is ahead of the tick +    if (IsFree(tick)) { +        return; +    } + +    // Update the GPU tick and try again +    Refresh(); + +    if (IsFree(tick)) { +        return; +    } + +    // If none of the above is hit, fallback to a regular wait +    while (!semaphore.Wait(tick)) { +    } + +    Refresh(); +} + +VkResult MasterSemaphore::SubmitQueue(vk::CommandBuffer& cmdbuf, VkSemaphore signal_semaphore, +                                      VkSemaphore wait_semaphore, u64 host_tick) { +    if (semaphore) { +        return SubmitQueueTimeline(cmdbuf, signal_semaphore, wait_semaphore, host_tick); +    } else { +        return SubmitQueueFence(cmdbuf, signal_semaphore, wait_semaphore, host_tick); +    } +} + +static constexpr std::array<VkPipelineStageFlags, 2> wait_stage_masks{ +    VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, +    VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, +}; + +VkResult MasterSemaphore::SubmitQueueTimeline(vk::CommandBuffer& cmdbuf, +                                              VkSemaphore signal_semaphore, +                                              VkSemaphore wait_semaphore, u64 host_tick) { +    const VkSemaphore timeline_semaphore = *semaphore; + +    const u32 num_signal_semaphores = signal_semaphore ? 2 : 1; +    const std::array signal_values{host_tick, u64(0)}; +    const std::array signal_semaphores{timeline_semaphore, signal_semaphore}; + +    const u32 num_wait_semaphores = wait_semaphore ? 2 : 1; +    const std::array wait_values{host_tick - 1, u64(1)}; +    const std::array wait_semaphores{timeline_semaphore, wait_semaphore}; + +    const VkTimelineSemaphoreSubmitInfo timeline_si{ +        .sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, +        .pNext = nullptr, +        .waitSemaphoreValueCount = num_wait_semaphores, +        .pWaitSemaphoreValues = wait_values.data(), +        .signalSemaphoreValueCount = num_signal_semaphores, +        .pSignalSemaphoreValues = signal_values.data(), +    }; +    const VkSubmitInfo submit_info{ +        .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, +        .pNext = &timeline_si, +        .waitSemaphoreCount = num_wait_semaphores, +        .pWaitSemaphores = wait_semaphores.data(), +        .pWaitDstStageMask = wait_stage_masks.data(), +        .commandBufferCount = 1, +        .pCommandBuffers = cmdbuf.address(), +        .signalSemaphoreCount = num_signal_semaphores, +        .pSignalSemaphores = signal_semaphores.data(), +    }; + +    return device.GetGraphicsQueue().Submit(submit_info); +} + +VkResult MasterSemaphore::SubmitQueueFence(vk::CommandBuffer& cmdbuf, VkSemaphore signal_semaphore, +                                           VkSemaphore wait_semaphore, u64 host_tick) { +    const u32 num_signal_semaphores = signal_semaphore ? 1 : 0; +    const u32 num_wait_semaphores = wait_semaphore ? 1 : 0; + +    const VkSubmitInfo submit_info{ +        .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, +        .pNext = nullptr, +        .waitSemaphoreCount = num_wait_semaphores, +        .pWaitSemaphores = &wait_semaphore, +        .pWaitDstStageMask = wait_stage_masks.data(), +        .commandBufferCount = 1, +        .pCommandBuffers = cmdbuf.address(), +        .signalSemaphoreCount = num_signal_semaphores, +        .pSignalSemaphores = &signal_semaphore, +    }; + +    auto result = device.GetGraphicsQueue().Submit(submit_info, *fence); + +    if (result == VK_SUCCESS) { +        fence.Wait(); +        fence.Reset(); +        gpu_tick.store(host_tick); +        gpu_tick.notify_all(); +    } + +    return result; +} +  } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_master_semaphore.h b/src/video_core/renderer_vulkan/vk_master_semaphore.h index 689f02ea5..f2f61f781 100644 --- a/src/video_core/renderer_vulkan/vk_master_semaphore.h +++ b/src/video_core/renderer_vulkan/vk_master_semaphore.h @@ -4,6 +4,8 @@  #pragma once  #include <atomic> +#include <condition_variable> +#include <mutex>  #include <thread>  #include "common/common_types.h" @@ -29,11 +31,6 @@ public:          return gpu_tick.load(std::memory_order_acquire);      } -    /// Returns the timeline semaphore handle. -    [[nodiscard]] VkSemaphore Handle() const noexcept { -        return *semaphore; -    } -      /// Returns true when a tick has been hit by the GPU.      [[nodiscard]] bool IsFree(u64 tick) const noexcept {          return KnownGpuTick() >= tick; @@ -45,37 +42,24 @@ public:      }      /// Refresh the known GPU tick -    void Refresh() { -        u64 this_tick{}; -        u64 counter{}; -        do { -            this_tick = gpu_tick.load(std::memory_order_acquire); -            counter = semaphore.GetCounter(); -            if (counter < this_tick) { -                return; -            } -        } while (!gpu_tick.compare_exchange_weak(this_tick, counter, std::memory_order_release, -                                                 std::memory_order_relaxed)); -    } +    void Refresh();      /// Waits for a tick to be hit on the GPU -    void Wait(u64 tick) { -        // No need to wait if the GPU is ahead of the tick -        if (IsFree(tick)) { -            return; -        } -        // Update the GPU tick and try again -        Refresh(); -        if (IsFree(tick)) { -            return; -        } -        // If none of the above is hit, fallback to a regular wait -        while (!semaphore.Wait(tick)) { -        } -        Refresh(); -    } +    void Wait(u64 tick); + +    /// Submits the device graphics queue, updating the tick as necessary +    VkResult SubmitQueue(vk::CommandBuffer& cmdbuf, VkSemaphore signal_semaphore, +                         VkSemaphore wait_semaphore, u64 host_tick); + +private: +    VkResult SubmitQueueTimeline(vk::CommandBuffer& cmdbuf, VkSemaphore signal_semaphore, +                                 VkSemaphore wait_semaphore, u64 host_tick); +    VkResult SubmitQueueFence(vk::CommandBuffer& cmdbuf, VkSemaphore signal_semaphore, +                              VkSemaphore wait_semaphore, u64 host_tick);  private: +    const Device& device;             ///< Device. +    vk::Fence fence;                  ///< Fence.      vk::Semaphore semaphore;          ///< Timeline semaphore.      std::atomic<u64> gpu_tick{0};     ///< Current known GPU tick.      std::atomic<u64> current_tick{1}; ///< Current logical tick. diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp index b264e6ada..057e16967 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.cpp +++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp @@ -212,45 +212,13 @@ void Scheduler::SubmitExecution(VkSemaphore signal_semaphore, VkSemaphore wait_s      const u64 signal_value = master_semaphore->NextTick();      Record([signal_semaphore, wait_semaphore, signal_value, this](vk::CommandBuffer cmdbuf) {          cmdbuf.End(); -        const VkSemaphore timeline_semaphore = master_semaphore->Handle(); - -        const u32 num_signal_semaphores = signal_semaphore ? 2U : 1U; -        const std::array signal_values{signal_value, u64(0)}; -        const std::array signal_semaphores{timeline_semaphore, signal_semaphore}; - -        const u32 num_wait_semaphores = wait_semaphore ? 2U : 1U; -        const std::array wait_values{signal_value - 1, u64(1)}; -        const std::array wait_semaphores{timeline_semaphore, wait_semaphore}; -        static constexpr std::array<VkPipelineStageFlags, 2> wait_stage_masks{ -            VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, -            VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, -        }; - -        const VkTimelineSemaphoreSubmitInfo timeline_si{ -            .sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, -            .pNext = nullptr, -            .waitSemaphoreValueCount = num_wait_semaphores, -            .pWaitSemaphoreValues = wait_values.data(), -            .signalSemaphoreValueCount = num_signal_semaphores, -            .pSignalSemaphoreValues = signal_values.data(), -        }; -        const VkSubmitInfo submit_info{ -            .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, -            .pNext = &timeline_si, -            .waitSemaphoreCount = num_wait_semaphores, -            .pWaitSemaphores = wait_semaphores.data(), -            .pWaitDstStageMask = wait_stage_masks.data(), -            .commandBufferCount = 1, -            .pCommandBuffers = cmdbuf.address(), -            .signalSemaphoreCount = num_signal_semaphores, -            .pSignalSemaphores = signal_semaphores.data(), -        };          if (on_submit) {              on_submit();          } -        switch (const VkResult result = device.GetGraphicsQueue().Submit(submit_info)) { +        switch (const VkResult result = master_semaphore->SubmitQueue( +                    cmdbuf, signal_semaphore, wait_semaphore, signal_value)) {          case VK_SUCCESS:              break;          case VK_ERROR_DEVICE_LOST: diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 41b5da18a..7d5018151 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -145,7 +145,6 @@      FEATURE_NAME(robustness2, robustImageAccess2)                                                  \      FEATURE_NAME(shader_demote_to_helper_invocation, shaderDemoteToHelperInvocation)               \      FEATURE_NAME(shader_draw_parameters, shaderDrawParameters)                                     \ -    FEATURE_NAME(timeline_semaphore, timelineSemaphore)                                            \      FEATURE_NAME(variable_pointer, variablePointers)                                               \      FEATURE_NAME(variable_pointer, variablePointersStorageBuffer) @@ -158,6 +157,7 @@      FEATURE_NAME(provoking_vertex, provokingVertexLast)                                            \      FEATURE_NAME(shader_float16_int8, shaderFloat16)                                               \      FEATURE_NAME(shader_float16_int8, shaderInt8)                                                  \ +    FEATURE_NAME(timeline_semaphore, timelineSemaphore)                                            \      FEATURE_NAME(transform_feedback, transformFeedback)                                            \      FEATURE_NAME(uniform_buffer_standard_layout, uniformBufferStandardLayout)                      \      FEATURE_NAME(vertex_input_dynamic_state, vertexInputDynamicState) @@ -493,6 +493,10 @@ public:          return extensions.shader_atomic_int64;      } +    bool HasTimelineSemaphore() const { +        return features.timeline_semaphore.timelineSemaphore; +    } +      /// Returns the minimum supported version of SPIR-V.      u32 SupportedSpirvVersion() const {          if (instance_version >= VK_API_VERSION_1_3) { | 
