Merge remote-tracking branch 'origin/master' into ssl

This commit is contained in:
comex 2023-07-01 15:01:11 -07:00
commit 98685d48e3
300 changed files with 24064 additions and 17224 deletions

View file

@ -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

View file

@ -322,11 +322,6 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
}
}
#ifdef ARCHITECTURE_arm64
// TODO: remove when fixed in dynarmic
config.optimizations &= ~Dynarmic::OptimizationFlag::BlockLinking;
#endif
return std::make_unique<Dynarmic::A32::Jit>(config);
}

View file

@ -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 {
if (is_multicore) [[likely]] {
return cpu_clock->GetCPUCycles();
}
return ticks;
}
u64 CoreTiming::GetClockTicks() const {
if (is_multicore) [[likely]] {
return cpu_clock->GetClockCycles();
return clock->GetCNTPCT();
}
return CpuCyclesToClockCycles(ticks);
return Common::WallClock::CPUTickToCNTPCT(cpu_ticks);
}
u64 CoreTiming::GetGPUTicks() const {
if (is_multicore) [[likely]] {
return clock->GetGPUTick();
}
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

View file

@ -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{};
};

View file

@ -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

View file

@ -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");

View file

@ -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;

View file

@ -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;
};

View file

@ -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;
};

View file

@ -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) {
@ -1249,6 +1250,11 @@ Common::Input::DriverResult EmulatedController::SetPollingMode(
const auto virtual_nfc_result = nfc_output_device->SetPollingMode(polling_mode);
const auto mapped_nfc_result = right_output_device->SetPollingMode(polling_mode);
// Restore previous state
if (mapped_nfc_result != Common::Input::DriverResult::Success) {
right_output_device->SetPollingMode(Common::Input::PollingMode::Active);
}
if (virtual_nfc_result == Common::Input::DriverResult::Success) {
return virtual_nfc_result;
}
@ -1308,6 +1314,79 @@ 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];
const auto device_result = nfc_output_device->StartNfcPolling();
const auto virtual_device_result = nfc_virtual_output_device->StartNfcPolling();
return device_result == Common::Input::NfcState::Success ||
virtual_device_result == 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];
const auto device_result = nfc_output_device->StopNfcPolling();
const auto virtual_device_result = nfc_virtual_output_device->StopNfcPolling();
return device_result == Common::Input::NfcState::Success ||
virtual_device_result == 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];

View file

@ -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};

View file

@ -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;

View file

@ -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) {

View file

@ -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);

View file

@ -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));
}
}

View file

@ -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);

View file

@ -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;

View file

@ -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);
}

View file

@ -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));

View file

@ -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.

View file

@ -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) {

View file

@ -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()) {

View file

@ -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_)

View file

@ -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_)

View file

@ -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> {

View file

@ -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"

View file

@ -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> {

View file

@ -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"

View file

@ -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};
tag_info = real_tag_info;
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);
// 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),
};

View file

@ -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{};
};

View file

@ -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()) {

View file

@ -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,

View file

@ -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");

View file

@ -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);

View file

@ -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

View file

@ -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();
}

View file

@ -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;

View file

@ -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(&params, 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(&params, 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(&params, 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(&params, 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(&params, 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(&params, 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(&params, 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(&params, input.data(), input.size());

View file

@ -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};

View file

@ -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(&params, 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(&params, 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(&params, 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(&params, 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(&params, 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(&params, input.data(), sizeof(params));

View file

@ -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);

View file

@ -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(&params, 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(&params, 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(&params, 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(&params, 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{};

View file

@ -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 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::vector<u8>& output);
NvResult GetTPCMasks(std::span<const u8> input, std::vector<u8>& output,
std::vector<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::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 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;

View file

@ -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(&params, 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(&params, 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(&params, 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(&params, 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(&params, 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(&params, 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(&params, input.data(), sizeof(IoctlSetTimeslice));
LOG_INFO(Service_NVDRV, "called, timeslice=0x{:X}", params.timeslice);

View file

@ -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;

View file

@ -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;
}

View file

@ -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;

View file

@ -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(&params, 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(&params, 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(&params, 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(&params, 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(&params, 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;

View file

@ -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;

View file

@ -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(&params, input.data(), input.size());
LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);

View file

@ -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

View file

@ -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;
}

View file

@ -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;

View file

@ -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(&params, 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(&params, 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(&params, 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(&params, 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(&params, input.data(), sizeof(params));

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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};

View file

@ -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

View file

@ -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, {});
}

View file

@ -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;

View file

@ -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

View file

@ -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());
}

View file

@ -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{};
};

View file

@ -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");

View file

@ -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) {

View file

@ -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()};
}

View file

@ -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};

View file

@ -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};

View file

@ -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;
}