diff options
Diffstat (limited to 'src/core')
69 files changed, 633 insertions, 607 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 227c431bc..3655b8478 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -14,7 +14,6 @@ add_library(core STATIC      core.h      core_timing.cpp      core_timing.h -    core_timing_util.h      cpu_manager.cpp      cpu_manager.h      crypto/aes_util.cpp diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index 4f2692b05..4f0a3f8ea 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp @@ -16,12 +16,11 @@  #include "common/microprofile.h"  #include "core/core_timing.h" -#include "core/core_timing_util.h"  #include "core/hardware_properties.h"  namespace Core::Timing { -constexpr s64 MAX_SLICE_LENGTH = 4000; +constexpr s64 MAX_SLICE_LENGTH = 10000;  std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback) {      return std::make_shared<EventType>(std::move(callback), std::move(name)); @@ -45,9 +44,7 @@ struct CoreTiming::Event {      }  }; -CoreTiming::CoreTiming() -    : cpu_clock{Common::CreateBestMatchingClock(Hardware::BASE_CLOCK_RATE, Hardware::CNTFREQ)}, -      event_clock{Common::CreateStandardWallClock(Hardware::BASE_CLOCK_RATE, Hardware::CNTFREQ)} {} +CoreTiming::CoreTiming() : clock{Common::CreateOptimalClock()} {}  CoreTiming::~CoreTiming() {      Reset(); @@ -68,7 +65,7 @@ void CoreTiming::Initialize(std::function<void()>&& on_thread_init_) {      on_thread_init = std::move(on_thread_init_);      event_fifo_id = 0;      shutting_down = false; -    ticks = 0; +    cpu_ticks = 0;      const auto empty_timed_callback = [](std::uintptr_t, u64, std::chrono::nanoseconds)          -> std::optional<std::chrono::nanoseconds> { return std::nullopt; };      ev_lost = CreateEvent("_lost_event", empty_timed_callback); @@ -173,38 +170,30 @@ void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type,  }  void CoreTiming::AddTicks(u64 ticks_to_add) { -    ticks += ticks_to_add; -    downcount -= static_cast<s64>(ticks); +    cpu_ticks += ticks_to_add; +    downcount -= static_cast<s64>(cpu_ticks);  }  void CoreTiming::Idle() { -    if (!event_queue.empty()) { -        const u64 next_event_time = event_queue.front().time; -        const u64 next_ticks = nsToCycles(std::chrono::nanoseconds(next_event_time)) + 10U; -        if (next_ticks > ticks) { -            ticks = next_ticks; -        } -        return; -    } -    ticks += 1000U; +    cpu_ticks += 1000U;  }  void CoreTiming::ResetTicks() {      downcount = MAX_SLICE_LENGTH;  } -u64 CoreTiming::GetCPUTicks() const { +u64 CoreTiming::GetClockTicks() const {      if (is_multicore) [[likely]] { -        return cpu_clock->GetCPUCycles(); +        return clock->GetCNTPCT();      } -    return ticks; +    return Common::WallClock::CPUTickToCNTPCT(cpu_ticks);  } -u64 CoreTiming::GetClockTicks() const { +u64 CoreTiming::GetGPUTicks() const {      if (is_multicore) [[likely]] { -        return cpu_clock->GetClockCycles(); +        return clock->GetGPUTick();      } -    return CpuCyclesToClockCycles(ticks); +    return Common::WallClock::CPUTickToGPUTick(cpu_ticks);  }  std::optional<s64> CoreTiming::Advance() { @@ -297,9 +286,7 @@ void CoreTiming::ThreadLoop() {          }          paused_set = true; -        event_clock->Pause(true);          pause_event.Wait(); -        event_clock->Pause(false);      }  } @@ -315,25 +302,18 @@ void CoreTiming::Reset() {      has_started = false;  } -std::chrono::nanoseconds CoreTiming::GetCPUTimeNs() const { -    if (is_multicore) [[likely]] { -        return cpu_clock->GetTimeNS(); -    } -    return CyclesToNs(ticks); -} -  std::chrono::nanoseconds CoreTiming::GetGlobalTimeNs() const {      if (is_multicore) [[likely]] { -        return event_clock->GetTimeNS(); +        return clock->GetTimeNS();      } -    return CyclesToNs(ticks); +    return std::chrono::nanoseconds{Common::WallClock::CPUTickToNS(cpu_ticks)};  }  std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const {      if (is_multicore) [[likely]] { -        return event_clock->GetTimeUS(); +        return clock->GetTimeUS();      } -    return CyclesToUs(ticks); +    return std::chrono::microseconds{Common::WallClock::CPUTickToUS(cpu_ticks)};  }  } // namespace Core::Timing diff --git a/src/core/core_timing.h b/src/core/core_timing.h index e7c4a949f..10db1de55 100644 --- a/src/core/core_timing.h +++ b/src/core/core_timing.h @@ -116,14 +116,11 @@ public:          return downcount;      } -    /// Returns current time in emulated CPU cycles -    u64 GetCPUTicks() const; - -    /// Returns current time in emulated in Clock cycles +    /// Returns the current CNTPCT tick value.      u64 GetClockTicks() const; -    /// Returns current time in nanoseconds. -    std::chrono::nanoseconds GetCPUTimeNs() const; +    /// Returns the current GPU tick value. +    u64 GetGPUTicks() const;      /// Returns current time in microseconds.      std::chrono::microseconds GetGlobalTimeUs() const; @@ -142,8 +139,7 @@ private:      void Reset(); -    std::unique_ptr<Common::WallClock> cpu_clock; -    std::unique_ptr<Common::WallClock> event_clock; +    std::unique_ptr<Common::WallClock> clock;      s64 global_timer = 0; @@ -171,7 +167,7 @@ private:      s64 pause_end_time{};      /// Cycle timing -    u64 ticks{}; +    u64 cpu_ticks{};      s64 downcount{};  }; diff --git a/src/core/core_timing_util.h b/src/core/core_timing_util.h deleted file mode 100644 index fe5aaefc7..000000000 --- a/src/core/core_timing_util.h +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <chrono> - -#include "common/common_types.h" -#include "core/hardware_properties.h" - -namespace Core::Timing { - -namespace detail { -constexpr u64 CNTFREQ_ADJUSTED = Hardware::CNTFREQ / 1000; -constexpr u64 BASE_CLOCK_RATE_ADJUSTED = Hardware::BASE_CLOCK_RATE / 1000; -} // namespace detail - -[[nodiscard]] constexpr s64 msToCycles(std::chrono::milliseconds ms) { -    return ms.count() * detail::BASE_CLOCK_RATE_ADJUSTED; -} - -[[nodiscard]] constexpr s64 usToCycles(std::chrono::microseconds us) { -    return us.count() * detail::BASE_CLOCK_RATE_ADJUSTED / 1000; -} - -[[nodiscard]] constexpr s64 nsToCycles(std::chrono::nanoseconds ns) { -    return ns.count() * detail::BASE_CLOCK_RATE_ADJUSTED / 1000000; -} - -[[nodiscard]] constexpr u64 msToClockCycles(std::chrono::milliseconds ms) { -    return static_cast<u64>(ms.count()) * detail::CNTFREQ_ADJUSTED; -} - -[[nodiscard]] constexpr u64 usToClockCycles(std::chrono::microseconds us) { -    return us.count() * detail::CNTFREQ_ADJUSTED / 1000; -} - -[[nodiscard]] constexpr u64 nsToClockCycles(std::chrono::nanoseconds ns) { -    return ns.count() * detail::CNTFREQ_ADJUSTED / 1000000; -} - -[[nodiscard]] constexpr u64 CpuCyclesToClockCycles(u64 ticks) { -    return ticks * detail::CNTFREQ_ADJUSTED / detail::BASE_CLOCK_RATE_ADJUSTED; -} - -[[nodiscard]] constexpr std::chrono::milliseconds CyclesToMs(s64 cycles) { -    return std::chrono::milliseconds(cycles / detail::BASE_CLOCK_RATE_ADJUSTED); -} - -[[nodiscard]] constexpr std::chrono::nanoseconds CyclesToNs(s64 cycles) { -    return std::chrono::nanoseconds(cycles * 1000000 / detail::BASE_CLOCK_RATE_ADJUSTED); -} - -[[nodiscard]] constexpr std::chrono::microseconds CyclesToUs(s64 cycles) { -    return std::chrono::microseconds(cycles * 1000 / detail::BASE_CLOCK_RATE_ADJUSTED); -} - -} // namespace Core::Timing diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index 4e61d4335..d3286b352 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp @@ -153,7 +153,7 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const {      const auto sdmc_load_dir = fs_controller.GetSDMCModificationLoadRoot(title_id);      std::vector<VirtualDir> patch_dirs = {sdmc_load_dir}; -    if (load_dir != nullptr && load_dir->GetSize() > 0) { +    if (load_dir != nullptr) {          const auto load_patch_dirs = load_dir->GetSubdirectories();          patch_dirs.insert(patch_dirs.end(), load_patch_dirs.begin(), load_patch_dirs.end());      } @@ -354,8 +354,7 @@ static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, ContentRecordType t      const auto load_dir = fs_controller.GetModificationLoadRoot(title_id);      const auto sdmc_load_dir = fs_controller.GetSDMCModificationLoadRoot(title_id);      if ((type != ContentRecordType::Program && type != ContentRecordType::Data) || -        ((load_dir == nullptr || load_dir->GetSize() <= 0) && -         (sdmc_load_dir == nullptr || sdmc_load_dir->GetSize() <= 0))) { +        (load_dir == nullptr && sdmc_load_dir == nullptr)) {          return;      } @@ -496,7 +495,7 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u      // General Mods (LayeredFS and IPS)      const auto mod_dir = fs_controller.GetModificationLoadRoot(title_id); -    if (mod_dir != nullptr && mod_dir->GetSize() > 0) { +    if (mod_dir != nullptr) {          for (const auto& mod : mod_dir->GetSubdirectories()) {              std::string types; @@ -540,7 +539,7 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u      // SDMC mod directory (RomFS LayeredFS)      const auto sdmc_mod_dir = fs_controller.GetSDMCModificationLoadRoot(title_id); -    if (sdmc_mod_dir != nullptr && sdmc_mod_dir->GetSize() > 0) { +    if (sdmc_mod_dir != nullptr) {          std::string types;          if (IsDirValidAndNonEmpty(FindSubdirectoryCaseless(sdmc_mod_dir, "exefs"))) {              AppendCommaIfNotEmpty(types, "LayeredExeFS"); diff --git a/src/core/file_sys/vfs_concat.cpp b/src/core/file_sys/vfs_concat.cpp index 853b893a1..311a59e5f 100644 --- a/src/core/file_sys/vfs_concat.cpp +++ b/src/core/file_sys/vfs_concat.cpp @@ -150,23 +150,29 @@ std::size_t ConcatenatedVfsFile::Read(u8* data, std::size_t length, std::size_t      while (cur_length > 0 && it != concatenation_map.end()) {          // Check if we can read the file at this position.          const auto& file = it->file; -        const u64 file_offset = it->offset; +        const u64 map_offset = it->offset;          const u64 file_size = file->GetSize(); -        if (cur_offset >= file_offset + file_size) { +        if (cur_offset > map_offset + file_size) {              // Entirely out of bounds read.              break;          }          // Read the file at this position. -        const u64 intended_read_size = std::min<u64>(cur_length, file_size); +        const u64 file_seek = cur_offset - map_offset; +        const u64 intended_read_size = std::min<u64>(cur_length, file_size - file_seek);          const u64 actual_read_size = -            file->Read(data + (cur_offset - offset), intended_read_size, cur_offset - file_offset); +            file->Read(data + (cur_offset - offset), intended_read_size, file_seek);          // Update tracking.          cur_offset += actual_read_size;          cur_length -= actual_read_size;          it++; + +        // If we encountered a short read, we're done. +        if (actual_read_size < intended_read_size) { +            break; +        }      }      return cur_offset - offset; diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp index 7a15d8438..b0515ec05 100644 --- a/src/core/file_sys/vfs_real.cpp +++ b/src/core/file_sys/vfs_real.cpp @@ -10,6 +10,7 @@  #include "common/fs/fs.h"  #include "common/fs/path_util.h"  #include "common/logging/log.h" +#include "core/file_sys/vfs.h"  #include "core/file_sys/vfs_real.h"  // For FileTimeStampRaw @@ -72,8 +73,10 @@ VfsEntryType RealVfsFilesystem::GetEntryType(std::string_view path_) const {      return VfsEntryType::File;  } -VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) { +VirtualFile RealVfsFilesystem::OpenFileFromEntry(std::string_view path_, std::optional<u64> size, +                                                 Mode perms) {      const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); +    std::scoped_lock lk{list_lock};      if (auto it = cache.find(path); it != cache.end()) {          if (auto file = it->second.lock(); file) { @@ -81,23 +84,30 @@ VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) {          }      } -    if (!FS::Exists(path) || !FS::IsFile(path)) { +    if (!size && !FS::IsFile(path)) {          return nullptr;      }      auto reference = std::make_unique<FileReference>(); -    this->InsertReferenceIntoList(*reference); +    this->InsertReferenceIntoListLocked(*reference); -    auto file = -        std::shared_ptr<RealVfsFile>(new RealVfsFile(*this, std::move(reference), path, perms)); +    auto file = std::shared_ptr<RealVfsFile>( +        new RealVfsFile(*this, std::move(reference), path, perms, size));      cache[path] = file;      return file;  } +VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) { +    return OpenFileFromEntry(path_, {}, perms); +} +  VirtualFile RealVfsFilesystem::CreateFile(std::string_view path_, Mode perms) {      const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); -    cache.erase(path); +    { +        std::scoped_lock lk{list_lock}; +        cache.erase(path); +    }      // Current usages of CreateFile expect to delete the contents of an existing file.      if (FS::IsFile(path)) { @@ -127,8 +137,11 @@ VirtualFile RealVfsFilesystem::CopyFile(std::string_view old_path_, std::string_  VirtualFile RealVfsFilesystem::MoveFile(std::string_view old_path_, std::string_view new_path_) {      const auto old_path = FS::SanitizePath(old_path_, FS::DirectorySeparator::PlatformDefault);      const auto new_path = FS::SanitizePath(new_path_, FS::DirectorySeparator::PlatformDefault); -    cache.erase(old_path); -    cache.erase(new_path); +    { +        std::scoped_lock lk{list_lock}; +        cache.erase(old_path); +        cache.erase(new_path); +    }      if (!FS::RenameFile(old_path, new_path)) {          return nullptr;      } @@ -137,7 +150,10 @@ VirtualFile RealVfsFilesystem::MoveFile(std::string_view old_path_, std::string_  bool RealVfsFilesystem::DeleteFile(std::string_view path_) {      const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); -    cache.erase(path); +    { +        std::scoped_lock lk{list_lock}; +        cache.erase(path); +    }      return FS::RemoveFile(path);  } @@ -176,14 +192,17 @@ bool RealVfsFilesystem::DeleteDirectory(std::string_view path_) {      return FS::RemoveDirRecursively(path);  } -void RealVfsFilesystem::RefreshReference(const std::string& path, Mode perms, -                                         FileReference& reference) { +std::unique_lock<std::mutex> RealVfsFilesystem::RefreshReference(const std::string& path, +                                                                 Mode perms, +                                                                 FileReference& reference) { +    std::unique_lock lk{list_lock}; +      // Temporarily remove from list. -    this->RemoveReferenceFromList(reference); +    this->RemoveReferenceFromListLocked(reference);      // Restore file if needed.      if (!reference.file) { -        this->EvictSingleReference(); +        this->EvictSingleReferenceLocked();          reference.file =              FS::FileOpen(path, ModeFlagsToFileAccessMode(perms), FS::FileType::BinaryFile); @@ -193,12 +212,16 @@ void RealVfsFilesystem::RefreshReference(const std::string& path, Mode perms,      }      // Reinsert into list. -    this->InsertReferenceIntoList(reference); +    this->InsertReferenceIntoListLocked(reference); + +    return lk;  }  void RealVfsFilesystem::DropReference(std::unique_ptr<FileReference>&& reference) { +    std::scoped_lock lk{list_lock}; +      // Remove from list. -    this->RemoveReferenceFromList(*reference); +    this->RemoveReferenceFromListLocked(*reference);      // Close the file.      if (reference->file) { @@ -207,14 +230,14 @@ void RealVfsFilesystem::DropReference(std::unique_ptr<FileReference>&& reference      }  } -void RealVfsFilesystem::EvictSingleReference() { +void RealVfsFilesystem::EvictSingleReferenceLocked() {      if (num_open_files < MaxOpenFiles || open_references.empty()) {          return;      }      // Get and remove from list.      auto& reference = open_references.back(); -    this->RemoveReferenceFromList(reference); +    this->RemoveReferenceFromListLocked(reference);      // Close the file.      if (reference.file) { @@ -223,10 +246,10 @@ void RealVfsFilesystem::EvictSingleReference() {      }      // Reinsert into closed list. -    this->InsertReferenceIntoList(reference); +    this->InsertReferenceIntoListLocked(reference);  } -void RealVfsFilesystem::InsertReferenceIntoList(FileReference& reference) { +void RealVfsFilesystem::InsertReferenceIntoListLocked(FileReference& reference) {      if (reference.file) {          open_references.push_front(reference);      } else { @@ -234,7 +257,7 @@ void RealVfsFilesystem::InsertReferenceIntoList(FileReference& reference) {      }  } -void RealVfsFilesystem::RemoveReferenceFromList(FileReference& reference) { +void RealVfsFilesystem::RemoveReferenceFromListLocked(FileReference& reference) {      if (reference.file) {          open_references.erase(open_references.iterator_to(reference));      } else { @@ -243,10 +266,10 @@ void RealVfsFilesystem::RemoveReferenceFromList(FileReference& reference) {  }  RealVfsFile::RealVfsFile(RealVfsFilesystem& base_, std::unique_ptr<FileReference> reference_, -                         const std::string& path_, Mode perms_) +                         const std::string& path_, Mode perms_, std::optional<u64> size_)      : base(base_), reference(std::move(reference_)), path(path_),        parent_path(FS::GetParentPath(path_)), path_components(FS::SplitPathComponents(path_)), -      perms(perms_) {} +      size(size_), perms(perms_) {}  RealVfsFile::~RealVfsFile() {      base.DropReference(std::move(reference)); @@ -257,12 +280,15 @@ std::string RealVfsFile::GetName() const {  }  std::size_t RealVfsFile::GetSize() const { -    base.RefreshReference(path, perms, *reference); -    return reference->file ? reference->file->GetSize() : 0; +    if (size) { +        return *size; +    } +    return FS::GetSize(path);  }  bool RealVfsFile::Resize(std::size_t new_size) { -    base.RefreshReference(path, perms, *reference); +    size.reset(); +    auto lk = base.RefreshReference(path, perms, *reference);      return reference->file ? reference->file->SetSize(new_size) : false;  } @@ -279,7 +305,7 @@ bool RealVfsFile::IsReadable() const {  }  std::size_t RealVfsFile::Read(u8* data, std::size_t length, std::size_t offset) const { -    base.RefreshReference(path, perms, *reference); +    auto lk = base.RefreshReference(path, perms, *reference);      if (!reference->file || !reference->file->Seek(static_cast<s64>(offset))) {          return 0;      } @@ -287,7 +313,8 @@ std::size_t RealVfsFile::Read(u8* data, std::size_t length, std::size_t offset)  }  std::size_t RealVfsFile::Write(const u8* data, std::size_t length, std::size_t offset) { -    base.RefreshReference(path, perms, *reference); +    size.reset(); +    auto lk = base.RefreshReference(path, perms, *reference);      if (!reference->file || !reference->file->Seek(static_cast<s64>(offset))) {          return 0;      } @@ -309,10 +336,11 @@ std::vector<VirtualFile> RealVfsDirectory::IterateEntries<RealVfsFile, VfsFile>(      std::vector<VirtualFile> out; -    const FS::DirEntryCallable callback = [this, &out](const std::filesystem::path& full_path) { -        const auto full_path_string = FS::PathToUTF8String(full_path); +    const FS::DirEntryCallable callback = [this, +                                           &out](const std::filesystem::directory_entry& entry) { +        const auto full_path_string = FS::PathToUTF8String(entry.path()); -        out.emplace_back(base.OpenFile(full_path_string, perms)); +        out.emplace_back(base.OpenFileFromEntry(full_path_string, entry.file_size(), perms));          return true;      }; @@ -330,8 +358,9 @@ std::vector<VirtualDir> RealVfsDirectory::IterateEntries<RealVfsDirectory, VfsDi      std::vector<VirtualDir> out; -    const FS::DirEntryCallable callback = [this, &out](const std::filesystem::path& full_path) { -        const auto full_path_string = FS::PathToUTF8String(full_path); +    const FS::DirEntryCallable callback = [this, +                                           &out](const std::filesystem::directory_entry& entry) { +        const auto full_path_string = FS::PathToUTF8String(entry.path());          out.emplace_back(base.OpenDirectory(full_path_string, perms)); @@ -483,12 +512,10 @@ std::map<std::string, VfsEntryType, std::less<>> RealVfsDirectory::GetEntries()      std::map<std::string, VfsEntryType, std::less<>> out; -    const FS::DirEntryCallable callback = [&out](const std::filesystem::path& full_path) { -        const auto filename = FS::PathToUTF8String(full_path.filename()); - +    const FS::DirEntryCallable callback = [&out](const std::filesystem::directory_entry& entry) { +        const auto filename = FS::PathToUTF8String(entry.path().filename());          out.insert_or_assign(filename, -                             FS::IsDir(full_path) ? VfsEntryType::Directory : VfsEntryType::File); - +                             entry.is_directory() ? VfsEntryType::Directory : VfsEntryType::File);          return true;      }; diff --git a/src/core/file_sys/vfs_real.h b/src/core/file_sys/vfs_real.h index d8c900e33..26ea7df62 100644 --- a/src/core/file_sys/vfs_real.h +++ b/src/core/file_sys/vfs_real.h @@ -4,6 +4,8 @@  #pragma once  #include <map> +#include <mutex> +#include <optional>  #include <string_view>  #include "common/intrusive_list.h"  #include "core/file_sys/mode.h" @@ -20,6 +22,8 @@ struct FileReference : public Common::IntrusiveListBaseNode<FileReference> {  };  class RealVfsFile; +class RealVfsDirectory; +  class RealVfsFilesystem : public VfsFilesystem {  public:      RealVfsFilesystem(); @@ -45,17 +49,24 @@ private:      std::map<std::string, std::weak_ptr<VfsFile>, std::less<>> cache;      ReferenceListType open_references;      ReferenceListType closed_references; +    std::mutex list_lock;      size_t num_open_files{};  private:      friend class RealVfsFile; -    void RefreshReference(const std::string& path, Mode perms, FileReference& reference); +    std::unique_lock<std::mutex> RefreshReference(const std::string& path, Mode perms, +                                                  FileReference& reference);      void DropReference(std::unique_ptr<FileReference>&& reference); -    void EvictSingleReference();  private: -    void InsertReferenceIntoList(FileReference& reference); -    void RemoveReferenceFromList(FileReference& reference); +    friend class RealVfsDirectory; +    VirtualFile OpenFileFromEntry(std::string_view path, std::optional<u64> size, +                                  Mode perms = Mode::Read); + +private: +    void EvictSingleReferenceLocked(); +    void InsertReferenceIntoListLocked(FileReference& reference); +    void RemoveReferenceFromListLocked(FileReference& reference);  };  // An implementation of VfsFile that represents a file on the user's computer. @@ -78,13 +89,14 @@ public:  private:      RealVfsFile(RealVfsFilesystem& base, std::unique_ptr<FileReference> reference, -                const std::string& path, Mode perms = Mode::Read); +                const std::string& path, Mode perms = Mode::Read, std::optional<u64> size = {});      RealVfsFilesystem& base;      std::unique_ptr<FileReference> reference;      std::string path;      std::string parent_path;      std::vector<std::string> path_components; +    std::optional<u64> size;      Mode perms;  }; diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 0a7777732..c937495f9 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -149,12 +149,16 @@ void EmulatedController::LoadDevices() {      camera_params[0] = right_joycon;      camera_params[0].Set("camera", true); -    camera_params[1] = Common::ParamPackage{"engine:camera,camera:1"}; -    ring_params[1] = Common::ParamPackage{"engine:joycon,axis_x:100,axis_y:101"}; -    nfc_params[0] = Common::ParamPackage{"engine:virtual_amiibo,nfc:1"};      nfc_params[1] = right_joycon;      nfc_params[1].Set("nfc", true); +    // Only map virtual devices to the first controller +    if (npad_id_type == NpadIdType::Player1 || npad_id_type == NpadIdType::Handheld) { +        camera_params[1] = Common::ParamPackage{"engine:camera,camera:1"}; +        ring_params[1] = Common::ParamPackage{"engine:joycon,axis_x:100,axis_y:101"}; +        nfc_params[0] = Common::ParamPackage{"engine:virtual_amiibo,nfc:1"}; +    } +      output_params[LeftIndex] = left_joycon;      output_params[RightIndex] = right_joycon;      output_params[2] = camera_params[1]; @@ -1176,10 +1180,7 @@ void EmulatedController::SetNfc(const Common::Input::CallbackStatus& callback) {          return;      } -    controller.nfc_state = { -        controller.nfc_values.state, -        controller.nfc_values.data, -    }; +    controller.nfc_state = controller.nfc_values;  }  bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) { @@ -1308,6 +1309,73 @@ bool EmulatedController::HasNfc() const {      return is_connected && (has_virtual_nfc && is_virtual_nfc_supported);  } +bool EmulatedController::AddNfcHandle() { +    nfc_handles++; +    return SetPollingMode(EmulatedDeviceIndex::RightIndex, Common::Input::PollingMode::NFC) == +           Common::Input::DriverResult::Success; +} + +bool EmulatedController::RemoveNfcHandle() { +    nfc_handles--; +    if (nfc_handles <= 0) { +        return SetPollingMode(EmulatedDeviceIndex::RightIndex, +                              Common::Input::PollingMode::Active) == +               Common::Input::DriverResult::Success; +    } +    return true; +} + +bool EmulatedController::StartNfcPolling() { +    auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)]; +    auto& nfc_virtual_output_device = output_devices[3]; + +    return nfc_output_device->StartNfcPolling() == Common::Input::NfcState::Success || +           nfc_virtual_output_device->StartNfcPolling() == Common::Input::NfcState::Success; +} + +bool EmulatedController::StopNfcPolling() { +    auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)]; +    auto& nfc_virtual_output_device = output_devices[3]; + +    return nfc_output_device->StopNfcPolling() == Common::Input::NfcState::Success || +           nfc_virtual_output_device->StopNfcPolling() == Common::Input::NfcState::Success; +} + +bool EmulatedController::ReadAmiiboData(std::vector<u8>& data) { +    auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)]; +    auto& nfc_virtual_output_device = output_devices[3]; + +    if (nfc_output_device->ReadAmiiboData(data) == Common::Input::NfcState::Success) { +        return true; +    } + +    return nfc_virtual_output_device->ReadAmiiboData(data) == Common::Input::NfcState::Success; +} + +bool EmulatedController::ReadMifareData(const Common::Input::MifareRequest& request, +                                        Common::Input::MifareRequest& out_data) { +    auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)]; +    auto& nfc_virtual_output_device = output_devices[3]; + +    if (nfc_output_device->ReadMifareData(request, out_data) == Common::Input::NfcState::Success) { +        return true; +    } + +    return nfc_virtual_output_device->ReadMifareData(request, out_data) == +           Common::Input::NfcState::Success; +} + +bool EmulatedController::WriteMifareData(const Common::Input::MifareRequest& request) { +    auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)]; +    auto& nfc_virtual_output_device = output_devices[3]; + +    if (nfc_output_device->WriteMifareData(request) == Common::Input::NfcState::Success) { +        return true; +    } + +    return nfc_virtual_output_device->WriteMifareData(request) == Common::Input::NfcState::Success; +} +  bool EmulatedController::WriteNfc(const std::vector<u8>& data) {      auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)];      auto& nfc_virtual_output_device = output_devices[3]; diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index 09fe1a0ab..d511e5fac 100644 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h @@ -97,10 +97,7 @@ struct RingSensorForce {      f32 force;  }; -struct NfcState { -    Common::Input::NfcState state{}; -    std::vector<u8> data{}; -}; +using NfcState = Common::Input::NfcStatus;  struct ControllerMotion {      Common::Vec3f accel{}; @@ -393,9 +390,31 @@ public:      /// Returns true if the device has nfc support      bool HasNfc() const; +    /// Sets the joycon in nfc mode and increments the handle count +    bool AddNfcHandle(); + +    /// Decrements the handle count if zero sets the joycon in active mode +    bool RemoveNfcHandle(); + +    /// Start searching for nfc tags +    bool StartNfcPolling(); + +    /// Stop searching for nfc tags +    bool StopNfcPolling(); + +    /// Returns true if the nfc tag was readable +    bool ReadAmiiboData(std::vector<u8>& data); +      /// Returns true if the nfc tag was written      bool WriteNfc(const std::vector<u8>& data); +    /// Returns true if the nfc tag was readable +    bool ReadMifareData(const Common::Input::MifareRequest& request, +                        Common::Input::MifareRequest& out_data); + +    /// Returns true if the nfc tag was written +    bool WriteMifareData(const Common::Input::MifareRequest& request); +      /// Returns the led pattern corresponding to this emulated controller      LedPattern GetLedPattern() const; @@ -532,6 +551,7 @@ private:      bool system_buttons_enabled{true};      f32 motion_sensitivity{Core::HID::MotionInput::IsAtRestStandard};      u32 turbo_button_state{0}; +    std::size_t nfc_handles{0};      // Temporary values to avoid doing changes while the controller is in configuring mode      NpadStyleIndex tmp_npad_type{NpadStyleIndex::None}; diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp index 4ccb1c596..a05716fd8 100644 --- a/src/core/hid/input_converter.cpp +++ b/src/core/hid/input_converter.cpp @@ -299,11 +299,7 @@ Common::Input::NfcStatus TransformToNfc(const Common::Input::CallbackStatus& cal      Common::Input::NfcStatus nfc{};      switch (callback.type) {      case Common::Input::InputType::Nfc: -        nfc = { -            .state = callback.nfc_status, -            .data = callback.raw_data, -        }; -        break; +        return callback.nfc_status;      default:          LOG_ERROR(Input, "Conversion from type {} to NFC not implemented", callback.type);          break; diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp index faa12b4f0..75ce5a23c 100644 --- a/src/core/hle/kernel/k_scheduler.cpp +++ b/src/core/hle/kernel/k_scheduler.cpp @@ -184,7 +184,8 @@ u64 KScheduler::UpdateHighestPriorityThread(KThread* highest_thread) {          prev_highest_thread != highest_thread) [[likely]] {          if (prev_highest_thread != nullptr) [[likely]] {              IncrementScheduledCount(prev_highest_thread); -            prev_highest_thread->SetLastScheduledTick(m_kernel.System().CoreTiming().GetCPUTicks()); +            prev_highest_thread->SetLastScheduledTick( +                m_kernel.System().CoreTiming().GetClockTicks());          }          if (m_state.should_count_idle) {              if (highest_thread != nullptr) [[likely]] { @@ -351,7 +352,7 @@ void KScheduler::SwitchThread(KThread* next_thread) {      // Update the CPU time tracking variables.      const s64 prev_tick = m_last_context_switch_time; -    const s64 cur_tick = m_kernel.System().CoreTiming().GetCPUTicks(); +    const s64 cur_tick = m_kernel.System().CoreTiming().GetClockTicks();      const s64 tick_diff = cur_tick - prev_tick;      cur_thread->AddCpuTime(m_core_id, tick_diff);      if (cur_process != nullptr) { diff --git a/src/core/hle/kernel/k_synchronization_object.cpp b/src/core/hle/kernel/k_synchronization_object.cpp index b7da3eee7..3e5b735b1 100644 --- a/src/core/hle/kernel/k_synchronization_object.cpp +++ b/src/core/hle/kernel/k_synchronization_object.cpp @@ -3,6 +3,7 @@  #include "common/assert.h"  #include "common/common_types.h" +#include "common/scratch_buffer.h"  #include "core/hle/kernel/k_scheduler.h"  #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"  #include "core/hle/kernel/k_synchronization_object.h" @@ -75,7 +76,7 @@ Result KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index,                                      KSynchronizationObject** objects, const s32 num_objects,                                      s64 timeout) {      // Allocate space on stack for thread nodes. -    std::vector<ThreadListNode> thread_nodes(num_objects); +    std::array<ThreadListNode, Svc::ArgumentHandleCountMax> thread_nodes;      // Prepare for wait.      KThread* thread = GetCurrentThreadPointer(kernel); diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index 908811e2c..adb6ec581 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -909,7 +909,7 @@ Result KThread::SetActivity(Svc::ThreadActivity activity) {      R_SUCCEED();  } -Result KThread::GetThreadContext3(std::vector<u8>& out) { +Result KThread::GetThreadContext3(Common::ScratchBuffer<u8>& out) {      // Lock ourselves.      KScopedLightLock lk{m_activity_pause_lock}; @@ -927,15 +927,13 @@ Result KThread::GetThreadContext3(std::vector<u8>& out) {                  // Mask away mode bits, interrupt bits, IL bit, and other reserved bits.                  auto context = GetContext64();                  context.pstate &= 0xFF0FFE20; - -                out.resize(sizeof(context)); +                out.resize_destructive(sizeof(context));                  std::memcpy(out.data(), std::addressof(context), sizeof(context));              } else {                  // Mask away mode bits, interrupt bits, IL bit, and other reserved bits.                  auto context = GetContext32();                  context.cpsr &= 0xFF0FFE20; - -                out.resize(sizeof(context)); +                out.resize_destructive(sizeof(context));                  std::memcpy(out.data(), std::addressof(context), sizeof(context));              }          } diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index 37fe5db77..dd662b3f8 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h @@ -15,6 +15,7 @@  #include "common/intrusive_list.h"  #include "common/intrusive_red_black_tree.h" +#include "common/scratch_buffer.h"  #include "common/spin_lock.h"  #include "core/arm/arm_interface.h"  #include "core/hle/kernel/k_affinity_mask.h" @@ -567,7 +568,7 @@ public:      void RemoveWaiter(KThread* thread); -    Result GetThreadContext3(std::vector<u8>& out); +    Result GetThreadContext3(Common::ScratchBuffer<u8>& out);      KThread* RemoveUserWaiterByKey(bool* out_has_waiters, KProcessAddress key) {          return this->RemoveWaiterByKey(out_has_waiters, key, false); diff --git a/src/core/hle/kernel/svc/svc_info.cpp b/src/core/hle/kernel/svc/svc_info.cpp index 2b2c878b5..445cdd87b 100644 --- a/src/core/hle/kernel/svc/svc_info.cpp +++ b/src/core/hle/kernel/svc/svc_info.cpp @@ -199,9 +199,9 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle          if (same_thread && info_sub_id == 0xFFFFFFFFFFFFFFFF) {              const u64 thread_ticks = current_thread->GetCpuTime(); -            out_ticks = thread_ticks + (core_timing.GetCPUTicks() - prev_ctx_ticks); +            out_ticks = thread_ticks + (core_timing.GetClockTicks() - prev_ctx_ticks);          } else if (same_thread && info_sub_id == system.Kernel().CurrentPhysicalCoreIndex()) { -            out_ticks = core_timing.GetCPUTicks() - prev_ctx_ticks; +            out_ticks = core_timing.GetClockTicks() - prev_ctx_ticks;          }          *result = out_ticks; diff --git a/src/core/hle/kernel/svc/svc_ipc.cpp b/src/core/hle/kernel/svc/svc_ipc.cpp index ea03068aa..60247df2e 100644 --- a/src/core/hle/kernel/svc/svc_ipc.cpp +++ b/src/core/hle/kernel/svc/svc_ipc.cpp @@ -2,6 +2,7 @@  // SPDX-License-Identifier: GPL-2.0-or-later  #include "common/scope_exit.h" +#include "common/scratch_buffer.h"  #include "core/core.h"  #include "core/hle/kernel/k_client_session.h"  #include "core/hle/kernel/k_process.h" @@ -45,11 +46,11 @@ Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles_ad                   handles_addr, static_cast<u64>(sizeof(Handle) * num_handles)),               ResultInvalidPointer); -    std::vector<Handle> handles(num_handles); +    std::array<Handle, Svc::ArgumentHandleCountMax> handles;      GetCurrentMemory(kernel).ReadBlock(handles_addr, handles.data(), sizeof(Handle) * num_handles);      // Convert handle list to object table. -    std::vector<KSynchronizationObject*> objs(num_handles); +    std::array<KSynchronizationObject*, Svc::ArgumentHandleCountMax> objs;      R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles.data(),                                                                       num_handles),               ResultInvalidHandle); @@ -80,7 +81,7 @@ Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles_ad          // Wait for an object.          s32 index;          Result result = KSynchronizationObject::Wait(kernel, std::addressof(index), objs.data(), -                                                     static_cast<s32>(objs.size()), timeout_ns); +                                                     num_handles, timeout_ns);          if (result == ResultTimedOut) {              R_RETURN(result);          } diff --git a/src/core/hle/kernel/svc/svc_synchronization.cpp b/src/core/hle/kernel/svc/svc_synchronization.cpp index 04d65f0bd..53df5bcd8 100644 --- a/src/core/hle/kernel/svc/svc_synchronization.cpp +++ b/src/core/hle/kernel/svc/svc_synchronization.cpp @@ -2,6 +2,7 @@  // SPDX-License-Identifier: GPL-2.0-or-later  #include "common/scope_exit.h" +#include "common/scratch_buffer.h"  #include "core/core.h"  #include "core/hle/kernel/k_process.h"  #include "core/hle/kernel/k_readable_event.h" @@ -54,7 +55,7 @@ static Result WaitSynchronization(Core::System& system, int32_t* out_index, cons      // Get the synchronization context.      auto& kernel = system.Kernel();      auto& handle_table = GetCurrentProcess(kernel).GetHandleTable(); -    std::vector<KSynchronizationObject*> objs(num_handles); +    std::array<KSynchronizationObject*, Svc::ArgumentHandleCountMax> objs;      // Copy user handles.      if (num_handles > 0) { @@ -72,8 +73,8 @@ static Result WaitSynchronization(Core::System& system, int32_t* out_index, cons      });      // Wait on the objects. -    Result res = KSynchronizationObject::Wait(kernel, out_index, objs.data(), -                                              static_cast<s32>(objs.size()), timeout_ns); +    Result res = +        KSynchronizationObject::Wait(kernel, out_index, objs.data(), num_handles, timeout_ns);      R_SUCCEED_IF(res == ResultSessionClosed);      R_RETURN(res); @@ -87,8 +88,7 @@ Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_ha      // Ensure number of handles is valid.      R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange); - -    std::vector<Handle> handles(num_handles); +    std::array<Handle, Svc::ArgumentHandleCountMax> handles;      if (num_handles > 0) {          GetCurrentMemory(system.Kernel())              .ReadBlock(user_handles, handles.data(), num_handles * sizeof(Handle)); diff --git a/src/core/hle/kernel/svc/svc_thread.cpp b/src/core/hle/kernel/svc/svc_thread.cpp index 37b54079c..36b94e6bf 100644 --- a/src/core/hle/kernel/svc/svc_thread.cpp +++ b/src/core/hle/kernel/svc/svc_thread.cpp @@ -174,7 +174,7 @@ Result GetThreadContext3(Core::System& system, u64 out_context, Handle thread_ha          }          // Get the thread context. -        std::vector<u8> context; +        static thread_local Common::ScratchBuffer<u8> context;          R_TRY(thread->GetThreadContext3(context));          // Copy the thread context to user space. diff --git a/src/core/hle/kernel/svc/svc_tick.cpp b/src/core/hle/kernel/svc/svc_tick.cpp index 561336482..7dd7c6e51 100644 --- a/src/core/hle/kernel/svc/svc_tick.cpp +++ b/src/core/hle/kernel/svc/svc_tick.cpp @@ -12,16 +12,8 @@ namespace Kernel::Svc {  int64_t GetSystemTick(Core::System& system) {      LOG_TRACE(Kernel_SVC, "called"); -    auto& core_timing = system.CoreTiming(); -      // Returns the value of cntpct_el0 (https://switchbrew.org/wiki/SVC#svcGetSystemTick) -    const u64 result{core_timing.GetClockTicks()}; - -    if (!system.Kernel().IsMulticore()) { -        core_timing.AddTicks(400U); -    } - -    return static_cast<int64_t>(result); +    return static_cast<int64_t>(system.CoreTiming().GetClockTicks());  }  int64_t GetSystemTick64(Core::System& system) { diff --git a/src/core/hle/service/am/applets/applet_cabinet.cpp b/src/core/hle/service/am/applets/applet_cabinet.cpp index 8b754e9d4..19ed184e8 100644 --- a/src/core/hle/service/am/applets/applet_cabinet.cpp +++ b/src/core/hle/service/am/applets/applet_cabinet.cpp @@ -141,7 +141,7 @@ void Cabinet::DisplayCompleted(bool apply_changes, std::string_view amiibo_name)      applet_output.device_handle = applet_input_common.device_handle;      applet_output.result = CabinetResult::Cancel;      const auto reg_result = nfp_device->GetRegisterInfo(applet_output.register_info); -    const auto tag_result = nfp_device->GetTagInfo(applet_output.tag_info, false); +    const auto tag_result = nfp_device->GetTagInfo(applet_output.tag_info);      nfp_device->Finalize();      if (reg_result.IsSuccess()) { diff --git a/src/core/hle/service/audio/audin_u.cpp b/src/core/hle/service/audio/audin_u.cpp index f0640c64f..c8d574993 100644 --- a/src/core/hle/service/audio/audin_u.cpp +++ b/src/core/hle/service/audio/audin_u.cpp @@ -5,6 +5,7 @@  #include "audio_core/renderer/audio_device.h"  #include "common/common_funcs.h"  #include "common/logging/log.h" +#include "common/settings.h"  #include "common/string_util.h"  #include "core/core.h"  #include "core/hle/kernel/k_event.h" @@ -123,19 +124,13 @@ private:      void GetReleasedAudioInBuffer(HLERequestContext& ctx) {          const auto write_buffer_size = ctx.GetWriteBufferNumElements<u64>(); -        std::vector<u64> released_buffers(write_buffer_size); +        tmp_buffer.resize_destructive(write_buffer_size); +        tmp_buffer[0] = 0; -        const auto count = impl->GetReleasedBuffers(released_buffers); +        const auto count = impl->GetReleasedBuffers(tmp_buffer); -        [[maybe_unused]] std::string tags{}; -        for (u32 i = 0; i < count; i++) { -            tags += fmt::format("{:08X}, ", released_buffers[i]); -        } -        [[maybe_unused]] auto sessionid{impl->GetSystem().GetSessionId()}; -        LOG_TRACE(Service_Audio, "called. Session {} released {} buffers: {}", sessionid, count, -                  tags); +        ctx.WriteBuffer(tmp_buffer); -        ctx.WriteBuffer(released_buffers);          IPC::ResponseBuilder rb{ctx, 3};          rb.Push(ResultSuccess);          rb.Push(count); @@ -200,6 +195,7 @@ private:      KernelHelpers::ServiceContext service_context;      Kernel::KEvent* event;      std::shared_ptr<AudioCore::AudioIn::In> impl; +    Common::ScratchBuffer<u64> tmp_buffer;  };  AudInU::AudInU(Core::System& system_) diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index 3e62fa4fc..032c8c11f 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp @@ -123,19 +123,13 @@ private:      void GetReleasedAudioOutBuffers(HLERequestContext& ctx) {          const auto write_buffer_size = ctx.GetWriteBufferNumElements<u64>(); -        std::vector<u64> released_buffers(write_buffer_size); +        tmp_buffer.resize_destructive(write_buffer_size); +        tmp_buffer[0] = 0; -        const auto count = impl->GetReleasedBuffers(released_buffers); +        const auto count = impl->GetReleasedBuffers(tmp_buffer); -        [[maybe_unused]] std::string tags{}; -        for (u32 i = 0; i < count; i++) { -            tags += fmt::format("{:08X}, ", released_buffers[i]); -        } -        [[maybe_unused]] const auto sessionid{impl->GetSystem().GetSessionId()}; -        LOG_TRACE(Service_Audio, "called. Session {} released {} buffers: {}", sessionid, count, -                  tags); +        ctx.WriteBuffer(tmp_buffer); -        ctx.WriteBuffer(released_buffers);          IPC::ResponseBuilder rb{ctx, 3};          rb.Push(ResultSuccess);          rb.Push(count); @@ -211,6 +205,7 @@ private:      KernelHelpers::ServiceContext service_context;      Kernel::KEvent* event;      std::shared_ptr<AudioCore::AudioOut::Out> impl; +    Common::ScratchBuffer<u64> tmp_buffer;  };  AudOutU::AudOutU(Core::System& system_) diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index 7086d4750..12845c23a 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp @@ -116,28 +116,26 @@ private:          // These buffers are written manually to avoid an issue with WriteBuffer throwing errors for          // checking size 0. Performance size is 0 for most games. -        std::vector<u8> output{}; -        std::vector<u8> performance{};          auto is_buffer_b{ctx.BufferDescriptorB()[0].Size() != 0};          if (is_buffer_b) {              const auto buffersB{ctx.BufferDescriptorB()}; -            output.resize(buffersB[0].Size(), 0); -            performance.resize(buffersB[1].Size(), 0); +            tmp_output.resize_destructive(buffersB[0].Size()); +            tmp_performance.resize_destructive(buffersB[1].Size());          } else {              const auto buffersC{ctx.BufferDescriptorC()}; -            output.resize(buffersC[0].Size(), 0); -            performance.resize(buffersC[1].Size(), 0); +            tmp_output.resize_destructive(buffersC[0].Size()); +            tmp_performance.resize_destructive(buffersC[1].Size());          } -        auto result = impl->RequestUpdate(input, performance, output); +        auto result = impl->RequestUpdate(input, tmp_performance, tmp_output);          if (result.IsSuccess()) {              if (is_buffer_b) { -                ctx.WriteBufferB(output.data(), output.size(), 0); -                ctx.WriteBufferB(performance.data(), performance.size(), 1); +                ctx.WriteBufferB(tmp_output.data(), tmp_output.size(), 0); +                ctx.WriteBufferB(tmp_performance.data(), tmp_performance.size(), 1);              } else { -                ctx.WriteBufferC(output.data(), output.size(), 0); -                ctx.WriteBufferC(performance.data(), performance.size(), 1); +                ctx.WriteBufferC(tmp_output.data(), tmp_output.size(), 0); +                ctx.WriteBufferC(tmp_performance.data(), tmp_performance.size(), 1);              }          } else {              LOG_ERROR(Service_Audio, "RequestUpdate failed error 0x{:02X}!", result.description); @@ -235,6 +233,8 @@ private:      Kernel::KEvent* rendered_event;      Manager& manager;      std::unique_ptr<Renderer> impl; +    Common::ScratchBuffer<u8> tmp_output; +    Common::ScratchBuffer<u8> tmp_performance;  };  class IAudioDevice final : public ServiceFramework<IAudioDevice> { diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audren_u.h index 24ce37e87..d8e9c8719 100644 --- a/src/core/hle/service/audio/audren_u.h +++ b/src/core/hle/service/audio/audren_u.h @@ -4,6 +4,7 @@  #pragma once  #include "audio_core/audio_render_manager.h" +#include "common/scratch_buffer.h"  #include "core/hle/service/kernel_helpers.h"  #include "core/hle/service/service.h" diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp index 451ac224a..c835f6cb7 100644 --- a/src/core/hle/service/audio/hwopus.cpp +++ b/src/core/hle/service/audio/hwopus.cpp @@ -68,13 +68,13 @@ private:                                   ExtraBehavior extra_behavior) {          u32 consumed = 0;          u32 sample_count = 0; -        std::vector<opus_int16> samples(ctx.GetWriteBufferNumElements<opus_int16>()); +        tmp_samples.resize_destructive(ctx.GetWriteBufferNumElements<opus_int16>());          if (extra_behavior == ExtraBehavior::ResetContext) {              ResetDecoderContext();          } -        if (!DecodeOpusData(consumed, sample_count, ctx.ReadBuffer(), samples, performance)) { +        if (!DecodeOpusData(consumed, sample_count, ctx.ReadBuffer(), tmp_samples, performance)) {              LOG_ERROR(Audio, "Failed to decode opus data");              IPC::ResponseBuilder rb{ctx, 2};              // TODO(ogniK): Use correct error code @@ -90,11 +90,11 @@ private:          if (performance) {              rb.Push<u64>(*performance);          } -        ctx.WriteBuffer(samples); +        ctx.WriteBuffer(tmp_samples);      }      bool DecodeOpusData(u32& consumed, u32& sample_count, std::span<const u8> input, -                        std::vector<opus_int16>& output, u64* out_performance_time) const { +                        std::span<opus_int16> output, u64* out_performance_time) const {          const auto start_time = std::chrono::steady_clock::now();          const std::size_t raw_output_sz = output.size() * sizeof(opus_int16);          if (sizeof(OpusPacketHeader) > input.size()) { @@ -154,6 +154,7 @@ private:      OpusDecoderPtr decoder;      u32 sample_rate;      u32 channel_count; +    Common::ScratchBuffer<opus_int16> tmp_samples;  };  class IHardwareOpusDecoderManager final : public ServiceFramework<IHardwareOpusDecoderManager> { diff --git a/src/core/hle/service/hid/hidbus.cpp b/src/core/hle/service/hid/hidbus.cpp index 5604a6fda..80aac221b 100644 --- a/src/core/hle/service/hid/hidbus.cpp +++ b/src/core/hle/service/hid/hidbus.cpp @@ -5,7 +5,6 @@  #include "common/settings.h"  #include "core/core.h"  #include "core/core_timing.h" -#include "core/core_timing_util.h"  #include "core/hid/hid_types.h"  #include "core/hle/kernel/k_event.h"  #include "core/hle/kernel/k_readable_event.h" diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp index f4b180b06..5bf289818 100644 --- a/src/core/hle/service/nfc/common/device.cpp +++ b/src/core/hle/service/nfc/common/device.cpp @@ -93,7 +93,8 @@ void NfcDevice::NpadUpdate(Core::HID::ControllerTriggerType type) {      const auto nfc_status = npad_device->GetNfc();      switch (nfc_status.state) {      case Common::Input::NfcState::NewAmiibo: -        LoadNfcTag(nfc_status.data); +        LoadNfcTag(nfc_status.protocol, nfc_status.tag_type, nfc_status.uuid_length, +                   nfc_status.uuid);          break;      case Common::Input::NfcState::AmiiboRemoved:          if (device_state == DeviceState::Initialized || device_state == DeviceState::TagRemoved) { @@ -108,28 +109,46 @@ void NfcDevice::NpadUpdate(Core::HID::ControllerTriggerType type) {      }  } -bool NfcDevice::LoadNfcTag(std::span<const u8> data) { +bool NfcDevice::LoadNfcTag(u8 protocol, u8 tag_type, u8 uuid_length, UniqueSerialNumber uuid) {      if (device_state != DeviceState::SearchingForTag) {          LOG_ERROR(Service_NFC, "Game is not looking for nfc tag, current state {}", device_state);          return false;      } +    if ((protocol & static_cast<u8>(allowed_protocols)) == 0) { +        LOG_ERROR(Service_NFC, "Protocol not supported {}", protocol); +        return false; +    } + +    real_tag_info = { +        .uuid = uuid, +        .uuid_length = uuid_length, +        .protocol = static_cast<NfcProtocol>(protocol), +        .tag_type = static_cast<TagType>(tag_type), +    }; + +    device_state = DeviceState::TagFound; +    deactivate_event->GetReadableEvent().Clear(); +    activate_event->Signal(); +    return true; +} + +bool NfcDevice::LoadAmiiboData() { +    std::vector<u8> data{}; + +    if (!npad_device->ReadAmiiboData(data)) { +        return false; +    } +      if (data.size() < sizeof(NFP::EncryptedNTAG215File)) {          LOG_ERROR(Service_NFC, "Not an amiibo, size={}", data.size());          return false;      } -    mifare_data.resize(data.size()); -    memcpy(mifare_data.data(), data.data(), data.size()); -      memcpy(&tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File));      is_plain_amiibo = NFP::AmiiboCrypto::IsAmiiboValid(tag_data);      is_write_protected = false; -    device_state = DeviceState::TagFound; -    deactivate_event->GetReadableEvent().Clear(); -    activate_event->Signal(); -      // Fallback for plain amiibos      if (is_plain_amiibo) {          LOG_INFO(Service_NFP, "Using plain amiibo"); @@ -147,6 +166,7 @@ bool NfcDevice::LoadNfcTag(std::span<const u8> data) {          return true;      } +    LOG_INFO(Service_NFP, "Using encrypted amiibo");      tag_data = {};      memcpy(&encrypted_tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File));      return true; @@ -162,7 +182,6 @@ void NfcDevice::CloseNfcTag() {      device_state = DeviceState::TagRemoved;      encrypted_tag_data = {};      tag_data = {}; -    mifare_data = {};      activate_event->GetReadableEvent().Clear();      deactivate_event->Signal();  } @@ -179,8 +198,12 @@ void NfcDevice::Initialize() {      device_state = npad_device->HasNfc() ? DeviceState::Initialized : DeviceState::Unavailable;      encrypted_tag_data = {};      tag_data = {}; -    mifare_data = {}; -    is_initalized = true; + +    if (device_state != DeviceState::Initialized) { +        return; +    } + +    is_initalized = npad_device->AddNfcHandle();  }  void NfcDevice::Finalize() { @@ -190,6 +213,11 @@ void NfcDevice::Finalize() {      if (device_state == DeviceState::SearchingForTag || device_state == DeviceState::TagRemoved) {          StopDetection();      } + +    if (device_state != DeviceState::Unavailable) { +        npad_device->RemoveNfcHandle(); +    } +      device_state = DeviceState::Unavailable;      is_initalized = false;  } @@ -200,10 +228,8 @@ Result NfcDevice::StartDetection(NfcProtocol allowed_protocol) {          return ResultWrongDeviceState;      } -    if (npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, -                                    Common::Input::PollingMode::NFC) != -        Common::Input::DriverResult::Success) { -        LOG_ERROR(Service_NFC, "Nfc not supported"); +    if (!npad_device->StartNfcPolling()) { +        LOG_ERROR(Service_NFC, "Nfc polling not supported");          return ResultNfcDisabled;      } @@ -213,9 +239,6 @@ Result NfcDevice::StartDetection(NfcProtocol allowed_protocol) {  }  Result NfcDevice::StopDetection() { -    npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, -                                Common::Input::PollingMode::Active); -      if (device_state == DeviceState::Initialized) {          return ResultSuccess;      } @@ -225,6 +248,7 @@ Result NfcDevice::StopDetection() {      }      if (device_state == DeviceState::SearchingForTag || device_state == DeviceState::TagRemoved) { +        npad_device->StopNfcPolling();          device_state = DeviceState::Initialized;          return ResultSuccess;      } @@ -233,7 +257,7 @@ Result NfcDevice::StopDetection() {      return ResultWrongDeviceState;  } -Result NfcDevice::GetTagInfo(NFP::TagInfo& tag_info, bool is_mifare) const { +Result NfcDevice::GetTagInfo(NFP::TagInfo& tag_info) const {      if (device_state != DeviceState::TagFound && device_state != DeviceState::TagMounted) {          LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);          if (device_state == DeviceState::TagRemoved) { @@ -242,41 +266,15 @@ Result NfcDevice::GetTagInfo(NFP::TagInfo& tag_info, bool is_mifare) const {          return ResultWrongDeviceState;      } -    UniqueSerialNumber uuid{}; -    u8 uuid_length{}; -    NfcProtocol protocol{NfcProtocol::TypeA}; -    TagType tag_type{TagType::Type2}; - -    if (is_mifare) { -        tag_type = TagType::Mifare; -        uuid_length = sizeof(NFP::NtagTagUuid); -        memcpy(uuid.data(), mifare_data.data(), uuid_length); -    } else { -        tag_type = TagType::Type2; -        uuid_length = sizeof(NFP::NtagTagUuid); -        NFP::NtagTagUuid nUuid{ -            .part1 = encrypted_tag_data.uuid.part1, -            .part2 = encrypted_tag_data.uuid.part2, -            .nintendo_id = encrypted_tag_data.uuid.nintendo_id, -        }; -        memcpy(uuid.data(), &nUuid, uuid_length); +    tag_info = real_tag_info; -        // Generate random UUID to bypass amiibo load limits -        if (Settings::values.random_amiibo_id) { -            Common::TinyMT rng{}; -            rng.Initialize(static_cast<u32>(GetCurrentPosixTime())); -            rng.GenerateRandomBytes(uuid.data(), uuid_length); -        } +    // Generate random UUID to bypass amiibo load limits +    if (real_tag_info.tag_type == TagType::Type2 && Settings::values.random_amiibo_id) { +        Common::TinyMT rng{}; +        rng.Initialize(static_cast<u32>(GetCurrentPosixTime())); +        rng.GenerateRandomBytes(tag_info.uuid.data(), tag_info.uuid_length);      } -    // Protocol and tag type may change here -    tag_info = { -        .uuid = uuid, -        .uuid_length = uuid_length, -        .protocol = protocol, -        .tag_type = tag_type, -    }; -      return ResultSuccess;  } @@ -293,7 +291,7 @@ Result NfcDevice::ReadMifare(std::span<const MifareReadBlockParameter> parameter      Result result = ResultSuccess;      TagInfo tag_info{}; -    result = GetTagInfo(tag_info, true); +    result = GetTagInfo(tag_info);      if (result.IsError()) {          return result; @@ -307,6 +305,8 @@ Result NfcDevice::ReadMifare(std::span<const MifareReadBlockParameter> parameter          return ResultInvalidArgument;      } +    Common::Input::MifareRequest request{}; +    Common::Input::MifareRequest out_data{};      const auto unknown = parameters[0].sector_key.unknown;      for (std::size_t i = 0; i < parameters.size(); i++) {          if (unknown != parameters[i].sector_key.unknown) { @@ -315,25 +315,29 @@ Result NfcDevice::ReadMifare(std::span<const MifareReadBlockParameter> parameter      }      for (std::size_t i = 0; i < parameters.size(); i++) { -        result = ReadMifare(parameters[i], read_block_data[i]); -        if (result.IsError()) { -            break; +        if (parameters[i].sector_key.command == MifareCmd::None) { +            continue;          } +        request.data[i].command = static_cast<u8>(parameters[i].sector_key.command); +        request.data[i].sector = parameters[i].sector_number; +        memcpy(request.data[i].key.data(), parameters[i].sector_key.sector_key.data(), +               sizeof(KeyData));      } -    return result; -} - -Result NfcDevice::ReadMifare(const MifareReadBlockParameter& parameter, -                             MifareReadBlockData& read_block_data) const { -    const std::size_t sector_index = parameter.sector_number * sizeof(DataBlock); -    read_block_data.sector_number = parameter.sector_number; -    if (mifare_data.size() < sector_index + sizeof(DataBlock)) { +    if (!npad_device->ReadMifareData(request, out_data)) {          return ResultMifareError288;      } -    // TODO: Use parameter.sector_key to read encrypted data -    memcpy(read_block_data.data.data(), mifare_data.data() + sector_index, sizeof(DataBlock)); +    for (std::size_t i = 0; i < read_block_data.size(); i++) { +        if (static_cast<MifareCmd>(out_data.data[i].command) == MifareCmd::None) { +            continue; +        } + +        read_block_data[i] = { +            .data = out_data.data[i].data, +            .sector_number = out_data.data[i].sector, +        }; +    }      return ResultSuccess;  } @@ -342,7 +346,7 @@ Result NfcDevice::WriteMifare(std::span<const MifareWriteBlockParameter> paramet      Result result = ResultSuccess;      TagInfo tag_info{}; -    result = GetTagInfo(tag_info, true); +    result = GetTagInfo(tag_info);      if (result.IsError()) {          return result; @@ -363,42 +367,25 @@ Result NfcDevice::WriteMifare(std::span<const MifareWriteBlockParameter> paramet          }      } +    Common::Input::MifareRequest request{};      for (std::size_t i = 0; i < parameters.size(); i++) { -        result = WriteMifare(parameters[i]); -        if (result.IsError()) { -            break; +        if (parameters[i].sector_key.command == MifareCmd::None) { +            continue;          } +        request.data[i].command = static_cast<u8>(parameters[i].sector_key.command); +        request.data[i].sector = parameters[i].sector_number; +        memcpy(request.data[i].key.data(), parameters[i].sector_key.sector_key.data(), +               sizeof(KeyData)); +        memcpy(request.data[i].data.data(), parameters[i].data.data(), sizeof(KeyData));      } -    if (!npad_device->WriteNfc(mifare_data)) { -        LOG_ERROR(Service_NFP, "Error writing to file"); +    if (!npad_device->WriteMifareData(request)) {          return ResultMifareError288;      }      return result;  } -Result NfcDevice::WriteMifare(const MifareWriteBlockParameter& parameter) { -    const std::size_t sector_index = parameter.sector_number * sizeof(DataBlock); - -    if (device_state != DeviceState::TagFound && device_state != DeviceState::TagMounted) { -        LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); -        if (device_state == DeviceState::TagRemoved) { -            return ResultTagRemoved; -        } -        return ResultWrongDeviceState; -    } - -    if (mifare_data.size() < sector_index + sizeof(DataBlock)) { -        return ResultMifareError288; -    } - -    // TODO: Use parameter.sector_key to encrypt the data -    memcpy(mifare_data.data() + sector_index, parameter.data.data(), sizeof(DataBlock)); - -    return ResultSuccess; -} -  Result NfcDevice::SendCommandByPassThrough(const Time::Clock::TimeSpanType& timeout,                                             std::span<const u8> command_data,                                             std::span<u8> out_data) { @@ -412,6 +399,11 @@ Result NfcDevice::Mount(NFP::ModelType model_type, NFP::MountTarget mount_target          return ResultWrongDeviceState;      } +    if (!LoadAmiiboData()) { +        LOG_ERROR(Service_NFP, "Not an amiibo"); +        return ResultInvalidTagType; +    } +      if (!NFP::AmiiboCrypto::IsAmiiboValid(encrypted_tag_data)) {          LOG_ERROR(Service_NFP, "Not an amiibo");          return ResultInvalidTagType; @@ -562,7 +554,7 @@ Result NfcDevice::Restore() {      NFC::TagInfo tag_info{};      std::array<u8, sizeof(NFP::EncryptedNTAG215File)> data{}; -    Result result = GetTagInfo(tag_info, false); +    Result result = GetTagInfo(tag_info);      if (result.IsError()) {          return result; @@ -635,7 +627,7 @@ Result NfcDevice::GetCommonInfo(NFP::CommonInfo& common_info) const {      // TODO: Validate this data      common_info = {          .last_write_date = settings.write_date.GetWriteDate(), -        .write_counter = tag_data.write_counter, +        .write_counter = tag_data.application_write_counter,          .version = tag_data.amiibo_version,          .application_area_size = sizeof(NFP::ApplicationArea),      }; diff --git a/src/core/hle/service/nfc/common/device.h b/src/core/hle/service/nfc/common/device.h index 7560210d6..0ed1ff34c 100644 --- a/src/core/hle/service/nfc/common/device.h +++ b/src/core/hle/service/nfc/common/device.h @@ -42,15 +42,12 @@ public:      Result StartDetection(NfcProtocol allowed_protocol);      Result StopDetection(); -    Result GetTagInfo(TagInfo& tag_info, bool is_mifare) const; +    Result GetTagInfo(TagInfo& tag_info) const;      Result ReadMifare(std::span<const MifareReadBlockParameter> parameters,                        std::span<MifareReadBlockData> read_block_data) const; -    Result ReadMifare(const MifareReadBlockParameter& parameter, -                      MifareReadBlockData& read_block_data) const;      Result WriteMifare(std::span<const MifareWriteBlockParameter> parameters); -    Result WriteMifare(const MifareWriteBlockParameter& parameter);      Result SendCommandByPassThrough(const Time::Clock::TimeSpanType& timeout,                                      std::span<const u8> command_data, std::span<u8> out_data); @@ -105,7 +102,8 @@ public:  private:      void NpadUpdate(Core::HID::ControllerTriggerType type); -    bool LoadNfcTag(std::span<const u8> data); +    bool LoadNfcTag(u8 protocol, u8 tag_type, u8 uuid_length, UniqueSerialNumber uuid); +    bool LoadAmiiboData();      void CloseNfcTag();      NFP::AmiiboName GetAmiiboName(const NFP::AmiiboSettings& settings) const; @@ -140,8 +138,8 @@ private:      bool is_write_protected{};      NFP::MountTarget mount_target{NFP::MountTarget::None}; +    TagInfo real_tag_info{};      NFP::NTAG215File tag_data{}; -    std::vector<u8> mifare_data{};      NFP::EncryptedNTAG215File encrypted_tag_data{};  }; diff --git a/src/core/hle/service/nfc/common/device_manager.cpp b/src/core/hle/service/nfc/common/device_manager.cpp index b0456508e..562f3a28e 100644 --- a/src/core/hle/service/nfc/common/device_manager.cpp +++ b/src/core/hle/service/nfc/common/device_manager.cpp @@ -29,6 +29,9 @@ DeviceManager::DeviceManager(Core::System& system_, KernelHelpers::ServiceContex  }  DeviceManager ::~DeviceManager() { +    if (is_initialized) { +        Finalize(); +    }      service_context.CloseEvent(availability_change_event);  } @@ -125,14 +128,14 @@ Result DeviceManager::StopDetection(u64 device_handle) {      return result;  } -Result DeviceManager::GetTagInfo(u64 device_handle, TagInfo& tag_info, bool is_mifare) const { +Result DeviceManager::GetTagInfo(u64 device_handle, TagInfo& tag_info) const {      std::scoped_lock lock{mutex};      std::shared_ptr<NfcDevice> device = nullptr;      auto result = GetDeviceHandle(device_handle, device);      if (result.IsSuccess()) { -        result = device->GetTagInfo(tag_info, is_mifare); +        result = device->GetTagInfo(tag_info);          result = VerifyDeviceResult(device, result);      } @@ -546,7 +549,7 @@ Result DeviceManager::ReadBackupData(u64 device_handle, std::span<u8> data) cons      NFC::TagInfo tag_info{};      if (result.IsSuccess()) { -        result = device->GetTagInfo(tag_info, false); +        result = device->GetTagInfo(tag_info);      }      if (result.IsSuccess()) { @@ -565,7 +568,7 @@ Result DeviceManager::WriteBackupData(u64 device_handle, std::span<const u8> dat      NFC::TagInfo tag_info{};      if (result.IsSuccess()) { -        result = device->GetTagInfo(tag_info, false); +        result = device->GetTagInfo(tag_info);      }      if (result.IsSuccess()) { diff --git a/src/core/hle/service/nfc/common/device_manager.h b/src/core/hle/service/nfc/common/device_manager.h index 2971e280f..c61ba0cf3 100644 --- a/src/core/hle/service/nfc/common/device_manager.h +++ b/src/core/hle/service/nfc/common/device_manager.h @@ -33,7 +33,7 @@ public:      Kernel::KReadableEvent& AttachAvailabilityChangeEvent() const;      Result StartDetection(u64 device_handle, NfcProtocol tag_protocol);      Result StopDetection(u64 device_handle); -    Result GetTagInfo(u64 device_handle, NFP::TagInfo& tag_info, bool is_mifare) const; +    Result GetTagInfo(u64 device_handle, NFP::TagInfo& tag_info) const;      Kernel::KReadableEvent& AttachActivateEvent(u64 device_handle) const;      Kernel::KReadableEvent& AttachDeactivateEvent(u64 device_handle) const;      Result ReadMifare(u64 device_handle, diff --git a/src/core/hle/service/nfc/mifare_types.h b/src/core/hle/service/nfc/mifare_types.h index 75b59f021..467937399 100644 --- a/src/core/hle/service/nfc/mifare_types.h +++ b/src/core/hle/service/nfc/mifare_types.h @@ -11,9 +11,10 @@  namespace Service::NFC {  enum class MifareCmd : u8 { +    None = 0x00, +    Read = 0x30,      AuthA = 0x60,      AuthB = 0x61, -    Read = 0x30,      Write = 0xA0,      Transfer = 0xB0,      Decrement = 0xC0, @@ -35,17 +36,17 @@ static_assert(sizeof(SectorKey) == 0x10, "SectorKey is an invalid size");  // This is nn::nfc::MifareReadBlockParameter  struct MifareReadBlockParameter { -    u8 sector_number; +    u8 sector_number{};      INSERT_PADDING_BYTES(0x7); -    SectorKey sector_key; +    SectorKey sector_key{};  };  static_assert(sizeof(MifareReadBlockParameter) == 0x18,                "MifareReadBlockParameter is an invalid size");  // This is nn::nfc::MifareReadBlockData  struct MifareReadBlockData { -    DataBlock data; -    u8 sector_number; +    DataBlock data{}; +    u8 sector_number{};      INSERT_PADDING_BYTES(0x7);  };  static_assert(sizeof(MifareReadBlockData) == 0x18, "MifareReadBlockData is an invalid size"); diff --git a/src/core/hle/service/nfc/nfc_interface.cpp b/src/core/hle/service/nfc/nfc_interface.cpp index 130fb7f78..e7ca7582e 100644 --- a/src/core/hle/service/nfc/nfc_interface.cpp +++ b/src/core/hle/service/nfc/nfc_interface.cpp @@ -174,8 +174,7 @@ void NfcInterface::GetTagInfo(HLERequestContext& ctx) {      LOG_INFO(Service_NFC, "called, device_handle={}", device_handle);      TagInfo tag_info{}; -    auto result = -        GetManager()->GetTagInfo(device_handle, tag_info, backend_type == BackendType::Mifare); +    auto result = GetManager()->GetTagInfo(device_handle, tag_info);      result = TranslateResultToServiceError(result);      if (result.IsSuccess()) { @@ -216,8 +215,8 @@ void NfcInterface::ReadMifare(HLERequestContext& ctx) {      memcpy(read_commands.data(), buffer.data(),             number_of_commands * sizeof(MifareReadBlockParameter)); -    LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, read_commands_size={}", -             device_handle, number_of_commands); +    LOG_INFO(Service_NFC, "called, device_handle={}, read_commands_size={}", device_handle, +             number_of_commands);      std::vector<MifareReadBlockData> out_data(number_of_commands);      auto result = GetManager()->ReadMifare(device_handle, read_commands, out_data); diff --git a/src/core/hle/service/nvdrv/devices/nvdevice.h b/src/core/hle/service/nvdrv/devices/nvdevice.h index ab1f30f9e..a04538d5d 100644 --- a/src/core/hle/service/nvdrv/devices/nvdevice.h +++ b/src/core/hle/service/nvdrv/devices/nvdevice.h @@ -34,7 +34,7 @@ public:       * @returns The result code of the ioctl.       */      virtual NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, -                            std::vector<u8>& output) = 0; +                            std::span<u8> output) = 0;      /**       * Handles an ioctl2 request. @@ -45,7 +45,7 @@ public:       * @returns The result code of the ioctl.       */      virtual NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, -                            std::span<const u8> inline_input, std::vector<u8>& output) = 0; +                            std::span<const u8> inline_input, std::span<u8> output) = 0;      /**       * Handles an ioctl3 request. @@ -56,7 +56,7 @@ public:       * @returns The result code of the ioctl.       */      virtual NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, -                            std::vector<u8>& output, std::vector<u8>& inline_output) = 0; +                            std::span<u8> output, std::span<u8> inline_output) = 0;      /**       * Called once a device is opened diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp index 5a5b2e305..05a43d8dc 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp @@ -18,19 +18,19 @@ nvdisp_disp0::nvdisp_disp0(Core::System& system_, NvCore::Container& core)  nvdisp_disp0::~nvdisp_disp0() = default;  NvResult nvdisp_disp0::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, -                              std::vector<u8>& output) { +                              std::span<u8> output) {      UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);      return NvResult::NotImplemented;  }  NvResult nvdisp_disp0::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, -                              std::span<const u8> inline_input, std::vector<u8>& output) { +                              std::span<const u8> inline_input, std::span<u8> output) {      UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);      return NvResult::NotImplemented;  }  NvResult nvdisp_disp0::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, -                              std::vector<u8>& output, std::vector<u8>& inline_output) { +                              std::span<u8> output, std::span<u8> inline_output) {      UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);      return NvResult::NotImplemented;  } @@ -51,8 +51,8 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, android::PixelFormat form                                                 stride, format, transform, crop_rect};      system.GPU().RequestSwapBuffers(&framebuffer, fences, num_fences); -    system.GetPerfStats().EndSystemFrame();      system.SpeedLimiter().DoSpeedLimiting(system.CoreTiming().GetGlobalTimeUs()); +    system.GetPerfStats().EndSystemFrame();      system.GetPerfStats().BeginSystemFrame();  } diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h index bcd0e3ed5..daee05fe8 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h @@ -26,11 +26,11 @@ public:      ~nvdisp_disp0() override;      NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, -                    std::vector<u8>& output) override; +                    std::span<u8> output) override;      NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, -                    std::span<const u8> inline_input, std::vector<u8>& output) override; -    NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output, -                    std::vector<u8>& inline_output) override; +                    std::span<const u8> inline_input, std::span<u8> output) override; +    NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, +                    std::span<u8> inline_output) override;      void OnOpen(DeviceFD fd) override;      void OnClose(DeviceFD fd) override; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp index 681bd0867..07e570a9f 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp @@ -28,7 +28,7 @@ nvhost_as_gpu::nvhost_as_gpu(Core::System& system_, Module& module_, NvCore::Con  nvhost_as_gpu::~nvhost_as_gpu() = default;  NvResult nvhost_as_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, -                               std::vector<u8>& output) { +                               std::span<u8> output) {      switch (command.group) {      case 'A':          switch (command.cmd) { @@ -61,13 +61,13 @@ NvResult nvhost_as_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> i  }  NvResult nvhost_as_gpu::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, -                               std::span<const u8> inline_input, std::vector<u8>& output) { +                               std::span<const u8> inline_input, std::span<u8> output) {      UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);      return NvResult::NotImplemented;  }  NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, -                               std::vector<u8>& output, std::vector<u8>& inline_output) { +                               std::span<u8> output, std::span<u8> inline_output) {      switch (command.group) {      case 'A':          switch (command.cmd) { @@ -87,7 +87,7 @@ NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> i  void nvhost_as_gpu::OnOpen(DeviceFD fd) {}  void nvhost_as_gpu::OnClose(DeviceFD fd) {} -NvResult nvhost_as_gpu::AllocAsEx(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::AllocAsEx(std::span<const u8> input, std::span<u8> output) {      IoctlAllocAsEx params{};      std::memcpy(¶ms, input.data(), input.size()); @@ -141,7 +141,7 @@ NvResult nvhost_as_gpu::AllocAsEx(std::span<const u8> input, std::vector<u8>& ou      return NvResult::Success;  } -NvResult nvhost_as_gpu::AllocateSpace(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::AllocateSpace(std::span<const u8> input, std::span<u8> output) {      IoctlAllocSpace params{};      std::memcpy(¶ms, input.data(), input.size()); @@ -220,7 +220,7 @@ void nvhost_as_gpu::FreeMappingLocked(u64 offset) {      mapping_map.erase(offset);  } -NvResult nvhost_as_gpu::FreeSpace(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::FreeSpace(std::span<const u8> input, std::span<u8> output) {      IoctlFreeSpace params{};      std::memcpy(¶ms, input.data(), input.size()); @@ -266,15 +266,14 @@ NvResult nvhost_as_gpu::FreeSpace(std::span<const u8> input, std::vector<u8>& ou      return NvResult::Success;  } -NvResult nvhost_as_gpu::Remap(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::Remap(std::span<const u8> input, std::span<u8> output) {      const auto num_entries = input.size() / sizeof(IoctlRemapEntry);      LOG_DEBUG(Service_NVDRV, "called, num_entries=0x{:X}", num_entries); -    std::vector<IoctlRemapEntry> entries(num_entries); -    std::memcpy(entries.data(), input.data(), input.size()); -      std::scoped_lock lock(mutex); +    entries.resize_destructive(num_entries); +    std::memcpy(entries.data(), input.data(), input.size());      if (!vm.initialised) {          return NvResult::BadValue; @@ -320,7 +319,7 @@ NvResult nvhost_as_gpu::Remap(std::span<const u8> input, std::vector<u8>& output      return NvResult::Success;  } -NvResult nvhost_as_gpu::MapBufferEx(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::MapBufferEx(std::span<const u8> input, std::span<u8> output) {      IoctlMapBufferEx params{};      std::memcpy(¶ms, input.data(), input.size()); @@ -424,7 +423,7 @@ NvResult nvhost_as_gpu::MapBufferEx(std::span<const u8> input, std::vector<u8>&      return NvResult::Success;  } -NvResult nvhost_as_gpu::UnmapBuffer(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::UnmapBuffer(std::span<const u8> input, std::span<u8> output) {      IoctlUnmapBuffer params{};      std::memcpy(¶ms, input.data(), input.size()); @@ -463,7 +462,7 @@ NvResult nvhost_as_gpu::UnmapBuffer(std::span<const u8> input, std::vector<u8>&      return NvResult::Success;  } -NvResult nvhost_as_gpu::BindChannel(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::BindChannel(std::span<const u8> input, std::span<u8> output) {      IoctlBindChannel params{};      std::memcpy(¶ms, input.data(), input.size());      LOG_DEBUG(Service_NVDRV, "called, fd={:X}", params.fd); @@ -492,7 +491,7 @@ void nvhost_as_gpu::GetVARegionsImpl(IoctlGetVaRegions& params) {      };  } -NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::span<u8> output) {      IoctlGetVaRegions params{};      std::memcpy(¶ms, input.data(), input.size()); @@ -511,8 +510,8 @@ NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::vector<u8>&      return NvResult::Success;  } -NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::vector<u8>& output, -                                     std::vector<u8>& inline_output) { +NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::span<u8> output, +                                     std::span<u8> inline_output) {      IoctlGetVaRegions params{};      std::memcpy(¶ms, input.data(), input.size()); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h index 1aba8d579..2af3e1260 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h @@ -15,6 +15,7 @@  #include "common/address_space.h"  #include "common/common_funcs.h"  #include "common/common_types.h" +#include "common/scratch_buffer.h"  #include "common/swap.h"  #include "core/hle/service/nvdrv/core/nvmap.h"  #include "core/hle/service/nvdrv/devices/nvdevice.h" @@ -48,11 +49,11 @@ public:      ~nvhost_as_gpu() override;      NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, -                    std::vector<u8>& output) override; +                    std::span<u8> output) override;      NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, -                    std::span<const u8> inline_input, std::vector<u8>& output) override; -    NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output, -                    std::vector<u8>& inline_output) override; +                    std::span<const u8> inline_input, std::span<u8> output) override; +    NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, +                    std::span<u8> inline_output) override;      void OnOpen(DeviceFD fd) override;      void OnClose(DeviceFD fd) override; @@ -138,18 +139,18 @@ private:      static_assert(sizeof(IoctlGetVaRegions) == 16 + sizeof(VaRegion) * 2,                    "IoctlGetVaRegions is incorrect size"); -    NvResult AllocAsEx(std::span<const u8> input, std::vector<u8>& output); -    NvResult AllocateSpace(std::span<const u8> input, std::vector<u8>& output); -    NvResult Remap(std::span<const u8> input, std::vector<u8>& output); -    NvResult MapBufferEx(std::span<const u8> input, std::vector<u8>& output); -    NvResult UnmapBuffer(std::span<const u8> input, std::vector<u8>& output); -    NvResult FreeSpace(std::span<const u8> input, std::vector<u8>& output); -    NvResult BindChannel(std::span<const u8> input, std::vector<u8>& output); +    NvResult AllocAsEx(std::span<const u8> input, std::span<u8> output); +    NvResult AllocateSpace(std::span<const u8> input, std::span<u8> output); +    NvResult Remap(std::span<const u8> input, std::span<u8> output); +    NvResult MapBufferEx(std::span<const u8> input, std::span<u8> output); +    NvResult UnmapBuffer(std::span<const u8> input, std::span<u8> output); +    NvResult FreeSpace(std::span<const u8> input, std::span<u8> output); +    NvResult BindChannel(std::span<const u8> input, std::span<u8> output);      void GetVARegionsImpl(IoctlGetVaRegions& params); -    NvResult GetVARegions(std::span<const u8> input, std::vector<u8>& output); -    NvResult GetVARegions(std::span<const u8> input, std::vector<u8>& output, -                          std::vector<u8>& inline_output); +    NvResult GetVARegions(std::span<const u8> input, std::span<u8> output); +    NvResult GetVARegions(std::span<const u8> input, std::span<u8> output, +                          std::span<u8> inline_output);      void FreeMappingLocked(u64 offset); @@ -212,6 +213,7 @@ private:          bool initialised{};      } vm;      std::shared_ptr<Tegra::MemoryManager> gmmu; +    Common::ScratchBuffer<IoctlRemapEntry> entries;      // s32 channel{};      // u32 big_page_size{VM::DEFAULT_BIG_PAGE_SIZE}; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index e12025560..4d55554b4 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp @@ -35,7 +35,7 @@ nvhost_ctrl::~nvhost_ctrl() {  }  NvResult nvhost_ctrl::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, -                             std::vector<u8>& output) { +                             std::span<u8> output) {      switch (command.group) {      case 0x0:          switch (command.cmd) { @@ -64,13 +64,13 @@ NvResult nvhost_ctrl::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inp  }  NvResult nvhost_ctrl::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, -                             std::span<const u8> inline_input, std::vector<u8>& output) { +                             std::span<const u8> inline_input, std::span<u8> output) {      UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);      return NvResult::NotImplemented;  }  NvResult nvhost_ctrl::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, -                             std::vector<u8>& output, std::vector<u8>& inline_outpu) { +                             std::span<u8> output, std::span<u8> inline_outpu) {      UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);      return NvResult::NotImplemented;  } @@ -79,7 +79,7 @@ void nvhost_ctrl::OnOpen(DeviceFD fd) {}  void nvhost_ctrl::OnClose(DeviceFD fd) {} -NvResult nvhost_ctrl::NvOsGetConfigU32(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_ctrl::NvOsGetConfigU32(std::span<const u8> input, std::span<u8> output) {      IocGetConfigParams params{};      std::memcpy(¶ms, input.data(), sizeof(params));      LOG_TRACE(Service_NVDRV, "called, setting={}!{}", params.domain_str.data(), @@ -87,7 +87,7 @@ NvResult nvhost_ctrl::NvOsGetConfigU32(std::span<const u8> input, std::vector<u8      return NvResult::ConfigVarNotFound; // Returns error on production mode  } -NvResult nvhost_ctrl::IocCtrlEventWait(std::span<const u8> input, std::vector<u8>& output, +NvResult nvhost_ctrl::IocCtrlEventWait(std::span<const u8> input, std::span<u8> output,                                         bool is_allocation) {      IocCtrlEventWaitParams params{};      std::memcpy(¶ms, input.data(), sizeof(params)); @@ -231,7 +231,7 @@ NvResult nvhost_ctrl::FreeEvent(u32 slot) {      return NvResult::Success;  } -NvResult nvhost_ctrl::IocCtrlEventRegister(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_ctrl::IocCtrlEventRegister(std::span<const u8> input, std::span<u8> output) {      IocCtrlEventRegisterParams params{};      std::memcpy(¶ms, input.data(), sizeof(params));      const u32 event_id = params.user_event_id; @@ -252,7 +252,7 @@ NvResult nvhost_ctrl::IocCtrlEventRegister(std::span<const u8> input, std::vecto      return NvResult::Success;  } -NvResult nvhost_ctrl::IocCtrlEventUnregister(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_ctrl::IocCtrlEventUnregister(std::span<const u8> input, std::span<u8> output) {      IocCtrlEventUnregisterParams params{};      std::memcpy(¶ms, input.data(), sizeof(params));      const u32 event_id = params.user_event_id & 0x00FF; @@ -262,8 +262,7 @@ NvResult nvhost_ctrl::IocCtrlEventUnregister(std::span<const u8> input, std::vec      return FreeEvent(event_id);  } -NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(std::span<const u8> input, -                                                  std::vector<u8>& output) { +NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(std::span<const u8> input, std::span<u8> output) {      IocCtrlEventUnregisterBatchParams params{};      std::memcpy(¶ms, input.data(), sizeof(params));      u64 event_mask = params.user_events; @@ -281,7 +280,7 @@ NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(std::span<const u8> input,      return NvResult::Success;  } -NvResult nvhost_ctrl::IocCtrlClearEventWait(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_ctrl::IocCtrlClearEventWait(std::span<const u8> input, std::span<u8> output) {      IocCtrlEventClearParams params{};      std::memcpy(¶ms, input.data(), sizeof(params)); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h index dd2e7888a..2efed4862 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h @@ -26,11 +26,11 @@ public:      ~nvhost_ctrl() override;      NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, -                    std::vector<u8>& output) override; +                    std::span<u8> output) override;      NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, -                    std::span<const u8> inline_input, std::vector<u8>& output) override; -    NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output, -                    std::vector<u8>& inline_output) override; +                    std::span<const u8> inline_input, std::span<u8> output) override; +    NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, +                    std::span<u8> inline_output) override;      void OnOpen(DeviceFD fd) override;      void OnClose(DeviceFD fd) override; @@ -186,13 +186,12 @@ private:      static_assert(sizeof(IocCtrlEventUnregisterBatchParams) == 8,                    "IocCtrlEventKill is incorrect size"); -    NvResult NvOsGetConfigU32(std::span<const u8> input, std::vector<u8>& output); -    NvResult IocCtrlEventWait(std::span<const u8> input, std::vector<u8>& output, -                              bool is_allocation); -    NvResult IocCtrlEventRegister(std::span<const u8> input, std::vector<u8>& output); -    NvResult IocCtrlEventUnregister(std::span<const u8> input, std::vector<u8>& output); -    NvResult IocCtrlEventUnregisterBatch(std::span<const u8> input, std::vector<u8>& output); -    NvResult IocCtrlClearEventWait(std::span<const u8> input, std::vector<u8>& output); +    NvResult NvOsGetConfigU32(std::span<const u8> input, std::span<u8> output); +    NvResult IocCtrlEventWait(std::span<const u8> input, std::span<u8> output, bool is_allocation); +    NvResult IocCtrlEventRegister(std::span<const u8> input, std::span<u8> output); +    NvResult IocCtrlEventUnregister(std::span<const u8> input, std::span<u8> output); +    NvResult IocCtrlEventUnregisterBatch(std::span<const u8> input, std::span<u8> output); +    NvResult IocCtrlClearEventWait(std::span<const u8> input, std::span<u8> output);      NvResult FreeEvent(u32 slot); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp index be3c083db..6081d92e9 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp @@ -22,7 +22,7 @@ nvhost_ctrl_gpu::~nvhost_ctrl_gpu() {  }  NvResult nvhost_ctrl_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, -                                 std::vector<u8>& output) { +                                 std::span<u8> output) {      switch (command.group) {      case 'G':          switch (command.cmd) { @@ -54,13 +54,13 @@ NvResult nvhost_ctrl_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8>  }  NvResult nvhost_ctrl_gpu::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, -                                 std::span<const u8> inline_input, std::vector<u8>& output) { +                                 std::span<const u8> inline_input, std::span<u8> output) {      UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);      return NvResult::NotImplemented;  }  NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, -                                 std::vector<u8>& output, std::vector<u8>& inline_output) { +                                 std::span<u8> output, std::span<u8> inline_output) {      switch (command.group) {      case 'G':          switch (command.cmd) { @@ -82,7 +82,7 @@ NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8>  void nvhost_ctrl_gpu::OnOpen(DeviceFD fd) {}  void nvhost_ctrl_gpu::OnClose(DeviceFD fd) {} -NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::span<u8> output) {      LOG_DEBUG(Service_NVDRV, "called");      IoctlCharacteristics params{};      std::memcpy(¶ms, input.data(), input.size()); @@ -127,8 +127,8 @@ NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::vec      return NvResult::Success;  } -NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::vector<u8>& output, -                                             std::vector<u8>& inline_output) { +NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::span<u8> output, +                                             std::span<u8> inline_output) {      LOG_DEBUG(Service_NVDRV, "called");      IoctlCharacteristics params{};      std::memcpy(¶ms, input.data(), input.size()); @@ -175,7 +175,7 @@ NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::vec      return NvResult::Success;  } -NvResult nvhost_ctrl_gpu::GetTPCMasks(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::GetTPCMasks(std::span<const u8> input, std::span<u8> output) {      IoctlGpuGetTpcMasksArgs params{};      std::memcpy(¶ms, input.data(), input.size());      LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size=0x{:X}", params.mask_buffer_size); @@ -186,8 +186,8 @@ NvResult nvhost_ctrl_gpu::GetTPCMasks(std::span<const u8> input, std::vector<u8>      return NvResult::Success;  } -NvResult nvhost_ctrl_gpu::GetTPCMasks(std::span<const u8> input, std::vector<u8>& output, -                                      std::vector<u8>& inline_output) { +NvResult nvhost_ctrl_gpu::GetTPCMasks(std::span<const u8> input, std::span<u8> output, +                                      std::span<u8> inline_output) {      IoctlGpuGetTpcMasksArgs params{};      std::memcpy(¶ms, input.data(), input.size());      LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size=0x{:X}", params.mask_buffer_size); @@ -199,7 +199,7 @@ NvResult nvhost_ctrl_gpu::GetTPCMasks(std::span<const u8> input, std::vector<u8>      return NvResult::Success;  } -NvResult nvhost_ctrl_gpu::GetActiveSlotMask(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::GetActiveSlotMask(std::span<const u8> input, std::span<u8> output) {      LOG_DEBUG(Service_NVDRV, "called");      IoctlActiveSlotMask params{}; @@ -212,7 +212,7 @@ NvResult nvhost_ctrl_gpu::GetActiveSlotMask(std::span<const u8> input, std::vect      return NvResult::Success;  } -NvResult nvhost_ctrl_gpu::ZCullGetCtxSize(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::ZCullGetCtxSize(std::span<const u8> input, std::span<u8> output) {      LOG_DEBUG(Service_NVDRV, "called");      IoctlZcullGetCtxSize params{}; @@ -224,7 +224,7 @@ NvResult nvhost_ctrl_gpu::ZCullGetCtxSize(std::span<const u8> input, std::vector      return NvResult::Success;  } -NvResult nvhost_ctrl_gpu::ZCullGetInfo(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::ZCullGetInfo(std::span<const u8> input, std::span<u8> output) {      LOG_DEBUG(Service_NVDRV, "called");      IoctlNvgpuGpuZcullGetInfoArgs params{}; @@ -247,7 +247,7 @@ NvResult nvhost_ctrl_gpu::ZCullGetInfo(std::span<const u8> input, std::vector<u8      return NvResult::Success;  } -NvResult nvhost_ctrl_gpu::ZBCSetTable(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::ZBCSetTable(std::span<const u8> input, std::span<u8> output) {      LOG_WARNING(Service_NVDRV, "(STUBBED) called");      IoctlZbcSetTable params{}; @@ -263,7 +263,7 @@ NvResult nvhost_ctrl_gpu::ZBCSetTable(std::span<const u8> input, std::vector<u8>      return NvResult::Success;  } -NvResult nvhost_ctrl_gpu::ZBCQueryTable(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::ZBCQueryTable(std::span<const u8> input, std::span<u8> output) {      LOG_WARNING(Service_NVDRV, "(STUBBED) called");      IoctlZbcQueryTable params{}; @@ -273,7 +273,7 @@ NvResult nvhost_ctrl_gpu::ZBCQueryTable(std::span<const u8> input, std::vector<u      return NvResult::Success;  } -NvResult nvhost_ctrl_gpu::FlushL2(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::FlushL2(std::span<const u8> input, std::span<u8> output) {      LOG_WARNING(Service_NVDRV, "(STUBBED) called");      IoctlFlushL2 params{}; @@ -283,7 +283,7 @@ NvResult nvhost_ctrl_gpu::FlushL2(std::span<const u8> input, std::vector<u8>& ou      return NvResult::Success;  } -NvResult nvhost_ctrl_gpu::GetGpuTime(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::GetGpuTime(std::span<const u8> input, std::span<u8> output) {      LOG_DEBUG(Service_NVDRV, "called");      IoctlGetGpuTime params{}; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h index b9333d9d3..97995551c 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h @@ -22,11 +22,11 @@ public:      ~nvhost_ctrl_gpu() override;      NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, -                    std::vector<u8>& output) override; +                    std::span<u8> output) override;      NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, -                    std::span<const u8> inline_input, std::vector<u8>& output) override; -    NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output, -                    std::vector<u8>& inline_output) override; +                    std::span<const u8> inline_input, std::span<u8> output) override; +    NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, +                    std::span<u8> inline_output) override;      void OnOpen(DeviceFD fd) override;      void OnClose(DeviceFD fd) override; @@ -151,21 +151,21 @@ private:      };      static_assert(sizeof(IoctlGetGpuTime) == 0x10, "IoctlGetGpuTime is incorrect size"); -    NvResult GetCharacteristics(std::span<const u8> input, std::vector<u8>& output); -    NvResult GetCharacteristics(std::span<const u8> input, std::vector<u8>& output, -                                std::vector<u8>& inline_output); - -    NvResult GetTPCMasks(std::span<const u8> input, std::vector<u8>& output); -    NvResult GetTPCMasks(std::span<const u8> input, std::vector<u8>& output, -                         std::vector<u8>& inline_output); - -    NvResult GetActiveSlotMask(std::span<const u8> input, std::vector<u8>& output); -    NvResult ZCullGetCtxSize(std::span<const u8> input, std::vector<u8>& output); -    NvResult ZCullGetInfo(std::span<const u8> input, std::vector<u8>& output); -    NvResult ZBCSetTable(std::span<const u8> input, std::vector<u8>& output); -    NvResult ZBCQueryTable(std::span<const u8> input, std::vector<u8>& output); -    NvResult FlushL2(std::span<const u8> input, std::vector<u8>& output); -    NvResult GetGpuTime(std::span<const u8> input, std::vector<u8>& output); +    NvResult GetCharacteristics(std::span<const u8> input, std::span<u8> output); +    NvResult GetCharacteristics(std::span<const u8> input, std::span<u8> output, +                                std::span<u8> inline_output); + +    NvResult GetTPCMasks(std::span<const u8> input, std::span<u8> output); +    NvResult GetTPCMasks(std::span<const u8> input, std::span<u8> output, +                         std::span<u8> inline_output); + +    NvResult GetActiveSlotMask(std::span<const u8> input, std::span<u8> output); +    NvResult ZCullGetCtxSize(std::span<const u8> input, std::span<u8> output); +    NvResult ZCullGetInfo(std::span<const u8> input, std::span<u8> output); +    NvResult ZBCSetTable(std::span<const u8> input, std::span<u8> output); +    NvResult ZBCQueryTable(std::span<const u8> input, std::span<u8> output); +    NvResult FlushL2(std::span<const u8> input, std::span<u8> output); +    NvResult GetGpuTime(std::span<const u8> input, std::span<u8> output);      EventInterface& events_interface; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index 453a965dc..46a25fcab 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp @@ -47,7 +47,7 @@ nvhost_gpu::~nvhost_gpu() {  }  NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, -                            std::vector<u8>& output) { +                            std::span<u8> output) {      switch (command.group) {      case 0x0:          switch (command.cmd) { @@ -99,7 +99,7 @@ NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu  };  NvResult nvhost_gpu::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, -                            std::span<const u8> inline_input, std::vector<u8>& output) { +                            std::span<const u8> inline_input, std::span<u8> output) {      switch (command.group) {      case 'H':          switch (command.cmd) { @@ -113,7 +113,7 @@ NvResult nvhost_gpu::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> inpu  }  NvResult nvhost_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, -                            std::vector<u8>& output, std::vector<u8>& inline_output) { +                            std::span<u8> output, std::span<u8> inline_output) {      UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);      return NvResult::NotImplemented;  } @@ -121,7 +121,7 @@ NvResult nvhost_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> inpu  void nvhost_gpu::OnOpen(DeviceFD fd) {}  void nvhost_gpu::OnClose(DeviceFD fd) {} -NvResult nvhost_gpu::SetNVMAPfd(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_gpu::SetNVMAPfd(std::span<const u8> input, std::span<u8> output) {      IoctlSetNvmapFD params{};      std::memcpy(¶ms, input.data(), input.size());      LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); @@ -130,7 +130,7 @@ NvResult nvhost_gpu::SetNVMAPfd(std::span<const u8> input, std::vector<u8>& outp      return NvResult::Success;  } -NvResult nvhost_gpu::SetClientData(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_gpu::SetClientData(std::span<const u8> input, std::span<u8> output) {      LOG_DEBUG(Service_NVDRV, "called");      IoctlClientData params{}; @@ -139,7 +139,7 @@ NvResult nvhost_gpu::SetClientData(std::span<const u8> input, std::vector<u8>& o      return NvResult::Success;  } -NvResult nvhost_gpu::GetClientData(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_gpu::GetClientData(std::span<const u8> input, std::span<u8> output) {      LOG_DEBUG(Service_NVDRV, "called");      IoctlClientData params{}; @@ -149,7 +149,7 @@ NvResult nvhost_gpu::GetClientData(std::span<const u8> input, std::vector<u8>& o      return NvResult::Success;  } -NvResult nvhost_gpu::ZCullBind(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_gpu::ZCullBind(std::span<const u8> input, std::span<u8> output) {      std::memcpy(&zcull_params, input.data(), input.size());      LOG_DEBUG(Service_NVDRV, "called, gpu_va={:X}, mode={:X}", zcull_params.gpu_va,                zcull_params.mode); @@ -158,7 +158,7 @@ NvResult nvhost_gpu::ZCullBind(std::span<const u8> input, std::vector<u8>& outpu      return NvResult::Success;  } -NvResult nvhost_gpu::SetErrorNotifier(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_gpu::SetErrorNotifier(std::span<const u8> input, std::span<u8> output) {      IoctlSetErrorNotifier params{};      std::memcpy(¶ms, input.data(), input.size());      LOG_WARNING(Service_NVDRV, "(STUBBED) called, offset={:X}, size={:X}, mem={:X}", params.offset, @@ -168,14 +168,14 @@ NvResult nvhost_gpu::SetErrorNotifier(std::span<const u8> input, std::vector<u8>      return NvResult::Success;  } -NvResult nvhost_gpu::SetChannelPriority(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_gpu::SetChannelPriority(std::span<const u8> input, std::span<u8> output) {      std::memcpy(&channel_priority, input.data(), input.size());      LOG_DEBUG(Service_NVDRV, "(STUBBED) called, priority={:X}", channel_priority);      return NvResult::Success;  } -NvResult nvhost_gpu::AllocGPFIFOEx2(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_gpu::AllocGPFIFOEx2(std::span<const u8> input, std::span<u8> output) {      IoctlAllocGpfifoEx2 params{};      std::memcpy(¶ms, input.data(), input.size());      LOG_WARNING(Service_NVDRV, @@ -197,7 +197,7 @@ NvResult nvhost_gpu::AllocGPFIFOEx2(std::span<const u8> input, std::vector<u8>&      return NvResult::Success;  } -NvResult nvhost_gpu::AllocateObjectContext(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_gpu::AllocateObjectContext(std::span<const u8> input, std::span<u8> output) {      IoctlAllocObjCtx params{};      std::memcpy(¶ms, input.data(), input.size());      LOG_WARNING(Service_NVDRV, "(STUBBED) called, class_num={:X}, flags={:X}", params.class_num, @@ -208,7 +208,8 @@ NvResult nvhost_gpu::AllocateObjectContext(std::span<const u8> input, std::vecto      return NvResult::Success;  } -static std::vector<Tegra::CommandHeader> BuildWaitCommandList(NvFence fence) { +static boost::container::small_vector<Tegra::CommandHeader, 512> BuildWaitCommandList( +    NvFence fence) {      return {          Tegra::BuildCommandHeader(Tegra::BufferMethods::SyncpointPayload, 1,                                    Tegra::SubmissionMode::Increasing), @@ -219,35 +220,35 @@ static std::vector<Tegra::CommandHeader> BuildWaitCommandList(NvFence fence) {      };  } -static std::vector<Tegra::CommandHeader> BuildIncrementCommandList(NvFence fence) { -    std::vector<Tegra::CommandHeader> result{ +static boost::container::small_vector<Tegra::CommandHeader, 512> BuildIncrementCommandList( +    NvFence fence) { +    boost::container::small_vector<Tegra::CommandHeader, 512> result{          Tegra::BuildCommandHeader(Tegra::BufferMethods::SyncpointPayload, 1,                                    Tegra::SubmissionMode::Increasing),          {}};      for (u32 count = 0; count < 2; ++count) { -        result.emplace_back(Tegra::BuildCommandHeader(Tegra::BufferMethods::SyncpointOperation, 1, -                                                      Tegra::SubmissionMode::Increasing)); -        result.emplace_back( +        result.push_back(Tegra::BuildCommandHeader(Tegra::BufferMethods::SyncpointOperation, 1, +                                                   Tegra::SubmissionMode::Increasing)); +        result.push_back(              BuildFenceAction(Tegra::Engines::Puller::FenceOperation::Increment, fence.id));      }      return result;  } -static std::vector<Tegra::CommandHeader> BuildIncrementWithWfiCommandList(NvFence fence) { -    std::vector<Tegra::CommandHeader> result{ +static boost::container::small_vector<Tegra::CommandHeader, 512> BuildIncrementWithWfiCommandList( +    NvFence fence) { +    boost::container::small_vector<Tegra::CommandHeader, 512> result{          Tegra::BuildCommandHeader(Tegra::BufferMethods::WaitForIdle, 1,                                    Tegra::SubmissionMode::Increasing),          {}}; -    const std::vector<Tegra::CommandHeader> increment{BuildIncrementCommandList(fence)}; - -    result.insert(result.end(), increment.begin(), increment.end()); - +    auto increment_list{BuildIncrementCommandList(fence)}; +    result.insert(result.end(), increment_list.begin(), increment_list.end());      return result;  } -NvResult nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::vector<u8>& output, +NvResult nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::span<u8> output,                                        Tegra::CommandList&& entries) {      LOG_TRACE(Service_NVDRV, "called, gpfifo={:X}, num_entries={:X}, flags={:X}", params.address,                params.num_entries, params.flags.raw); @@ -293,7 +294,7 @@ NvResult nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::vector<u8>      return NvResult::Success;  } -NvResult nvhost_gpu::SubmitGPFIFOBase(std::span<const u8> input, std::vector<u8>& output, +NvResult nvhost_gpu::SubmitGPFIFOBase(std::span<const u8> input, std::span<u8> output,                                        bool kickoff) {      if (input.size() < sizeof(IoctlSubmitGpfifo)) {          UNIMPLEMENTED(); @@ -315,7 +316,7 @@ NvResult nvhost_gpu::SubmitGPFIFOBase(std::span<const u8> input, std::vector<u8>  }  NvResult nvhost_gpu::SubmitGPFIFOBase(std::span<const u8> input, std::span<const u8> input_inline, -                                      std::vector<u8>& output) { +                                      std::span<u8> output) {      if (input.size() < sizeof(IoctlSubmitGpfifo)) {          UNIMPLEMENTED();          return NvResult::InvalidSize; @@ -327,7 +328,7 @@ NvResult nvhost_gpu::SubmitGPFIFOBase(std::span<const u8> input, std::span<const      return SubmitGPFIFOImpl(params, output, std::move(entries));  } -NvResult nvhost_gpu::GetWaitbase(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_gpu::GetWaitbase(std::span<const u8> input, std::span<u8> output) {      IoctlGetWaitbase params{};      std::memcpy(¶ms, input.data(), sizeof(IoctlGetWaitbase));      LOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown); @@ -337,7 +338,7 @@ NvResult nvhost_gpu::GetWaitbase(std::span<const u8> input, std::vector<u8>& out      return NvResult::Success;  } -NvResult nvhost_gpu::ChannelSetTimeout(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_gpu::ChannelSetTimeout(std::span<const u8> input, std::span<u8> output) {      IoctlChannelSetTimeout params{};      std::memcpy(¶ms, input.data(), sizeof(IoctlChannelSetTimeout));      LOG_INFO(Service_NVDRV, "called, timeout=0x{:X}", params.timeout); @@ -345,7 +346,7 @@ NvResult nvhost_gpu::ChannelSetTimeout(std::span<const u8> input, std::vector<u8      return NvResult::Success;  } -NvResult nvhost_gpu::ChannelSetTimeslice(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_gpu::ChannelSetTimeslice(std::span<const u8> input, std::span<u8> output) {      IoctlSetTimeslice params{};      std::memcpy(¶ms, input.data(), sizeof(IoctlSetTimeslice));      LOG_INFO(Service_NVDRV, "called, timeslice=0x{:X}", params.timeslice); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h index 3ca58202d..529c20526 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h @@ -41,11 +41,11 @@ public:      ~nvhost_gpu() override;      NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, -                    std::vector<u8>& output) override; +                    std::span<u8> output) override;      NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, -                    std::span<const u8> inline_input, std::vector<u8>& output) override; -    NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output, -                    std::vector<u8>& inline_output) override; +                    std::span<const u8> inline_input, std::span<u8> output) override; +    NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, +                    std::span<u8> inline_output) override;      void OnOpen(DeviceFD fd) override;      void OnClose(DeviceFD fd) override; @@ -186,23 +186,23 @@ private:      u32_le channel_priority{};      u32_le channel_timeslice{}; -    NvResult SetNVMAPfd(std::span<const u8> input, std::vector<u8>& output); -    NvResult SetClientData(std::span<const u8> input, std::vector<u8>& output); -    NvResult GetClientData(std::span<const u8> input, std::vector<u8>& output); -    NvResult ZCullBind(std::span<const u8> input, std::vector<u8>& output); -    NvResult SetErrorNotifier(std::span<const u8> input, std::vector<u8>& output); -    NvResult SetChannelPriority(std::span<const u8> input, std::vector<u8>& output); -    NvResult AllocGPFIFOEx2(std::span<const u8> input, std::vector<u8>& output); -    NvResult AllocateObjectContext(std::span<const u8> input, std::vector<u8>& output); -    NvResult SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::vector<u8>& output, +    NvResult SetNVMAPfd(std::span<const u8> input, std::span<u8> output); +    NvResult SetClientData(std::span<const u8> input, std::span<u8> output); +    NvResult GetClientData(std::span<const u8> input, std::span<u8> output); +    NvResult ZCullBind(std::span<const u8> input, std::span<u8> output); +    NvResult SetErrorNotifier(std::span<const u8> input, std::span<u8> output); +    NvResult SetChannelPriority(std::span<const u8> input, std::span<u8> output); +    NvResult AllocGPFIFOEx2(std::span<const u8> input, std::span<u8> output); +    NvResult AllocateObjectContext(std::span<const u8> input, std::span<u8> output); +    NvResult SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::span<u8> output,                                Tegra::CommandList&& entries); -    NvResult SubmitGPFIFOBase(std::span<const u8> input, std::vector<u8>& output, +    NvResult SubmitGPFIFOBase(std::span<const u8> input, std::span<u8> output,                                bool kickoff = false);      NvResult SubmitGPFIFOBase(std::span<const u8> input, std::span<const u8> input_inline, -                              std::vector<u8>& output); -    NvResult GetWaitbase(std::span<const u8> input, std::vector<u8>& output); -    NvResult ChannelSetTimeout(std::span<const u8> input, std::vector<u8>& output); -    NvResult ChannelSetTimeslice(std::span<const u8> input, std::vector<u8>& output); +                              std::span<u8> output); +    NvResult GetWaitbase(std::span<const u8> input, std::span<u8> output); +    NvResult ChannelSetTimeout(std::span<const u8> input, std::span<u8> output); +    NvResult ChannelSetTimeslice(std::span<const u8> input, std::span<u8> output);      EventInterface& events_interface;      NvCore::Container& core; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp index dc45169ad..a174442a6 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp @@ -16,7 +16,7 @@ nvhost_nvdec::nvhost_nvdec(Core::System& system_, NvCore::Container& core_)  nvhost_nvdec::~nvhost_nvdec() = default;  NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, -                              std::vector<u8>& output) { +                              std::span<u8> output) {      switch (command.group) {      case 0x0:          switch (command.cmd) { @@ -56,13 +56,13 @@ NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> in  }  NvResult nvhost_nvdec::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, -                              std::span<const u8> inline_input, std::vector<u8>& output) { +                              std::span<const u8> inline_input, std::span<u8> output) {      UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);      return NvResult::NotImplemented;  }  NvResult nvhost_nvdec::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, -                              std::vector<u8>& output, std::vector<u8>& inline_output) { +                              std::span<u8> output, std::span<u8> inline_output) {      UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);      return NvResult::NotImplemented;  } diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h index 0d615bbcb..ad2233c49 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h @@ -14,11 +14,11 @@ public:      ~nvhost_nvdec() override;      NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, -                    std::vector<u8>& output) override; +                    std::span<u8> output) override;      NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, -                    std::span<const u8> inline_input, std::vector<u8>& output) override; -    NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output, -                    std::vector<u8>& inline_output) override; +                    std::span<const u8> inline_input, std::span<u8> output) override; +    NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, +                    std::span<u8> inline_output) override;      void OnOpen(DeviceFD fd) override;      void OnClose(DeviceFD fd) override; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp index 1ab51f10b..61649aa4a 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp @@ -36,7 +36,7 @@ std::size_t SliceVectors(std::span<const u8> input, std::vector<T>& dst, std::si  // Writes the data in src to an offset into the dst vector. The offset is specified in bytes  // Returns the number of bytes written into dst.  template <typename T> -std::size_t WriteVectors(std::vector<u8>& dst, const std::vector<T>& src, std::size_t offset) { +std::size_t WriteVectors(std::span<u8> dst, const std::vector<T>& src, std::size_t offset) {      if (src.empty()) {          return 0;      } @@ -72,8 +72,7 @@ NvResult nvhost_nvdec_common::SetNVMAPfd(std::span<const u8> input) {      return NvResult::Success;  } -NvResult nvhost_nvdec_common::Submit(DeviceFD fd, std::span<const u8> input, -                                     std::vector<u8>& output) { +NvResult nvhost_nvdec_common::Submit(DeviceFD fd, std::span<const u8> input, std::span<u8> output) {      IoctlSubmit params{};      std::memcpy(¶ms, input.data(), sizeof(IoctlSubmit));      LOG_DEBUG(Service_NVDRV, "called NVDEC Submit, cmd_buffer_count={}", params.cmd_buffer_count); @@ -121,7 +120,7 @@ NvResult nvhost_nvdec_common::Submit(DeviceFD fd, std::span<const u8> input,      return NvResult::Success;  } -NvResult nvhost_nvdec_common::GetSyncpoint(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_nvdec_common::GetSyncpoint(std::span<const u8> input, std::span<u8> output) {      IoctlGetSyncpoint params{};      std::memcpy(¶ms, input.data(), sizeof(IoctlGetSyncpoint));      LOG_DEBUG(Service_NVDRV, "called GetSyncpoint, id={}", params.param); @@ -133,7 +132,7 @@ NvResult nvhost_nvdec_common::GetSyncpoint(std::span<const u8> input, std::vecto      return NvResult::Success;  } -NvResult nvhost_nvdec_common::GetWaitbase(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_nvdec_common::GetWaitbase(std::span<const u8> input, std::span<u8> output) {      IoctlGetWaitbase params{};      LOG_CRITICAL(Service_NVDRV, "called WAITBASE");      std::memcpy(¶ms, input.data(), sizeof(IoctlGetWaitbase)); @@ -142,7 +141,7 @@ NvResult nvhost_nvdec_common::GetWaitbase(std::span<const u8> input, std::vector      return NvResult::Success;  } -NvResult nvhost_nvdec_common::MapBuffer(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_nvdec_common::MapBuffer(std::span<const u8> input, std::span<u8> output) {      IoctlMapBuffer params{};      std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer));      std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); @@ -159,7 +158,7 @@ NvResult nvhost_nvdec_common::MapBuffer(std::span<const u8> input, std::vector<u      return NvResult::Success;  } -NvResult nvhost_nvdec_common::UnmapBuffer(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_nvdec_common::UnmapBuffer(std::span<const u8> input, std::span<u8> output) {      IoctlMapBuffer params{};      std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer));      std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); @@ -173,7 +172,7 @@ NvResult nvhost_nvdec_common::UnmapBuffer(std::span<const u8> input, std::vector      return NvResult::Success;  } -NvResult nvhost_nvdec_common::SetSubmitTimeout(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_nvdec_common::SetSubmitTimeout(std::span<const u8> input, std::span<u8> output) {      std::memcpy(&submit_timeout, input.data(), input.size());      LOG_WARNING(Service_NVDRV, "(STUBBED) called");      return NvResult::Success; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h index 5af26a26f..9bb573bfe 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h @@ -108,12 +108,12 @@ protected:      /// Ioctl command implementations      NvResult SetNVMAPfd(std::span<const u8> input); -    NvResult Submit(DeviceFD fd, std::span<const u8> input, std::vector<u8>& output); -    NvResult GetSyncpoint(std::span<const u8> input, std::vector<u8>& output); -    NvResult GetWaitbase(std::span<const u8> input, std::vector<u8>& output); -    NvResult MapBuffer(std::span<const u8> input, std::vector<u8>& output); -    NvResult UnmapBuffer(std::span<const u8> input, std::vector<u8>& output); -    NvResult SetSubmitTimeout(std::span<const u8> input, std::vector<u8>& output); +    NvResult Submit(DeviceFD fd, std::span<const u8> input, std::span<u8> output); +    NvResult GetSyncpoint(std::span<const u8> input, std::span<u8> output); +    NvResult GetWaitbase(std::span<const u8> input, std::span<u8> output); +    NvResult MapBuffer(std::span<const u8> input, std::span<u8> output); +    NvResult UnmapBuffer(std::span<const u8> input, std::span<u8> output); +    NvResult SetSubmitTimeout(std::span<const u8> input, std::span<u8> output);      Kernel::KEvent* QueryEvent(u32 event_id) override; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp index 39f30e7c8..a05c8cdae 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp @@ -13,7 +13,7 @@ nvhost_nvjpg::nvhost_nvjpg(Core::System& system_) : nvdevice{system_} {}  nvhost_nvjpg::~nvhost_nvjpg() = default;  NvResult nvhost_nvjpg::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, -                              std::vector<u8>& output) { +                              std::span<u8> output) {      switch (command.group) {      case 'H':          switch (command.cmd) { @@ -32,13 +32,13 @@ NvResult nvhost_nvjpg::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> in  }  NvResult nvhost_nvjpg::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, -                              std::span<const u8> inline_input, std::vector<u8>& output) { +                              std::span<const u8> inline_input, std::span<u8> output) {      UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);      return NvResult::NotImplemented;  }  NvResult nvhost_nvjpg::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, -                              std::vector<u8>& output, std::vector<u8>& inline_output) { +                              std::span<u8> output, std::span<u8> inline_output) {      UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);      return NvResult::NotImplemented;  } @@ -46,7 +46,7 @@ NvResult nvhost_nvjpg::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> in  void nvhost_nvjpg::OnOpen(DeviceFD fd) {}  void nvhost_nvjpg::OnClose(DeviceFD fd) {} -NvResult nvhost_nvjpg::SetNVMAPfd(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvhost_nvjpg::SetNVMAPfd(std::span<const u8> input, std::span<u8> output) {      IoctlSetNvmapFD params{};      std::memcpy(¶ms, input.data(), input.size());      LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h index 41b57e872..5623e0d47 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h @@ -16,11 +16,11 @@ public:      ~nvhost_nvjpg() override;      NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, -                    std::vector<u8>& output) override; +                    std::span<u8> output) override;      NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, -                    std::span<const u8> inline_input, std::vector<u8>& output) override; -    NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output, -                    std::vector<u8>& inline_output) override; +                    std::span<const u8> inline_input, std::span<u8> output) override; +    NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, +                    std::span<u8> inline_output) override;      void OnOpen(DeviceFD fd) override;      void OnClose(DeviceFD fd) override; @@ -33,7 +33,7 @@ private:      s32_le nvmap_fd{}; -    NvResult SetNVMAPfd(std::span<const u8> input, std::vector<u8>& output); +    NvResult SetNVMAPfd(std::span<const u8> input, std::span<u8> output);  };  } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp index b0ea402a7..c0b8684c3 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp @@ -16,7 +16,7 @@ nvhost_vic::nvhost_vic(Core::System& system_, NvCore::Container& core_)  nvhost_vic::~nvhost_vic() = default;  NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, -                            std::vector<u8>& output) { +                            std::span<u8> output) {      switch (command.group) {      case 0x0:          switch (command.cmd) { @@ -56,13 +56,13 @@ NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu  }  NvResult nvhost_vic::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, -                            std::span<const u8> inline_input, std::vector<u8>& output) { +                            std::span<const u8> inline_input, std::span<u8> output) {      UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);      return NvResult::NotImplemented;  }  NvResult nvhost_vic::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, -                            std::vector<u8>& output, std::vector<u8>& inline_output) { +                            std::span<u8> output, std::span<u8> inline_output) {      UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);      return NvResult::NotImplemented;  } diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.h b/src/core/hle/service/nvdrv/devices/nvhost_vic.h index b5e350a83..cadbcb0a5 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.h @@ -13,11 +13,11 @@ public:      ~nvhost_vic();      NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, -                    std::vector<u8>& output) override; +                    std::span<u8> output) override;      NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, -                    std::span<const u8> inline_input, std::vector<u8>& output) override; -    NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output, -                    std::vector<u8>& inline_output) override; +                    std::span<const u8> inline_input, std::span<u8> output) override; +    NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, +                    std::span<u8> inline_output) override;      void OnOpen(DeviceFD fd) override;      void OnClose(DeviceFD fd) override; diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp index 07417f045..e7f7e273b 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.cpp +++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp @@ -26,7 +26,7 @@ nvmap::nvmap(Core::System& system_, NvCore::Container& container_)  nvmap::~nvmap() = default;  NvResult nvmap::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, -                       std::vector<u8>& output) { +                       std::span<u8> output) {      switch (command.group) {      case 0x1:          switch (command.cmd) { @@ -55,13 +55,13 @@ NvResult nvmap::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,  }  NvResult nvmap::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, -                       std::span<const u8> inline_input, std::vector<u8>& output) { +                       std::span<const u8> inline_input, std::span<u8> output) {      UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);      return NvResult::NotImplemented;  } -NvResult nvmap::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, -                       std::vector<u8>& output, std::vector<u8>& inline_output) { +NvResult nvmap::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, +                       std::span<u8> inline_output) {      UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);      return NvResult::NotImplemented;  } @@ -69,7 +69,7 @@ NvResult nvmap::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,  void nvmap::OnOpen(DeviceFD fd) {}  void nvmap::OnClose(DeviceFD fd) {} -NvResult nvmap::IocCreate(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvmap::IocCreate(std::span<const u8> input, std::span<u8> output) {      IocCreateParams params;      std::memcpy(¶ms, input.data(), sizeof(params));      LOG_DEBUG(Service_NVDRV, "called, size=0x{:08X}", params.size); @@ -89,7 +89,7 @@ NvResult nvmap::IocCreate(std::span<const u8> input, std::vector<u8>& output) {      return NvResult::Success;  } -NvResult nvmap::IocAlloc(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvmap::IocAlloc(std::span<const u8> input, std::span<u8> output) {      IocAllocParams params;      std::memcpy(¶ms, input.data(), sizeof(params));      LOG_DEBUG(Service_NVDRV, "called, addr={:X}", params.address); @@ -137,7 +137,7 @@ NvResult nvmap::IocAlloc(std::span<const u8> input, std::vector<u8>& output) {      return result;  } -NvResult nvmap::IocGetId(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvmap::IocGetId(std::span<const u8> input, std::span<u8> output) {      IocGetIdParams params;      std::memcpy(¶ms, input.data(), sizeof(params)); @@ -161,7 +161,7 @@ NvResult nvmap::IocGetId(std::span<const u8> input, std::vector<u8>& output) {      return NvResult::Success;  } -NvResult nvmap::IocFromId(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvmap::IocFromId(std::span<const u8> input, std::span<u8> output) {      IocFromIdParams params;      std::memcpy(¶ms, input.data(), sizeof(params)); @@ -192,7 +192,7 @@ NvResult nvmap::IocFromId(std::span<const u8> input, std::vector<u8>& output) {      return NvResult::Success;  } -NvResult nvmap::IocParam(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvmap::IocParam(std::span<const u8> input, std::span<u8> output) {      enum class ParamTypes { Size = 1, Alignment = 2, Base = 3, Heap = 4, Kind = 5, Compr = 6 };      IocParamParams params; @@ -241,7 +241,7 @@ NvResult nvmap::IocParam(std::span<const u8> input, std::vector<u8>& output) {      return NvResult::Success;  } -NvResult nvmap::IocFree(std::span<const u8> input, std::vector<u8>& output) { +NvResult nvmap::IocFree(std::span<const u8> input, std::span<u8> output) {      IocFreeParams params;      std::memcpy(¶ms, input.data(), sizeof(params)); diff --git a/src/core/hle/service/nvdrv/devices/nvmap.h b/src/core/hle/service/nvdrv/devices/nvmap.h index 82bd3b118..40c65b430 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.h +++ b/src/core/hle/service/nvdrv/devices/nvmap.h @@ -27,11 +27,11 @@ public:      nvmap& operator=(const nvmap&) = delete;      NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, -                    std::vector<u8>& output) override; +                    std::span<u8> output) override;      NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, -                    std::span<const u8> inline_input, std::vector<u8>& output) override; -    NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output, -                    std::vector<u8>& inline_output) override; +                    std::span<const u8> inline_input, std::span<u8> output) override; +    NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, +                    std::span<u8> inline_output) override;      void OnOpen(DeviceFD fd) override;      void OnClose(DeviceFD fd) override; @@ -106,12 +106,12 @@ private:      };      static_assert(sizeof(IocGetIdParams) == 8, "IocGetIdParams has wrong size"); -    NvResult IocCreate(std::span<const u8> input, std::vector<u8>& output); -    NvResult IocAlloc(std::span<const u8> input, std::vector<u8>& output); -    NvResult IocGetId(std::span<const u8> input, std::vector<u8>& output); -    NvResult IocFromId(std::span<const u8> input, std::vector<u8>& output); -    NvResult IocParam(std::span<const u8> input, std::vector<u8>& output); -    NvResult IocFree(std::span<const u8> input, std::vector<u8>& output); +    NvResult IocCreate(std::span<const u8> input, std::span<u8> output); +    NvResult IocAlloc(std::span<const u8> input, std::span<u8> output); +    NvResult IocGetId(std::span<const u8> input, std::span<u8> output); +    NvResult IocFromId(std::span<const u8> input, std::span<u8> output); +    NvResult IocParam(std::span<const u8> input, std::span<u8> output); +    NvResult IocFree(std::span<const u8> input, std::span<u8> output);      NvCore::Container& container;      NvCore::NvMap& file; diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp index 3d774eec4..9e46ee8dd 100644 --- a/src/core/hle/service/nvdrv/nvdrv.cpp +++ b/src/core/hle/service/nvdrv/nvdrv.cpp @@ -130,7 +130,7 @@ DeviceFD Module::Open(const std::string& device_name) {  }  NvResult Module::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, -                        std::vector<u8>& output) { +                        std::span<u8> output) {      if (fd < 0) {          LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd);          return NvResult::InvalidState; @@ -147,7 +147,7 @@ NvResult Module::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,  }  NvResult Module::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, -                        std::span<const u8> inline_input, std::vector<u8>& output) { +                        std::span<const u8> inline_input, std::span<u8> output) {      if (fd < 0) {          LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd);          return NvResult::InvalidState; @@ -163,8 +163,8 @@ NvResult Module::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,      return itr->second->Ioctl2(fd, command, input, inline_input, output);  } -NvResult Module::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, -                        std::vector<u8>& output, std::vector<u8>& inline_output) { +NvResult Module::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, +                        std::span<u8> inline_output) {      if (fd < 0) {          LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd);          return NvResult::InvalidState; diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h index 668be742b..d8622b3ca 100644 --- a/src/core/hle/service/nvdrv/nvdrv.h +++ b/src/core/hle/service/nvdrv/nvdrv.h @@ -80,13 +80,13 @@ public:      DeviceFD Open(const std::string& device_name);      /// Sends an ioctl command to the specified file descriptor. -    NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output); +    NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output);      NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input, -                    std::span<const u8> inline_input, std::vector<u8>& output); +                    std::span<const u8> inline_input, std::span<u8> output); -    NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output, -                    std::vector<u8>& inline_output); +    NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, +                    std::span<u8> inline_output);      /// Closes a device file descriptor and returns operation success.      NvResult Close(DeviceFD fd); diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.cpp b/src/core/hle/service/nvdrv/nvdrv_interface.cpp index d010a1e03..348207e25 100644 --- a/src/core/hle/service/nvdrv/nvdrv_interface.cpp +++ b/src/core/hle/service/nvdrv/nvdrv_interface.cpp @@ -63,12 +63,12 @@ void NVDRV::Ioctl1(HLERequestContext& ctx) {      }      // Check device -    std::vector<u8> output_buffer(ctx.GetWriteBufferSize(0)); +    tmp_output.resize_destructive(ctx.GetWriteBufferSize(0));      const auto input_buffer = ctx.ReadBuffer(0); -    const auto nv_result = nvdrv->Ioctl1(fd, command, input_buffer, output_buffer); +    const auto nv_result = nvdrv->Ioctl1(fd, command, input_buffer, tmp_output);      if (command.is_out != 0) { -        ctx.WriteBuffer(output_buffer); +        ctx.WriteBuffer(tmp_output);      }      IPC::ResponseBuilder rb{ctx, 3}; @@ -90,12 +90,12 @@ void NVDRV::Ioctl2(HLERequestContext& ctx) {      const auto input_buffer = ctx.ReadBuffer(0);      const auto input_inlined_buffer = ctx.ReadBuffer(1); -    std::vector<u8> output_buffer(ctx.GetWriteBufferSize(0)); +    tmp_output.resize_destructive(ctx.GetWriteBufferSize(0));      const auto nv_result = -        nvdrv->Ioctl2(fd, command, input_buffer, input_inlined_buffer, output_buffer); +        nvdrv->Ioctl2(fd, command, input_buffer, input_inlined_buffer, tmp_output);      if (command.is_out != 0) { -        ctx.WriteBuffer(output_buffer); +        ctx.WriteBuffer(tmp_output);      }      IPC::ResponseBuilder rb{ctx, 3}; @@ -116,14 +116,12 @@ void NVDRV::Ioctl3(HLERequestContext& ctx) {      }      const auto input_buffer = ctx.ReadBuffer(0); -    std::vector<u8> output_buffer(ctx.GetWriteBufferSize(0)); -    std::vector<u8> output_buffer_inline(ctx.GetWriteBufferSize(1)); - -    const auto nv_result = -        nvdrv->Ioctl3(fd, command, input_buffer, output_buffer, output_buffer_inline); +    tmp_output.resize_destructive(ctx.GetWriteBufferSize(0)); +    tmp_output_inline.resize_destructive(ctx.GetWriteBufferSize(1)); +    const auto nv_result = nvdrv->Ioctl3(fd, command, input_buffer, tmp_output, tmp_output_inline);      if (command.is_out != 0) { -        ctx.WriteBuffer(output_buffer, 0); -        ctx.WriteBuffer(output_buffer_inline, 1); +        ctx.WriteBuffer(tmp_output, 0); +        ctx.WriteBuffer(tmp_output_inline, 1);      }      IPC::ResponseBuilder rb{ctx, 3}; diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.h b/src/core/hle/service/nvdrv/nvdrv_interface.h index 881ea1a6b..4b593ff90 100644 --- a/src/core/hle/service/nvdrv/nvdrv_interface.h +++ b/src/core/hle/service/nvdrv/nvdrv_interface.h @@ -4,6 +4,7 @@  #pragma once  #include <memory> +#include "common/scratch_buffer.h"  #include "core/hle/service/nvdrv/nvdrv.h"  #include "core/hle/service/service.h" @@ -33,6 +34,8 @@ private:      u64 pid{};      bool is_initialized{}; +    Common::ScratchBuffer<u8> tmp_output; +    Common::ScratchBuffer<u8> tmp_output_inline;  };  } // namespace Service::Nvidia diff --git a/src/core/hle/service/nvnflinger/nvnflinger.cpp b/src/core/hle/service/nvnflinger/nvnflinger.cpp index da2d5890f..5f55cd31e 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.cpp +++ b/src/core/hle/service/nvnflinger/nvnflinger.cpp @@ -43,14 +43,10 @@ void Nvnflinger::SplitVSync(std::stop_token stop_token) {      Common::SetCurrentThreadPriority(Common::ThreadPriority::High);      while (!stop_token.stop_requested()) { -        vsync_signal.wait(false); -        vsync_signal.store(false); - -        guard->lock(); +        vsync_signal.Wait(); +        const auto lock_guard = Lock();          Compose(); - -        guard->unlock();      }  } @@ -69,8 +65,8 @@ Nvnflinger::Nvnflinger(Core::System& system_, HosBinderDriverServer& hos_binder_          "ScreenComposition",          [this](std::uintptr_t, s64 time,                 std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { -            vsync_signal.store(true); -            vsync_signal.notify_all(); +            { const auto lock_guard = Lock(); } +            vsync_signal.Set();              return std::chrono::nanoseconds(GetNextTicks());          }); @@ -96,8 +92,7 @@ Nvnflinger::~Nvnflinger() {      if (system.IsMulticore()) {          system.CoreTiming().UnscheduleEvent(multi_composition_event, {});          vsync_thread.request_stop(); -        vsync_signal.store(true); -        vsync_signal.notify_all(); +        vsync_signal.Set();      } else {          system.CoreTiming().UnscheduleEvent(single_composition_event, {});      } diff --git a/src/core/hle/service/nvnflinger/nvnflinger.h b/src/core/hle/service/nvnflinger/nvnflinger.h index a043cceb2..ef236303a 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.h +++ b/src/core/hle/service/nvnflinger/nvnflinger.h @@ -12,6 +12,7 @@  #include "common/common_types.h"  #include "common/polyfill_thread.h" +#include "common/thread.h"  #include "core/hle/result.h"  #include "core/hle/service/kernel_helpers.h" @@ -143,7 +144,7 @@ private:      Core::System& system; -    std::atomic<bool> vsync_signal; +    Common::Event vsync_signal;      std::jthread vsync_thread; diff --git a/src/core/hle/service/nvnflinger/parcel.h b/src/core/hle/service/nvnflinger/parcel.h index fb56d75d7..23ba315a0 100644 --- a/src/core/hle/service/nvnflinger/parcel.h +++ b/src/core/hle/service/nvnflinger/parcel.h @@ -6,6 +6,7 @@  #include <memory>  #include <span>  #include <vector> +#include <boost/container/small_vector.hpp>  #include "common/alignment.h"  #include "common/assert.h" @@ -167,7 +168,7 @@ public:  private:      template <typename T>          requires(std::is_trivially_copyable_v<T>) -    void WriteImpl(const T& val, std::vector<u8>& buffer) { +    void WriteImpl(const T& val, boost::container::small_vector<u8, 0x200>& buffer) {          const size_t aligned_size = Common::AlignUp(sizeof(T), 4);          const size_t old_size = buffer.size();          buffer.resize(old_size + aligned_size); @@ -176,8 +177,8 @@ private:      }  private: -    std::vector<u8> m_data_buffer; -    std::vector<u8> m_object_buffer; +    boost::container::small_vector<u8, 0x200> m_data_buffer; +    boost::container::small_vector<u8, 0x200> m_object_buffer;  };  } // namespace Service::android diff --git a/src/core/hle/service/server_manager.cpp b/src/core/hle/service/server_manager.cpp index 156bc27d8..d1e99b184 100644 --- a/src/core/hle/service/server_manager.cpp +++ b/src/core/hle/service/server_manager.cpp @@ -44,7 +44,7 @@ ServerManager::~ServerManager() {      m_event->Signal();      // Wait for processing to stop. -    m_stopped.wait(false); +    m_stopped.Wait();      m_threads.clear();      // Clean up ports. @@ -182,10 +182,7 @@ void ServerManager::StartAdditionalHostThreads(const char* name, size_t num_thre  }  Result ServerManager::LoopProcess() { -    SCOPE_EXIT({ -        m_stopped.store(true); -        m_stopped.notify_all(); -    }); +    SCOPE_EXIT({ m_stopped.Set(); });      R_RETURN(this->LoopProcessImpl());  } diff --git a/src/core/hle/service/server_manager.h b/src/core/hle/service/server_manager.h index fdb8af2ff..58b0a0832 100644 --- a/src/core/hle/service/server_manager.h +++ b/src/core/hle/service/server_manager.h @@ -3,7 +3,6 @@  #pragma once -#include <atomic>  #include <functional>  #include <list>  #include <map> @@ -12,6 +11,7 @@  #include <vector>  #include "common/polyfill_thread.h" +#include "common/thread.h"  #include "core/hle/result.h"  #include "core/hle/service/mutex.h" @@ -82,7 +82,7 @@ private:      std::list<RequestState> m_deferrals{};      // Host state tracking -    std::atomic<bool> m_stopped{}; +    Common::Event m_stopped{};      std::vector<std::jthread> m_threads{};      std::stop_source m_stop_source{};  }; diff --git a/src/core/hle/service/time/clock_types.h b/src/core/hle/service/time/clock_types.h index e6293ffb9..9fc01ea90 100644 --- a/src/core/hle/service/time/clock_types.h +++ b/src/core/hle/service/time/clock_types.h @@ -3,6 +3,8 @@  #pragma once +#include <ratio> +  #include "common/common_funcs.h"  #include "common/common_types.h"  #include "common/uuid.h" @@ -74,18 +76,19 @@ static_assert(std::is_trivially_copyable_v<ContinuousAdjustmentTimePoint>,  /// https://switchbrew.org/wiki/Glue_services#TimeSpanType  struct TimeSpanType {      s64 nanoseconds{}; -    static constexpr s64 ns_per_second{1000000000ULL};      s64 ToSeconds() const { -        return nanoseconds / ns_per_second; +        return nanoseconds / std::nano::den;      }      static TimeSpanType FromSeconds(s64 seconds) { -        return {seconds * ns_per_second}; +        return {seconds * std::nano::den};      } -    static TimeSpanType FromTicks(u64 ticks, u64 frequency) { -        return FromSeconds(static_cast<s64>(ticks) / static_cast<s64>(frequency)); +    template <u64 Frequency> +    static TimeSpanType FromTicks(u64 ticks) { +        using TicksToNSRatio = std::ratio<std::nano::den, Frequency>; +        return {static_cast<s64>(ticks * TicksToNSRatio::num / TicksToNSRatio::den)};      }  };  static_assert(sizeof(TimeSpanType) == 8, "TimeSpanType is incorrect size"); diff --git a/src/core/hle/service/time/standard_steady_clock_core.cpp b/src/core/hle/service/time/standard_steady_clock_core.cpp index 3dbbb9850..5627b7003 100644 --- a/src/core/hle/service/time/standard_steady_clock_core.cpp +++ b/src/core/hle/service/time/standard_steady_clock_core.cpp @@ -10,7 +10,7 @@ namespace Service::Time::Clock {  TimeSpanType StandardSteadyClockCore::GetCurrentRawTimePoint(Core::System& system) {      const TimeSpanType ticks_time_span{ -        TimeSpanType::FromTicks(system.CoreTiming().GetClockTicks(), Core::Hardware::CNTFREQ)}; +        TimeSpanType::FromTicks<Core::Hardware::CNTFREQ>(system.CoreTiming().GetClockTicks())};      TimeSpanType raw_time_point{setup_value.nanoseconds + ticks_time_span.nanoseconds};      if (raw_time_point.nanoseconds < cached_raw_time_point.nanoseconds) { diff --git a/src/core/hle/service/time/tick_based_steady_clock_core.cpp b/src/core/hle/service/time/tick_based_steady_clock_core.cpp index 27600413e..0d9fb3143 100644 --- a/src/core/hle/service/time/tick_based_steady_clock_core.cpp +++ b/src/core/hle/service/time/tick_based_steady_clock_core.cpp @@ -10,7 +10,7 @@ namespace Service::Time::Clock {  SteadyClockTimePoint TickBasedSteadyClockCore::GetTimePoint(Core::System& system) {      const TimeSpanType ticks_time_span{ -        TimeSpanType::FromTicks(system.CoreTiming().GetClockTicks(), Core::Hardware::CNTFREQ)}; +        TimeSpanType::FromTicks<Core::Hardware::CNTFREQ>(system.CoreTiming().GetClockTicks())};      return {ticks_time_span.ToSeconds(), GetClockSourceId()};  } diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp index 868be60c5..7197ca30f 100644 --- a/src/core/hle/service/time/time.cpp +++ b/src/core/hle/service/time/time.cpp @@ -240,8 +240,8 @@ void Module::Interface::CalculateMonotonicSystemClockBaseTimePoint(HLERequestCon      const auto current_time_point{steady_clock_core.GetCurrentTimePoint(system)};      if (current_time_point.clock_source_id == context.steady_time_point.clock_source_id) { -        const auto ticks{Clock::TimeSpanType::FromTicks(system.CoreTiming().GetClockTicks(), -                                                        Core::Hardware::CNTFREQ)}; +        const auto ticks{Clock::TimeSpanType::FromTicks<Core::Hardware::CNTFREQ>( +            system.CoreTiming().GetClockTicks())};          const s64 base_time_point{context.offset + current_time_point.time_point -                                    ticks.ToSeconds()};          IPC::ResponseBuilder rb{ctx, (sizeof(s64) / 4) + 2}; diff --git a/src/core/hle/service/time/time_sharedmemory.cpp b/src/core/hle/service/time/time_sharedmemory.cpp index ce1c85bcc..a00676669 100644 --- a/src/core/hle/service/time/time_sharedmemory.cpp +++ b/src/core/hle/service/time/time_sharedmemory.cpp @@ -21,8 +21,9 @@ SharedMemory::~SharedMemory() = default;  void SharedMemory::SetupStandardSteadyClock(const Common::UUID& clock_source_id,                                              Clock::TimeSpanType current_time_point) { -    const Clock::TimeSpanType ticks_time_span{Clock::TimeSpanType::FromTicks( -        system.CoreTiming().GetClockTicks(), Core::Hardware::CNTFREQ)}; +    const Clock::TimeSpanType ticks_time_span{ +        Clock::TimeSpanType::FromTicks<Core::Hardware::CNTFREQ>( +            system.CoreTiming().GetClockTicks())};      const Clock::SteadyClockContext context{          static_cast<u64>(current_time_point.nanoseconds - ticks_time_span.nanoseconds),          clock_source_id}; diff --git a/src/core/hle/service/time/time_zone_manager.cpp b/src/core/hle/service/time/time_zone_manager.cpp index 63aacd19f..205371a26 100644 --- a/src/core/hle/service/time/time_zone_manager.cpp +++ b/src/core/hle/service/time/time_zone_manager.cpp @@ -911,9 +911,13 @@ static Result ToCalendarTimeInternal(const TimeZoneRule& rules, s64 time,      calendar_additional_info.is_dst = rules.ttis[tti_index].is_dst;      const char* time_zone{&rules.chars[rules.ttis[tti_index].abbreviation_list_index]}; -    for (int index{}; time_zone[index] != '\0'; ++index) { +    u32 index; +    for (index = 0; time_zone[index] != '\0' && time_zone[index] != ',' && +                    index < calendar_additional_info.timezone_name.size() - 1; +         ++index) {          calendar_additional_info.timezone_name[index] = time_zone[index];      } +    calendar_additional_info.timezone_name[index] = '\0';      return ResultSuccess;  }  | 
