early-access version 3351

This commit is contained in:
pineappleEA 2023-01-30 03:12:20 +01:00
parent 6a214ce067
commit 3ee566278a
94 changed files with 990 additions and 574 deletions

View file

@ -1,7 +1,7 @@
yuzu emulator early access yuzu emulator early access
============= =============
This is the source code for early-access 3350. This is the source code for early-access 3351.
## Legal Notice ## Legal Notice

BIN
dist/yuzu.ico vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 25 KiB

2
dist/yuzu.svg vendored
View file

@ -1 +1 @@
<svg id="svg815" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 614.4 682.67"><defs><style>.cls-1{fill:none;}.cls-2{clip-path:url(#clip-path);}.cls-3{fill:#ff3c28;}.cls-4{fill:#0ab9e6;}</style><clipPath id="clip-path"><rect class="cls-1" x="-43" y="-46.67" width="699.6" height="777.33"/></clipPath></defs><title>Artboard 1</title><g id="g823"><g id="right"><g class="cls-2"><g id="g827"><g id="g833"><path id="path835" class="cls-3" d="M340.81,138V682.08c150.26,0,272.06-121.81,272.06-272.06S491.07,138,340.81,138M394,197.55a219.06,219.06,0,0,1,0,424.94V197.55"/></g></g></g></g><g id="left"><g class="cls-2"><g id="g839"><g id="g845"><path id="path847" class="cls-4" d="M272.79,1.92C122.53,1.92.73,123.73.73,274s121.8,272.07,272.06,272.07ZM219.65,61.51v425A219,219,0,0,1,118,119.18,217.51,217.51,0,0,1,219.65,61.51"/></g></g></g></g></g></svg> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 612.15 680.17"><defs><style>.cls-1{fill:#c6c6c6;}.cls-2{fill:#ffdc00;}</style></defs><title>newAsset 7</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><g id="g823"><g id="right"><g id="g827"><g id="g833"><path id="path835" class="cls-1" d="M340.08,136V680.17c150.26,0,272.07-121.81,272.07-272.07S490.34,136,340.08,136m53.14,59.6a219.06,219.06,0,0,1,0,424.94V195.63"/></g></g></g><g id="left"><g id="g839"><g id="g845"><path id="path847" class="cls-2" d="M272.07,0C121.81,0,0,121.81,0,272.07S121.81,544.13,272.07,544.13ZM218.93,59.6V484.54A219,219,0,0,1,117.26,117.26,217.44,217.44,0,0,1,218.93,59.6"/></g></g></g></g></g></g></svg>

Before

Width:  |  Height:  |  Size: 889 B

After

Width:  |  Height:  |  Size: 717 B

View file

@ -130,6 +130,8 @@ struct ButtonStatus {
bool inverted{}; bool inverted{};
// Press once to activate, press again to release // Press once to activate, press again to release
bool toggle{}; bool toggle{};
// Spams the button when active
bool turbo{};
// Internal lock for the toggle status // Internal lock for the toggle status
bool locked{}; bool locked{};
}; };

View file

@ -30,7 +30,7 @@ std::string ToUpper(std::string str) {
return str; return str;
} }
std::string StringFromBuffer(const std::vector<u8>& data) { std::string StringFromBuffer(std::span<const u8> data) {
return std::string(data.begin(), std::find(data.begin(), data.end(), '\0')); return std::string(data.begin(), std::find(data.begin(), data.end(), '\0'));
} }

View file

@ -5,6 +5,7 @@
#pragma once #pragma once
#include <cstddef> #include <cstddef>
#include <span>
#include <string> #include <string>
#include <vector> #include <vector>
#include "common/common_types.h" #include "common/common_types.h"
@ -17,7 +18,7 @@ namespace Common {
/// Make a string uppercase /// Make a string uppercase
[[nodiscard]] std::string ToUpper(std::string str); [[nodiscard]] std::string ToUpper(std::string str);
[[nodiscard]] std::string StringFromBuffer(const std::vector<u8>& data); [[nodiscard]] std::string StringFromBuffer(std::span<const u8> data);
[[nodiscard]] std::string StripSpaces(const std::string& s); [[nodiscard]] std::string StripSpaces(const std::string& s);
[[nodiscard]] std::string StripQuotes(const std::string& s); [[nodiscard]] std::string StripQuotes(const std::string& s);

View file

@ -182,6 +182,8 @@ add_library(core STATIC
hle/kernel/k_auto_object_container.cpp hle/kernel/k_auto_object_container.cpp
hle/kernel/k_auto_object_container.h hle/kernel/k_auto_object_container.h
hle/kernel/k_affinity_mask.h hle/kernel/k_affinity_mask.h
hle/kernel/k_capabilities.cpp
hle/kernel/k_capabilities.h
hle/kernel/k_class_token.cpp hle/kernel/k_class_token.cpp
hle/kernel/k_class_token.h hle/kernel/k_class_token.h
hle/kernel/k_client_port.cpp hle/kernel/k_client_port.cpp

View file

@ -25,6 +25,26 @@ constexpr std::array<s32, Common::BitSize<u64>()> VirtualToPhysicalCoreMap{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
}; };
static constexpr inline size_t NumVirtualCores = Common::BitSize<u64>();
static constexpr inline u64 VirtualCoreMask = [] {
u64 mask = 0;
for (size_t i = 0; i < NumVirtualCores; ++i) {
mask |= (UINT64_C(1) << i);
}
return mask;
}();
static constexpr inline u64 ConvertVirtualCoreMaskToPhysical(u64 v_core_mask) {
u64 p_core_mask = 0;
while (v_core_mask != 0) {
const u64 next = std::countr_zero(v_core_mask);
v_core_mask &= ~(static_cast<u64>(1) << next);
p_core_mask |= (static_cast<u64>(1) << VirtualToPhysicalCoreMap[next]);
}
return p_core_mask;
}
// Cortex-A57 supports 4 memory watchpoints // Cortex-A57 supports 4 memory watchpoints
constexpr u64 NUM_WATCHPOINTS = 4; constexpr u64 NUM_WATCHPOINTS = 4;

View file

@ -687,6 +687,7 @@ void EmulatedController::SetButton(const Common::Input::CallbackStatus& callback
} }
current_status.toggle = new_status.toggle; current_status.toggle = new_status.toggle;
current_status.turbo = new_status.turbo;
current_status.uuid = uuid; current_status.uuid = uuid;
// Update button status with current // Update button status with current
@ -1548,7 +1549,7 @@ NpadButtonState EmulatedController::GetNpadButtons() const {
if (is_configuring) { if (is_configuring) {
return {}; return {};
} }
return controller.npad_button_state; return {controller.npad_button_state.raw & GetTurboButtonMask()};
} }
DebugPadButton EmulatedController::GetDebugPadButtons() const { DebugPadButton EmulatedController::GetDebugPadButtons() const {
@ -1656,4 +1657,74 @@ void EmulatedController::DeleteCallback(int key) {
} }
callback_list.erase(iterator); callback_list.erase(iterator);
} }
void EmulatedController::TurboButtonUpdate() {
turbo_button_state = !turbo_button_state;
}
NpadButton EmulatedController::GetTurboButtonMask() const {
// Apply no mask when disabled
if (!turbo_button_state) {
return {NpadButton::All};
}
NpadButtonState button_mask{};
for (std::size_t index = 0; index < controller.button_values.size(); ++index) {
if (!controller.button_values[index].turbo) {
continue;
}
switch (index) {
case Settings::NativeButton::A:
button_mask.a.Assign(1);
break;
case Settings::NativeButton::B:
button_mask.b.Assign(1);
break;
case Settings::NativeButton::X:
button_mask.x.Assign(1);
break;
case Settings::NativeButton::Y:
button_mask.y.Assign(1);
break;
case Settings::NativeButton::L:
button_mask.l.Assign(1);
break;
case Settings::NativeButton::R:
button_mask.r.Assign(1);
break;
case Settings::NativeButton::ZL:
button_mask.zl.Assign(1);
break;
case Settings::NativeButton::ZR:
button_mask.zr.Assign(1);
break;
case Settings::NativeButton::DLeft:
button_mask.left.Assign(1);
break;
case Settings::NativeButton::DUp:
button_mask.up.Assign(1);
break;
case Settings::NativeButton::DRight:
button_mask.right.Assign(1);
break;
case Settings::NativeButton::DDown:
button_mask.down.Assign(1);
break;
case Settings::NativeButton::SL:
button_mask.left_sl.Assign(1);
button_mask.right_sl.Assign(1);
break;
case Settings::NativeButton::SR:
button_mask.left_sr.Assign(1);
button_mask.right_sr.Assign(1);
break;
default:
break;
}
}
return static_cast<NpadButton>(~button_mask.raw);
}
} // namespace Core::HID } // namespace Core::HID

View file

@ -411,6 +411,9 @@ public:
*/ */
void DeleteCallback(int key); void DeleteCallback(int key);
/// Swaps the state of the turbo buttons
void TurboButtonUpdate();
private: private:
/// creates input devices from params /// creates input devices from params
void LoadDevices(); void LoadDevices();
@ -511,6 +514,8 @@ private:
*/ */
void TriggerOnChange(ControllerTriggerType type, bool is_service_update); void TriggerOnChange(ControllerTriggerType type, bool is_service_update);
NpadButton GetTurboButtonMask() const;
const NpadIdType npad_id_type; const NpadIdType npad_id_type;
NpadStyleIndex npad_type{NpadStyleIndex::None}; NpadStyleIndex npad_type{NpadStyleIndex::None};
NpadStyleIndex original_npad_type{NpadStyleIndex::None}; NpadStyleIndex original_npad_type{NpadStyleIndex::None};
@ -520,6 +525,7 @@ private:
bool system_buttons_enabled{true}; bool system_buttons_enabled{true};
f32 motion_sensitivity{0.01f}; f32 motion_sensitivity{0.01f};
bool force_update_motion{false}; bool force_update_motion{false};
bool turbo_button_state{false};
// Temporary values to avoid doing changes while the controller is in configuring mode // Temporary values to avoid doing changes while the controller is in configuring mode
NpadStyleIndex tmp_npad_type{NpadStyleIndex::None}; NpadStyleIndex tmp_npad_type{NpadStyleIndex::None};

View file

@ -11,6 +11,7 @@
#include "common/common_funcs.h" #include "common/common_funcs.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/scratch_buffer.h"
#include "core/hle/ipc_helpers.h" #include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/hle_ipc.h" #include "core/hle/kernel/hle_ipc.h"
#include "core/hle/kernel/k_auto_object.h" #include "core/hle/kernel/k_auto_object.h"
@ -325,7 +326,7 @@ Result HLERequestContext::WriteToOutgoingCommandBuffer(KThread& requesting_threa
return ResultSuccess; return ResultSuccess;
} }
std::vector<u8> HLERequestContext::ReadBuffer(std::size_t buffer_index) const { std::vector<u8> HLERequestContext::ReadBufferCopy(std::size_t buffer_index) const {
const bool is_buffer_a{BufferDescriptorA().size() > buffer_index && const bool is_buffer_a{BufferDescriptorA().size() > buffer_index &&
BufferDescriptorA()[buffer_index].Size()}; BufferDescriptorA()[buffer_index].Size()};
if (is_buffer_a) { if (is_buffer_a) {
@ -345,6 +346,33 @@ std::vector<u8> HLERequestContext::ReadBuffer(std::size_t buffer_index) const {
} }
} }
std::span<const u8> HLERequestContext::ReadBuffer(std::size_t buffer_index) const {
static thread_local std::array<Common::ScratchBuffer<u8>, 2> read_buffer_a;
static thread_local std::array<Common::ScratchBuffer<u8>, 2> read_buffer_x;
const bool is_buffer_a{BufferDescriptorA().size() > buffer_index &&
BufferDescriptorA()[buffer_index].Size()};
if (is_buffer_a) {
ASSERT_OR_EXECUTE_MSG(
BufferDescriptorA().size() > buffer_index, { return {}; },
"BufferDescriptorA invalid buffer_index {}", buffer_index);
auto& read_buffer = read_buffer_a[buffer_index];
read_buffer.resize_destructive(BufferDescriptorA()[buffer_index].Size());
memory.ReadBlock(BufferDescriptorA()[buffer_index].Address(), read_buffer.data(),
read_buffer.size());
return read_buffer;
} else {
ASSERT_OR_EXECUTE_MSG(
BufferDescriptorX().size() > buffer_index, { return {}; },
"BufferDescriptorX invalid buffer_index {}", buffer_index);
auto& read_buffer = read_buffer_x[buffer_index];
read_buffer.resize_destructive(BufferDescriptorX()[buffer_index].Size());
memory.ReadBlock(BufferDescriptorX()[buffer_index].Address(), read_buffer.data(),
read_buffer.size());
return read_buffer;
}
}
std::size_t HLERequestContext::WriteBuffer(const void* buffer, std::size_t size, std::size_t HLERequestContext::WriteBuffer(const void* buffer, std::size_t size,
std::size_t buffer_index) const { std::size_t buffer_index) const {
if (size == 0) { if (size == 0) {

View file

@ -7,6 +7,7 @@
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <optional> #include <optional>
#include <span>
#include <string> #include <string>
#include <type_traits> #include <type_traits>
#include <vector> #include <vector>
@ -270,8 +271,11 @@ public:
return domain_message_header.has_value(); return domain_message_header.has_value();
} }
/// Helper function to read a buffer using the appropriate buffer descriptor /// Helper function to get a span of a buffer using the appropriate buffer descriptor
[[nodiscard]] std::vector<u8> ReadBuffer(std::size_t buffer_index = 0) const; [[nodiscard]] std::span<const u8> ReadBuffer(std::size_t buffer_index = 0) const;
/// Helper function to read a copy of a buffer using the appropriate buffer descriptor
[[nodiscard]] std::vector<u8> ReadBufferCopy(std::size_t buffer_index = 0) const;
/// Helper function to write a buffer using the appropriate buffer descriptor /// Helper function to write a buffer using the appropriate buffer descriptor
std::size_t WriteBuffer(const void* buffer, std::size_t size, std::size_t WriteBuffer(const void* buffer, std::size_t size,

View file

@ -3,6 +3,8 @@
#pragma once #pragma once
#include <bitset>
#include "common/common_funcs.h" #include "common/common_funcs.h"
#include "common/common_types.h" #include "common/common_types.h"
@ -592,4 +594,7 @@ struct CreateProcessParameter {
}; };
static_assert(sizeof(CreateProcessParameter) == 0x30); static_assert(sizeof(CreateProcessParameter) == 0x30);
constexpr size_t NumSupervisorCalls = 0xC0;
using SvcAccessFlagSet = std::bitset<NumSupervisorCalls>;
} // namespace Kernel::Svc } // namespace Kernel::Svc

View file

@ -1124,7 +1124,7 @@ void IStorageAccessor::Write(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const u64 offset{rp.Pop<u64>()}; const u64 offset{rp.Pop<u64>()};
const std::vector<u8> data{ctx.ReadBuffer()}; const auto data{ctx.ReadBuffer()};
const std::size_t size{std::min<u64>(data.size(), backing.GetSize() - offset)}; const std::size_t size{std::min<u64>(data.size(), backing.GetSize() - offset)};
LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size); LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size);

View file

@ -112,7 +112,7 @@ private:
void RequestUpdate(Kernel::HLERequestContext& ctx) { void RequestUpdate(Kernel::HLERequestContext& ctx) {
LOG_TRACE(Service_Audio, "called"); LOG_TRACE(Service_Audio, "called");
std::vector<u8> input{ctx.ReadBuffer(0)}; const auto input{ctx.ReadBuffer(0)};
// These buffers are written manually to avoid an issue with WriteBuffer throwing errors for // These buffers are written manually to avoid an issue with WriteBuffer throwing errors for
// checking size 0. Performance size is 0 for most games. // checking size 0. Performance size is 0 for most games.

View file

@ -93,7 +93,7 @@ private:
ctx.WriteBuffer(samples); ctx.WriteBuffer(samples);
} }
bool DecodeOpusData(u32& consumed, u32& sample_count, const std::vector<u8>& input, bool DecodeOpusData(u32& consumed, u32& sample_count, std::span<const u8> input,
std::vector<opus_int16>& output, u64* out_performance_time) const { std::vector<opus_int16>& output, u64* out_performance_time) const {
const auto start_time = std::chrono::steady_clock::now(); const auto start_time = std::chrono::steady_clock::now();
const std::size_t raw_output_sz = output.size() * sizeof(opus_int16); const std::size_t raw_output_sz = output.size() * sizeof(opus_int16);

View file

@ -122,7 +122,7 @@ private:
void ImportTicket(Kernel::HLERequestContext& ctx) { void ImportTicket(Kernel::HLERequestContext& ctx) {
const auto ticket = ctx.ReadBuffer(); const auto ticket = ctx.ReadBuffer();
const auto cert = ctx.ReadBuffer(1); [[maybe_unused]] const auto cert = ctx.ReadBuffer(1);
if (ticket.size() < sizeof(Core::Crypto::Ticket)) { if (ticket.size() < sizeof(Core::Crypto::Ticket)) {
LOG_ERROR(Service_ETicket, "The input buffer is not large enough!"); LOG_ERROR(Service_ETicket, "The input buffer is not large enough!");

View file

@ -190,7 +190,7 @@ private:
return; return;
} }
const std::vector<u8> data = ctx.ReadBuffer(); const auto data = ctx.ReadBuffer();
ASSERT_MSG( ASSERT_MSG(
static_cast<s64>(data.size()) <= length, static_cast<s64>(data.size()) <= length,
@ -401,11 +401,8 @@ public:
} }
void RenameFile(Kernel::HLERequestContext& ctx) { void RenameFile(Kernel::HLERequestContext& ctx) {
std::vector<u8> buffer = ctx.ReadBuffer(0); const std::string src_name = Common::StringFromBuffer(ctx.ReadBuffer(0));
const std::string src_name = Common::StringFromBuffer(buffer); const std::string dst_name = Common::StringFromBuffer(ctx.ReadBuffer(1));
buffer = ctx.ReadBuffer(1);
const std::string dst_name = Common::StringFromBuffer(buffer);
LOG_DEBUG(Service_FS, "called. file '{}' to file '{}'", src_name, dst_name); LOG_DEBUG(Service_FS, "called. file '{}' to file '{}'", src_name, dst_name);

View file

@ -228,7 +228,8 @@ private:
return; return;
} }
control = ctx.ReadBuffer(); // TODO: Can this be a span?
control = ctx.ReadBufferCopy();
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);

View file

@ -428,6 +428,9 @@ void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) {
return; return;
} }
// This function is unique to yuzu for the turbo buttons to work properly
controller.device->TurboButtonUpdate();
auto& pad_entry = controller.npad_pad_state; auto& pad_entry = controller.npad_pad_state;
auto& trigger_entry = controller.npad_trigger_state; auto& trigger_entry = controller.npad_trigger_state;
const auto button_state = controller.device->GetNpadButtons(); const auto button_state = controller.device->GetNpadButtons();
@ -755,11 +758,12 @@ Core::HID::NpadStyleTag Controller_NPad::GetSupportedStyleSet() const {
return hid_core.GetSupportedStyleTag(); return hid_core.GetSupportedStyleTag();
} }
void Controller_NPad::SetSupportedNpadIdTypes(u8* data, std::size_t length) { void Controller_NPad::SetSupportedNpadIdTypes(std::span<const u8> data) {
const auto length = data.size();
ASSERT(length > 0 && (length % sizeof(u32)) == 0); ASSERT(length > 0 && (length % sizeof(u32)) == 0);
supported_npad_id_types.clear(); supported_npad_id_types.clear();
supported_npad_id_types.resize(length / sizeof(u32)); supported_npad_id_types.resize(length / sizeof(u32));
std::memcpy(supported_npad_id_types.data(), data, length); std::memcpy(supported_npad_id_types.data(), data.data(), length);
} }
void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) { void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) {

View file

@ -6,6 +6,7 @@
#include <array> #include <array>
#include <atomic> #include <atomic>
#include <mutex> #include <mutex>
#include <span>
#include "common/bit_field.h" #include "common/bit_field.h"
#include "common/common_types.h" #include "common/common_types.h"
@ -95,7 +96,7 @@ public:
void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set); void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set);
Core::HID::NpadStyleTag GetSupportedStyleSet() const; Core::HID::NpadStyleTag GetSupportedStyleSet() const;
void SetSupportedNpadIdTypes(u8* data, std::size_t length); void SetSupportedNpadIdTypes(std::span<const u8> data);
void GetSupportedNpadIdTypes(u32* data, std::size_t max_length); void GetSupportedNpadIdTypes(u32* data, std::size_t max_length);
std::size_t GetSupportedNpadIdTypesSize() const; std::size_t GetSupportedNpadIdTypesSize() const;

View file

@ -1026,7 +1026,7 @@ void Hid::SetSupportedNpadIdType(Kernel::HLERequestContext& ctx) {
const auto applet_resource_user_id{rp.Pop<u64>()}; const auto applet_resource_user_id{rp.Pop<u64>()};
applet_resource->GetController<Controller_NPad>(HidController::NPad) applet_resource->GetController<Controller_NPad>(HidController::NPad)
.SetSupportedNpadIdTypes(ctx.ReadBuffer().data(), ctx.GetReadBufferSize()); .SetSupportedNpadIdTypes(ctx.ReadBuffer());
LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
@ -2104,7 +2104,7 @@ void Hid::WritePalmaRgbLedPatternEntry(Kernel::HLERequestContext& ctx) {
const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()}; const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
const auto unknown{rp.Pop<u64>()}; const auto unknown{rp.Pop<u64>()};
const auto buffer = ctx.ReadBuffer(); [[maybe_unused]] const auto buffer = ctx.ReadBuffer();
LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, unknown={}", LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, unknown={}",
connection_handle.npad_id, unknown); connection_handle.npad_id, unknown);

View file

@ -4,6 +4,7 @@
#pragma once #pragma once
#include <array> #include <array>
#include <span>
#include "common/common_types.h" #include "common/common_types.h"
#include "core/hle/result.h" #include "core/hle/result.h"
@ -150,7 +151,7 @@ public:
} }
// Assigns a command from data // Assigns a command from data
virtual bool SetCommand(const std::vector<u8>& data) { virtual bool SetCommand(std::span<const u8> data) {
return {}; return {};
} }

View file

@ -116,7 +116,7 @@ std::vector<u8> RingController::GetReply() const {
} }
} }
bool RingController::SetCommand(const std::vector<u8>& data) { bool RingController::SetCommand(std::span<const u8> data) {
if (data.size() < 4) { if (data.size() < 4) {
LOG_ERROR(Service_HID, "Command size not supported {}", data.size()); LOG_ERROR(Service_HID, "Command size not supported {}", data.size());
command = RingConCommands::Error; command = RingConCommands::Error;

View file

@ -4,6 +4,7 @@
#pragma once #pragma once
#include <array> #include <array>
#include <span>
#include "common/common_types.h" #include "common/common_types.h"
#include "core/hle/service/hid/hidbus/hidbus_base.h" #include "core/hle/service/hid/hidbus/hidbus_base.h"
@ -31,7 +32,7 @@ public:
u8 GetDeviceId() const override; u8 GetDeviceId() const override;
// Assigns a command from data // Assigns a command from data
bool SetCommand(const std::vector<u8>& data) override; bool SetCommand(std::span<const u8> data) override;
// Returns a reply from a command // Returns a reply from a command
std::vector<u8> GetReply() const override; std::vector<u8> GetReply() const override;

View file

@ -42,7 +42,7 @@ std::vector<u8> Starlink::GetReply() const {
return {}; return {};
} }
bool Starlink::SetCommand(const std::vector<u8>& data) { bool Starlink::SetCommand(std::span<const u8> data) {
LOG_ERROR(Service_HID, "Command not implemented"); LOG_ERROR(Service_HID, "Command not implemented");
return false; return false;
} }

View file

@ -29,7 +29,7 @@ public:
u8 GetDeviceId() const override; u8 GetDeviceId() const override;
// Assigns a command from data // Assigns a command from data
bool SetCommand(const std::vector<u8>& data) override; bool SetCommand(std::span<const u8> data) override;
// Returns a reply from a command // Returns a reply from a command
std::vector<u8> GetReply() const override; std::vector<u8> GetReply() const override;

View file

@ -43,7 +43,7 @@ std::vector<u8> HidbusStubbed::GetReply() const {
return {}; return {};
} }
bool HidbusStubbed::SetCommand(const std::vector<u8>& data) { bool HidbusStubbed::SetCommand(std::span<const u8> data) {
LOG_ERROR(Service_HID, "Command not implemented"); LOG_ERROR(Service_HID, "Command not implemented");
return false; return false;
} }

View file

@ -29,7 +29,7 @@ public:
u8 GetDeviceId() const override; u8 GetDeviceId() const override;
// Assigns a command from data // Assigns a command from data
bool SetCommand(const std::vector<u8>& data) override; bool SetCommand(std::span<const u8> data) override;
// Returns a reply from a command // Returns a reply from a command
std::vector<u8> GetReply() const override; std::vector<u8> GetReply() const override;

View file

@ -62,7 +62,7 @@ public:
const auto parameters{rp.PopRaw<InputParameters>()}; const auto parameters{rp.PopRaw<InputParameters>()};
// Optional input/output buffers // Optional input/output buffers
std::vector<u8> input_buffer{ctx.CanReadBuffer() ? ctx.ReadBuffer() : std::vector<u8>()}; const auto input_buffer{ctx.CanReadBuffer() ? ctx.ReadBuffer() : std::span<const u8>()};
std::vector<u8> output_buffer(ctx.CanWriteBuffer() ? ctx.GetWriteBufferSize() : 0); std::vector<u8> output_buffer(ctx.CanWriteBuffer() ? ctx.GetWriteBufferSize() : 0);
// Function call prototype: // Function call prototype:
@ -132,7 +132,7 @@ public:
const auto command{rp.PopRaw<u64>()}; const auto command{rp.PopRaw<u64>()};
// Optional input/output buffers // Optional input/output buffers
std::vector<u8> input_buffer{ctx.CanReadBuffer() ? ctx.ReadBuffer() : std::vector<u8>()}; const auto input_buffer{ctx.CanReadBuffer() ? ctx.ReadBuffer() : std::span<const u8>()};
std::vector<u8> output_buffer(ctx.CanWriteBuffer() ? ctx.GetWriteBufferSize() : 0); std::vector<u8> output_buffer(ctx.CanWriteBuffer() ? ctx.GetWriteBufferSize() : 0);
// Function call prototype: // Function call prototype:

View file

@ -427,7 +427,7 @@ public:
} }
void SetAdvertiseData(Kernel::HLERequestContext& ctx) { void SetAdvertiseData(Kernel::HLERequestContext& ctx) {
std::vector<u8> read_buffer = ctx.ReadBuffer(); const auto read_buffer = ctx.ReadBuffer();
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(lan_discovery.SetAdvertiseData(read_buffer)); rb.Push(lan_discovery.SetAdvertiseData(read_buffer));
@ -479,7 +479,7 @@ public:
parameters.security_config.passphrase_size, parameters.security_config.passphrase_size,
parameters.security_config.security_mode, parameters.local_communication_version); parameters.security_config.security_mode, parameters.local_communication_version);
const std::vector<u8> read_buffer = ctx.ReadBuffer(); const auto read_buffer = ctx.ReadBuffer();
if (read_buffer.size() != sizeof(NetworkInfo)) { if (read_buffer.size() != sizeof(NetworkInfo)) {
LOG_ERROR(Frontend, "NetworkInfo doesn't match read_buffer size!"); LOG_ERROR(Frontend, "NetworkInfo doesn't match read_buffer size!");
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};

View file

@ -3,7 +3,9 @@
#pragma once #pragma once
#include <span>
#include <vector> #include <vector>
#include "common/common_types.h" #include "common/common_types.h"
#include "core/hle/service/nvdrv/nvdata.h" #include "core/hle/service/nvdrv/nvdata.h"
@ -31,7 +33,7 @@ public:
* @param output A buffer where the output data will be written to. * @param output A buffer where the output data will be written to.
* @returns The result code of the ioctl. * @returns The result code of the ioctl.
*/ */
virtual NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, virtual NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
std::vector<u8>& output) = 0; std::vector<u8>& output) = 0;
/** /**
@ -42,8 +44,8 @@ public:
* @param output A buffer where the output data will be written to. * @param output A buffer where the output data will be written to.
* @returns The result code of the ioctl. * @returns The result code of the ioctl.
*/ */
virtual NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, virtual NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
const std::vector<u8>& inline_input, std::vector<u8>& output) = 0; std::span<const u8> inline_input, std::vector<u8>& output) = 0;
/** /**
* Handles an ioctl3 request. * Handles an ioctl3 request.
@ -53,7 +55,7 @@ public:
* @param inline_output A buffer where the inlined output data will be written to. * @param inline_output A buffer where the inlined output data will be written to.
* @returns The result code of the ioctl. * @returns The result code of the ioctl.
*/ */
virtual NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, virtual NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
std::vector<u8>& output, std::vector<u8>& inline_output) = 0; std::vector<u8>& output, std::vector<u8>& inline_output) = 0;
/** /**

View file

@ -17,19 +17,19 @@ nvdisp_disp0::nvdisp_disp0(Core::System& system_, NvCore::Container& core)
: nvdevice{system_}, container{core}, nvmap{core.GetNvMapFile()} {} : nvdevice{system_}, container{core}, nvmap{core.GetNvMapFile()} {}
nvdisp_disp0::~nvdisp_disp0() = default; nvdisp_disp0::~nvdisp_disp0() = default;
NvResult nvdisp_disp0::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult nvdisp_disp0::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
std::vector<u8>& output) { std::vector<u8>& output) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented; return NvResult::NotImplemented;
} }
NvResult nvdisp_disp0::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult nvdisp_disp0::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
const std::vector<u8>& inline_input, std::vector<u8>& output) { std::span<const u8> inline_input, std::vector<u8>& output) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented; return NvResult::NotImplemented;
} }
NvResult nvdisp_disp0::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult nvdisp_disp0::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
std::vector<u8>& output, std::vector<u8>& inline_output) { std::vector<u8>& output, std::vector<u8>& inline_output) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented; return NvResult::NotImplemented;

View file

@ -25,12 +25,12 @@ public:
explicit nvdisp_disp0(Core::System& system_, NvCore::Container& core); explicit nvdisp_disp0(Core::System& system_, NvCore::Container& core);
~nvdisp_disp0() override; ~nvdisp_disp0() override;
NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
std::vector<u8>& output) override; std::vector<u8>& output) override;
NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
const std::vector<u8>& inline_input, std::vector<u8>& output) override; std::span<const u8> inline_input, std::vector<u8>& output) override;
NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output,
std::vector<u8>& output, std::vector<u8>& inline_output) override; std::vector<u8>& inline_output) override;
void OnOpen(DeviceFD fd) override; void OnOpen(DeviceFD fd) override;
void OnClose(DeviceFD fd) override; void OnClose(DeviceFD fd) override;

View file

@ -27,7 +27,7 @@ nvhost_as_gpu::nvhost_as_gpu(Core::System& system_, Module& module_, NvCore::Con
nvhost_as_gpu::~nvhost_as_gpu() = default; nvhost_as_gpu::~nvhost_as_gpu() = default;
NvResult nvhost_as_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult nvhost_as_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
std::vector<u8>& output) { std::vector<u8>& output) {
switch (command.group) { switch (command.group) {
case 'A': case 'A':
@ -60,13 +60,13 @@ NvResult nvhost_as_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>
return NvResult::NotImplemented; return NvResult::NotImplemented;
} }
NvResult nvhost_as_gpu::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult nvhost_as_gpu::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
const std::vector<u8>& inline_input, std::vector<u8>& output) { std::span<const u8> inline_input, std::vector<u8>& output) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented; return NvResult::NotImplemented;
} }
NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
std::vector<u8>& output, std::vector<u8>& inline_output) { std::vector<u8>& output, std::vector<u8>& inline_output) {
switch (command.group) { switch (command.group) {
case 'A': case 'A':
@ -87,7 +87,7 @@ NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>
void nvhost_as_gpu::OnOpen(DeviceFD fd) {} void nvhost_as_gpu::OnOpen(DeviceFD fd) {}
void nvhost_as_gpu::OnClose(DeviceFD fd) {} void nvhost_as_gpu::OnClose(DeviceFD fd) {}
NvResult nvhost_as_gpu::AllocAsEx(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_as_gpu::AllocAsEx(std::span<const u8> input, std::vector<u8>& output) {
IoctlAllocAsEx params{}; IoctlAllocAsEx params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());
@ -141,7 +141,7 @@ NvResult nvhost_as_gpu::AllocAsEx(const std::vector<u8>& input, std::vector<u8>&
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_as_gpu::AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_as_gpu::AllocateSpace(std::span<const u8> input, std::vector<u8>& output) {
IoctlAllocSpace params{}; IoctlAllocSpace params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());
@ -220,7 +220,7 @@ void nvhost_as_gpu::FreeMappingLocked(u64 offset) {
mapping_map.erase(offset); mapping_map.erase(offset);
} }
NvResult nvhost_as_gpu::FreeSpace(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_as_gpu::FreeSpace(std::span<const u8> input, std::vector<u8>& output) {
IoctlFreeSpace params{}; IoctlFreeSpace params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());
@ -266,7 +266,7 @@ NvResult nvhost_as_gpu::FreeSpace(const std::vector<u8>& input, std::vector<u8>&
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_as_gpu::Remap(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_as_gpu::Remap(std::span<const u8> input, std::vector<u8>& output) {
const auto num_entries = input.size() / sizeof(IoctlRemapEntry); const auto num_entries = input.size() / sizeof(IoctlRemapEntry);
LOG_DEBUG(Service_NVDRV, "called, num_entries=0x{:X}", num_entries); LOG_DEBUG(Service_NVDRV, "called, num_entries=0x{:X}", num_entries);
@ -320,7 +320,7 @@ NvResult nvhost_as_gpu::Remap(const std::vector<u8>& input, std::vector<u8>& out
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_as_gpu::MapBufferEx(std::span<const u8> input, std::vector<u8>& output) {
IoctlMapBufferEx params{}; IoctlMapBufferEx params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());
@ -424,7 +424,7 @@ NvResult nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_as_gpu::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_as_gpu::UnmapBuffer(std::span<const u8> input, std::vector<u8>& output) {
IoctlUnmapBuffer params{}; IoctlUnmapBuffer params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());
@ -463,7 +463,7 @@ NvResult nvhost_as_gpu::UnmapBuffer(const std::vector<u8>& input, std::vector<u8
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_as_gpu::BindChannel(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_as_gpu::BindChannel(std::span<const u8> input, std::vector<u8>& output) {
IoctlBindChannel params{}; IoctlBindChannel params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());
LOG_DEBUG(Service_NVDRV, "called, fd={:X}", params.fd); LOG_DEBUG(Service_NVDRV, "called, fd={:X}", params.fd);
@ -492,7 +492,7 @@ void nvhost_as_gpu::GetVARegionsImpl(IoctlGetVaRegions& params) {
}; };
} }
NvResult nvhost_as_gpu::GetVARegions(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::vector<u8>& output) {
IoctlGetVaRegions params{}; IoctlGetVaRegions params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());
@ -511,7 +511,7 @@ NvResult nvhost_as_gpu::GetVARegions(const std::vector<u8>& input, std::vector<u
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_as_gpu::GetVARegions(const std::vector<u8>& input, std::vector<u8>& output, NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::vector<u8>& output,
std::vector<u8>& inline_output) { std::vector<u8>& inline_output) {
IoctlGetVaRegions params{}; IoctlGetVaRegions params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());

View file

@ -47,12 +47,12 @@ public:
explicit nvhost_as_gpu(Core::System& system_, Module& module, NvCore::Container& core); explicit nvhost_as_gpu(Core::System& system_, Module& module, NvCore::Container& core);
~nvhost_as_gpu() override; ~nvhost_as_gpu() override;
NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
std::vector<u8>& output) override; std::vector<u8>& output) override;
NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
const std::vector<u8>& inline_input, std::vector<u8>& output) override; std::span<const u8> inline_input, std::vector<u8>& output) override;
NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output,
std::vector<u8>& output, std::vector<u8>& inline_output) override; std::vector<u8>& inline_output) override;
void OnOpen(DeviceFD fd) override; void OnOpen(DeviceFD fd) override;
void OnClose(DeviceFD fd) override; void OnClose(DeviceFD fd) override;
@ -138,17 +138,17 @@ private:
static_assert(sizeof(IoctlGetVaRegions) == 16 + sizeof(VaRegion) * 2, static_assert(sizeof(IoctlGetVaRegions) == 16 + sizeof(VaRegion) * 2,
"IoctlGetVaRegions is incorrect size"); "IoctlGetVaRegions is incorrect size");
NvResult AllocAsEx(const std::vector<u8>& input, std::vector<u8>& output); NvResult AllocAsEx(std::span<const u8> input, std::vector<u8>& output);
NvResult AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output); NvResult AllocateSpace(std::span<const u8> input, std::vector<u8>& output);
NvResult Remap(const std::vector<u8>& input, std::vector<u8>& output); NvResult Remap(std::span<const u8> input, std::vector<u8>& output);
NvResult MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output); NvResult MapBufferEx(std::span<const u8> input, std::vector<u8>& output);
NvResult UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output); NvResult UnmapBuffer(std::span<const u8> input, std::vector<u8>& output);
NvResult FreeSpace(const std::vector<u8>& input, std::vector<u8>& output); NvResult FreeSpace(std::span<const u8> input, std::vector<u8>& output);
NvResult BindChannel(const std::vector<u8>& input, std::vector<u8>& output); NvResult BindChannel(std::span<const u8> input, std::vector<u8>& output);
void GetVARegionsImpl(IoctlGetVaRegions& params); void GetVARegionsImpl(IoctlGetVaRegions& params);
NvResult GetVARegions(const std::vector<u8>& input, std::vector<u8>& output); NvResult GetVARegions(std::span<const u8> input, std::vector<u8>& output);
NvResult GetVARegions(const std::vector<u8>& input, std::vector<u8>& output, NvResult GetVARegions(std::span<const u8> input, std::vector<u8>& output,
std::vector<u8>& inline_output); std::vector<u8>& inline_output);
void FreeMappingLocked(u64 offset); void FreeMappingLocked(u64 offset);

View file

@ -34,7 +34,7 @@ nvhost_ctrl::~nvhost_ctrl() {
} }
} }
NvResult nvhost_ctrl::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult nvhost_ctrl::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
std::vector<u8>& output) { std::vector<u8>& output) {
switch (command.group) { switch (command.group) {
case 0x0: case 0x0:
@ -63,13 +63,13 @@ NvResult nvhost_ctrl::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>&
return NvResult::NotImplemented; return NvResult::NotImplemented;
} }
NvResult nvhost_ctrl::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult nvhost_ctrl::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
const std::vector<u8>& inline_input, std::vector<u8>& output) { std::span<const u8> inline_input, std::vector<u8>& output) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented; return NvResult::NotImplemented;
} }
NvResult nvhost_ctrl::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult nvhost_ctrl::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
std::vector<u8>& output, std::vector<u8>& inline_outpu) { std::vector<u8>& output, std::vector<u8>& inline_outpu) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented; return NvResult::NotImplemented;
@ -79,7 +79,7 @@ void nvhost_ctrl::OnOpen(DeviceFD fd) {}
void nvhost_ctrl::OnClose(DeviceFD fd) {} void nvhost_ctrl::OnClose(DeviceFD fd) {}
NvResult nvhost_ctrl::NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_ctrl::NvOsGetConfigU32(std::span<const u8> input, std::vector<u8>& output) {
IocGetConfigParams params{}; IocGetConfigParams params{};
std::memcpy(&params, input.data(), sizeof(params)); std::memcpy(&params, input.data(), sizeof(params));
LOG_TRACE(Service_NVDRV, "called, setting={}!{}", params.domain_str.data(), LOG_TRACE(Service_NVDRV, "called, setting={}!{}", params.domain_str.data(),
@ -87,7 +87,7 @@ NvResult nvhost_ctrl::NvOsGetConfigU32(const std::vector<u8>& input, std::vector
return NvResult::ConfigVarNotFound; // Returns error on production mode return NvResult::ConfigVarNotFound; // Returns error on production mode
} }
NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output, NvResult nvhost_ctrl::IocCtrlEventWait(std::span<const u8> input, std::vector<u8>& output,
bool is_allocation) { bool is_allocation) {
IocCtrlEventWaitParams params{}; IocCtrlEventWaitParams params{};
std::memcpy(&params, input.data(), sizeof(params)); std::memcpy(&params, input.data(), sizeof(params));
@ -231,7 +231,7 @@ NvResult nvhost_ctrl::FreeEvent(u32 slot) {
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_ctrl::IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_ctrl::IocCtrlEventRegister(std::span<const u8> input, std::vector<u8>& output) {
IocCtrlEventRegisterParams params{}; IocCtrlEventRegisterParams params{};
std::memcpy(&params, input.data(), sizeof(params)); std::memcpy(&params, input.data(), sizeof(params));
const u32 event_id = params.user_event_id; const u32 event_id = params.user_event_id;
@ -252,8 +252,7 @@ NvResult nvhost_ctrl::IocCtrlEventRegister(const std::vector<u8>& input, std::ve
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_ctrl::IocCtrlEventUnregister(const std::vector<u8>& input, NvResult nvhost_ctrl::IocCtrlEventUnregister(std::span<const u8> input, std::vector<u8>& output) {
std::vector<u8>& output) {
IocCtrlEventUnregisterParams params{}; IocCtrlEventUnregisterParams params{};
std::memcpy(&params, input.data(), sizeof(params)); std::memcpy(&params, input.data(), sizeof(params));
const u32 event_id = params.user_event_id & 0x00FF; const u32 event_id = params.user_event_id & 0x00FF;
@ -263,7 +262,7 @@ NvResult nvhost_ctrl::IocCtrlEventUnregister(const std::vector<u8>& input,
return FreeEvent(event_id); return FreeEvent(event_id);
} }
NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(const std::vector<u8>& input, NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(std::span<const u8> input,
std::vector<u8>& output) { std::vector<u8>& output) {
IocCtrlEventUnregisterBatchParams params{}; IocCtrlEventUnregisterBatchParams params{};
std::memcpy(&params, input.data(), sizeof(params)); std::memcpy(&params, input.data(), sizeof(params));
@ -282,7 +281,7 @@ NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(const std::vector<u8>& input,
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_ctrl::IocCtrlClearEventWait(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_ctrl::IocCtrlClearEventWait(std::span<const u8> input, std::vector<u8>& output) {
IocCtrlEventClearParams params{}; IocCtrlEventClearParams params{};
std::memcpy(&params, input.data(), sizeof(params)); std::memcpy(&params, input.data(), sizeof(params));

View file

@ -25,12 +25,12 @@ public:
NvCore::Container& core); NvCore::Container& core);
~nvhost_ctrl() override; ~nvhost_ctrl() override;
NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
std::vector<u8>& output) override; std::vector<u8>& output) override;
NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
const std::vector<u8>& inline_input, std::vector<u8>& output) override; std::span<const u8> inline_input, std::vector<u8>& output) override;
NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output,
std::vector<u8>& output, std::vector<u8>& inline_output) override; std::vector<u8>& inline_output) override;
void OnOpen(DeviceFD fd) override; void OnOpen(DeviceFD fd) override;
void OnClose(DeviceFD fd) override; void OnClose(DeviceFD fd) override;
@ -186,13 +186,13 @@ private:
static_assert(sizeof(IocCtrlEventUnregisterBatchParams) == 8, static_assert(sizeof(IocCtrlEventUnregisterBatchParams) == 8,
"IocCtrlEventKill is incorrect size"); "IocCtrlEventKill is incorrect size");
NvResult NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output); NvResult NvOsGetConfigU32(std::span<const u8> input, std::vector<u8>& output);
NvResult IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output, NvResult IocCtrlEventWait(std::span<const u8> input, std::vector<u8>& output,
bool is_allocation); bool is_allocation);
NvResult IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output); NvResult IocCtrlEventRegister(std::span<const u8> input, std::vector<u8>& output);
NvResult IocCtrlEventUnregister(const std::vector<u8>& input, std::vector<u8>& output); NvResult IocCtrlEventUnregister(std::span<const u8> input, std::vector<u8>& output);
NvResult IocCtrlEventUnregisterBatch(const std::vector<u8>& input, std::vector<u8>& output); NvResult IocCtrlEventUnregisterBatch(std::span<const u8> input, std::vector<u8>& output);
NvResult IocCtrlClearEventWait(const std::vector<u8>& input, std::vector<u8>& output); NvResult IocCtrlClearEventWait(std::span<const u8> input, std::vector<u8>& output);
NvResult FreeEvent(u32 slot); NvResult FreeEvent(u32 slot);

View file

@ -21,7 +21,7 @@ nvhost_ctrl_gpu::~nvhost_ctrl_gpu() {
events_interface.FreeEvent(unknown_event); events_interface.FreeEvent(unknown_event);
} }
NvResult nvhost_ctrl_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult nvhost_ctrl_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
std::vector<u8>& output) { std::vector<u8>& output) {
switch (command.group) { switch (command.group) {
case 'G': case 'G':
@ -53,13 +53,13 @@ NvResult nvhost_ctrl_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u
return NvResult::NotImplemented; return NvResult::NotImplemented;
} }
NvResult nvhost_ctrl_gpu::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult nvhost_ctrl_gpu::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
const std::vector<u8>& inline_input, std::vector<u8>& output) { std::span<const u8> inline_input, std::vector<u8>& output) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented; return NvResult::NotImplemented;
} }
NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
std::vector<u8>& output, std::vector<u8>& inline_output) { std::vector<u8>& output, std::vector<u8>& inline_output) {
switch (command.group) { switch (command.group) {
case 'G': case 'G':
@ -82,8 +82,7 @@ NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u
void nvhost_ctrl_gpu::OnOpen(DeviceFD fd) {} void nvhost_ctrl_gpu::OnOpen(DeviceFD fd) {}
void nvhost_ctrl_gpu::OnClose(DeviceFD fd) {} void nvhost_ctrl_gpu::OnClose(DeviceFD fd) {}
NvResult nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::vector<u8>& output) {
std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "called"); LOG_DEBUG(Service_NVDRV, "called");
IoctlCharacteristics params{}; IoctlCharacteristics params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());
@ -128,7 +127,7 @@ NvResult nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input,
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output, NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::vector<u8>& output,
std::vector<u8>& inline_output) { std::vector<u8>& inline_output) {
LOG_DEBUG(Service_NVDRV, "called"); LOG_DEBUG(Service_NVDRV, "called");
IoctlCharacteristics params{}; IoctlCharacteristics params{};
@ -176,7 +175,7 @@ NvResult nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, std::
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_ctrl_gpu::GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_ctrl_gpu::GetTPCMasks(std::span<const u8> input, std::vector<u8>& output) {
IoctlGpuGetTpcMasksArgs params{}; IoctlGpuGetTpcMasksArgs params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());
LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size=0x{:X}", params.mask_buffer_size); LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size=0x{:X}", params.mask_buffer_size);
@ -187,7 +186,7 @@ NvResult nvhost_ctrl_gpu::GetTPCMasks(const std::vector<u8>& input, std::vector<
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_ctrl_gpu::GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output, NvResult nvhost_ctrl_gpu::GetTPCMasks(std::span<const u8> input, std::vector<u8>& output,
std::vector<u8>& inline_output) { std::vector<u8>& inline_output) {
IoctlGpuGetTpcMasksArgs params{}; IoctlGpuGetTpcMasksArgs params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());
@ -200,7 +199,7 @@ NvResult nvhost_ctrl_gpu::GetTPCMasks(const std::vector<u8>& input, std::vector<
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_ctrl_gpu::GetActiveSlotMask(std::span<const u8> input, std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "called"); LOG_DEBUG(Service_NVDRV, "called");
IoctlActiveSlotMask params{}; IoctlActiveSlotMask params{};
@ -213,7 +212,7 @@ NvResult nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector<u8>& input, std::v
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_ctrl_gpu::ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_ctrl_gpu::ZCullGetCtxSize(std::span<const u8> input, std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "called"); LOG_DEBUG(Service_NVDRV, "called");
IoctlZcullGetCtxSize params{}; IoctlZcullGetCtxSize params{};
@ -225,7 +224,7 @@ NvResult nvhost_ctrl_gpu::ZCullGetCtxSize(const std::vector<u8>& input, std::vec
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_ctrl_gpu::ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_ctrl_gpu::ZCullGetInfo(std::span<const u8> input, std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "called"); LOG_DEBUG(Service_NVDRV, "called");
IoctlNvgpuGpuZcullGetInfoArgs params{}; IoctlNvgpuGpuZcullGetInfoArgs params{};
@ -248,7 +247,7 @@ NvResult nvhost_ctrl_gpu::ZCullGetInfo(const std::vector<u8>& input, std::vector
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_ctrl_gpu::ZBCSetTable(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_ctrl_gpu::ZBCSetTable(std::span<const u8> input, std::vector<u8>& output) {
LOG_WARNING(Service_NVDRV, "(STUBBED) called"); LOG_WARNING(Service_NVDRV, "(STUBBED) called");
IoctlZbcSetTable params{}; IoctlZbcSetTable params{};
@ -264,7 +263,7 @@ NvResult nvhost_ctrl_gpu::ZBCSetTable(const std::vector<u8>& input, std::vector<
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_ctrl_gpu::ZBCQueryTable(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_ctrl_gpu::ZBCQueryTable(std::span<const u8> input, std::vector<u8>& output) {
LOG_WARNING(Service_NVDRV, "(STUBBED) called"); LOG_WARNING(Service_NVDRV, "(STUBBED) called");
IoctlZbcQueryTable params{}; IoctlZbcQueryTable params{};
@ -274,7 +273,7 @@ NvResult nvhost_ctrl_gpu::ZBCQueryTable(const std::vector<u8>& input, std::vecto
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_ctrl_gpu::FlushL2(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_ctrl_gpu::FlushL2(std::span<const u8> input, std::vector<u8>& output) {
LOG_WARNING(Service_NVDRV, "(STUBBED) called"); LOG_WARNING(Service_NVDRV, "(STUBBED) called");
IoctlFlushL2 params{}; IoctlFlushL2 params{};
@ -284,7 +283,7 @@ NvResult nvhost_ctrl_gpu::FlushL2(const std::vector<u8>& input, std::vector<u8>&
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_ctrl_gpu::GetGpuTime(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_ctrl_gpu::GetGpuTime(std::span<const u8> input, std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "called"); LOG_DEBUG(Service_NVDRV, "called");
IoctlGetGpuTime params{}; IoctlGetGpuTime params{};

View file

@ -21,12 +21,12 @@ public:
explicit nvhost_ctrl_gpu(Core::System& system_, EventInterface& events_interface_); explicit nvhost_ctrl_gpu(Core::System& system_, EventInterface& events_interface_);
~nvhost_ctrl_gpu() override; ~nvhost_ctrl_gpu() override;
NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
std::vector<u8>& output) override; std::vector<u8>& output) override;
NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
const std::vector<u8>& inline_input, std::vector<u8>& output) override; std::span<const u8> inline_input, std::vector<u8>& output) override;
NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output,
std::vector<u8>& output, std::vector<u8>& inline_output) override; std::vector<u8>& inline_output) override;
void OnOpen(DeviceFD fd) override; void OnOpen(DeviceFD fd) override;
void OnClose(DeviceFD fd) override; void OnClose(DeviceFD fd) override;
@ -151,21 +151,21 @@ private:
}; };
static_assert(sizeof(IoctlGetGpuTime) == 0x10, "IoctlGetGpuTime is incorrect size"); static_assert(sizeof(IoctlGetGpuTime) == 0x10, "IoctlGetGpuTime is incorrect size");
NvResult GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output); NvResult GetCharacteristics(std::span<const u8> input, std::vector<u8>& output);
NvResult GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output, NvResult GetCharacteristics(std::span<const u8> input, std::vector<u8>& output,
std::vector<u8>& inline_output); std::vector<u8>& inline_output);
NvResult GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output); NvResult GetTPCMasks(std::span<const u8> input, std::vector<u8>& output);
NvResult GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output, NvResult GetTPCMasks(std::span<const u8> input, std::vector<u8>& output,
std::vector<u8>& inline_output); std::vector<u8>& inline_output);
NvResult GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output); NvResult GetActiveSlotMask(std::span<const u8> input, std::vector<u8>& output);
NvResult ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output); NvResult ZCullGetCtxSize(std::span<const u8> input, std::vector<u8>& output);
NvResult ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& output); NvResult ZCullGetInfo(std::span<const u8> input, std::vector<u8>& output);
NvResult ZBCSetTable(const std::vector<u8>& input, std::vector<u8>& output); NvResult ZBCSetTable(std::span<const u8> input, std::vector<u8>& output);
NvResult ZBCQueryTable(const std::vector<u8>& input, std::vector<u8>& output); NvResult ZBCQueryTable(std::span<const u8> input, std::vector<u8>& output);
NvResult FlushL2(const std::vector<u8>& input, std::vector<u8>& output); NvResult FlushL2(std::span<const u8> input, std::vector<u8>& output);
NvResult GetGpuTime(const std::vector<u8>& input, std::vector<u8>& output); NvResult GetGpuTime(std::span<const u8> input, std::vector<u8>& output);
EventInterface& events_interface; EventInterface& events_interface;

View file

@ -46,7 +46,7 @@ nvhost_gpu::~nvhost_gpu() {
syncpoint_manager.FreeSyncpoint(channel_syncpoint); syncpoint_manager.FreeSyncpoint(channel_syncpoint);
} }
NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
std::vector<u8>& output) { std::vector<u8>& output) {
switch (command.group) { switch (command.group) {
case 0x0: case 0x0:
@ -98,8 +98,8 @@ NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& i
return NvResult::NotImplemented; return NvResult::NotImplemented;
}; };
NvResult nvhost_gpu::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult nvhost_gpu::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
const std::vector<u8>& inline_input, std::vector<u8>& output) { std::span<const u8> inline_input, std::vector<u8>& output) {
switch (command.group) { switch (command.group) {
case 'H': case 'H':
switch (command.cmd) { switch (command.cmd) {
@ -112,7 +112,7 @@ NvResult nvhost_gpu::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& i
return NvResult::NotImplemented; return NvResult::NotImplemented;
} }
NvResult nvhost_gpu::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult nvhost_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
std::vector<u8>& output, std::vector<u8>& inline_output) { std::vector<u8>& output, std::vector<u8>& inline_output) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented; return NvResult::NotImplemented;
@ -121,7 +121,7 @@ NvResult nvhost_gpu::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& i
void nvhost_gpu::OnOpen(DeviceFD fd) {} void nvhost_gpu::OnOpen(DeviceFD fd) {}
void nvhost_gpu::OnClose(DeviceFD fd) {} void nvhost_gpu::OnClose(DeviceFD fd) {}
NvResult nvhost_gpu::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_gpu::SetNVMAPfd(std::span<const u8> input, std::vector<u8>& output) {
IoctlSetNvmapFD params{}; IoctlSetNvmapFD params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());
LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
@ -130,7 +130,7 @@ NvResult nvhost_gpu::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& o
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_gpu::SetClientData(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_gpu::SetClientData(std::span<const u8> input, std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "called"); LOG_DEBUG(Service_NVDRV, "called");
IoctlClientData params{}; IoctlClientData params{};
@ -139,7 +139,7 @@ NvResult nvhost_gpu::SetClientData(const std::vector<u8>& input, std::vector<u8>
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_gpu::GetClientData(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_gpu::GetClientData(std::span<const u8> input, std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "called"); LOG_DEBUG(Service_NVDRV, "called");
IoctlClientData params{}; IoctlClientData params{};
@ -149,7 +149,7 @@ NvResult nvhost_gpu::GetClientData(const std::vector<u8>& input, std::vector<u8>
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_gpu::ZCullBind(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_gpu::ZCullBind(std::span<const u8> input, std::vector<u8>& output) {
std::memcpy(&zcull_params, input.data(), input.size()); std::memcpy(&zcull_params, input.data(), input.size());
LOG_DEBUG(Service_NVDRV, "called, gpu_va={:X}, mode={:X}", zcull_params.gpu_va, LOG_DEBUG(Service_NVDRV, "called, gpu_va={:X}, mode={:X}", zcull_params.gpu_va,
zcull_params.mode); zcull_params.mode);
@ -158,7 +158,7 @@ NvResult nvhost_gpu::ZCullBind(const std::vector<u8>& input, std::vector<u8>& ou
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_gpu::SetErrorNotifier(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_gpu::SetErrorNotifier(std::span<const u8> input, std::vector<u8>& output) {
IoctlSetErrorNotifier params{}; IoctlSetErrorNotifier params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());
LOG_WARNING(Service_NVDRV, "(STUBBED) called, offset={:X}, size={:X}, mem={:X}", params.offset, LOG_WARNING(Service_NVDRV, "(STUBBED) called, offset={:X}, size={:X}, mem={:X}", params.offset,
@ -168,14 +168,14 @@ NvResult nvhost_gpu::SetErrorNotifier(const std::vector<u8>& input, std::vector<
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_gpu::SetChannelPriority(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_gpu::SetChannelPriority(std::span<const u8> input, std::vector<u8>& output) {
std::memcpy(&channel_priority, input.data(), input.size()); std::memcpy(&channel_priority, input.data(), input.size());
LOG_DEBUG(Service_NVDRV, "(STUBBED) called, priority={:X}", channel_priority); LOG_DEBUG(Service_NVDRV, "(STUBBED) called, priority={:X}", channel_priority);
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_gpu::AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_gpu::AllocGPFIFOEx2(std::span<const u8> input, std::vector<u8>& output) {
IoctlAllocGpfifoEx2 params{}; IoctlAllocGpfifoEx2 params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());
LOG_WARNING(Service_NVDRV, LOG_WARNING(Service_NVDRV,
@ -197,7 +197,7 @@ NvResult nvhost_gpu::AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_gpu::AllocateObjectContext(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_gpu::AllocateObjectContext(std::span<const u8> input, std::vector<u8>& output) {
IoctlAllocObjCtx params{}; IoctlAllocObjCtx params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());
LOG_WARNING(Service_NVDRV, "(STUBBED) called, class_num={:X}, flags={:X}", params.class_num, LOG_WARNING(Service_NVDRV, "(STUBBED) called, class_num={:X}, flags={:X}", params.class_num,
@ -293,7 +293,7 @@ NvResult nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::vector<u8>
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_gpu::SubmitGPFIFOBase(const std::vector<u8>& input, std::vector<u8>& output, NvResult nvhost_gpu::SubmitGPFIFOBase(std::span<const u8> input, std::vector<u8>& output,
bool kickoff) { bool kickoff) {
if (input.size() < sizeof(IoctlSubmitGpfifo)) { if (input.size() < sizeof(IoctlSubmitGpfifo)) {
UNIMPLEMENTED(); UNIMPLEMENTED();
@ -314,8 +314,7 @@ NvResult nvhost_gpu::SubmitGPFIFOBase(const std::vector<u8>& input, std::vector<
return SubmitGPFIFOImpl(params, output, std::move(entries)); return SubmitGPFIFOImpl(params, output, std::move(entries));
} }
NvResult nvhost_gpu::SubmitGPFIFOBase(const std::vector<u8>& input, NvResult nvhost_gpu::SubmitGPFIFOBase(std::span<const u8> input, std::span<const u8> input_inline,
const std::vector<u8>& input_inline,
std::vector<u8>& output) { std::vector<u8>& output) {
if (input.size() < sizeof(IoctlSubmitGpfifo)) { if (input.size() < sizeof(IoctlSubmitGpfifo)) {
UNIMPLEMENTED(); UNIMPLEMENTED();
@ -328,7 +327,7 @@ NvResult nvhost_gpu::SubmitGPFIFOBase(const std::vector<u8>& input,
return SubmitGPFIFOImpl(params, output, std::move(entries)); return SubmitGPFIFOImpl(params, output, std::move(entries));
} }
NvResult nvhost_gpu::GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_gpu::GetWaitbase(std::span<const u8> input, std::vector<u8>& output) {
IoctlGetWaitbase params{}; IoctlGetWaitbase params{};
std::memcpy(&params, input.data(), sizeof(IoctlGetWaitbase)); std::memcpy(&params, input.data(), sizeof(IoctlGetWaitbase));
LOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown); LOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown);
@ -338,7 +337,7 @@ NvResult nvhost_gpu::GetWaitbase(const std::vector<u8>& input, std::vector<u8>&
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_gpu::ChannelSetTimeout(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_gpu::ChannelSetTimeout(std::span<const u8> input, std::vector<u8>& output) {
IoctlChannelSetTimeout params{}; IoctlChannelSetTimeout params{};
std::memcpy(&params, input.data(), sizeof(IoctlChannelSetTimeout)); std::memcpy(&params, input.data(), sizeof(IoctlChannelSetTimeout));
LOG_INFO(Service_NVDRV, "called, timeout=0x{:X}", params.timeout); LOG_INFO(Service_NVDRV, "called, timeout=0x{:X}", params.timeout);
@ -346,7 +345,7 @@ NvResult nvhost_gpu::ChannelSetTimeout(const std::vector<u8>& input, std::vector
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_gpu::ChannelSetTimeslice(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_gpu::ChannelSetTimeslice(std::span<const u8> input, std::vector<u8>& output) {
IoctlSetTimeslice params{}; IoctlSetTimeslice params{};
std::memcpy(&params, input.data(), sizeof(IoctlSetTimeslice)); std::memcpy(&params, input.data(), sizeof(IoctlSetTimeslice));
LOG_INFO(Service_NVDRV, "called, timeslice=0x{:X}", params.timeslice); LOG_INFO(Service_NVDRV, "called, timeslice=0x{:X}", params.timeslice);

View file

@ -40,12 +40,12 @@ public:
NvCore::Container& core); NvCore::Container& core);
~nvhost_gpu() override; ~nvhost_gpu() override;
NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
std::vector<u8>& output) override; std::vector<u8>& output) override;
NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
const std::vector<u8>& inline_input, std::vector<u8>& output) override; std::span<const u8> inline_input, std::vector<u8>& output) override;
NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output,
std::vector<u8>& output, std::vector<u8>& inline_output) override; std::vector<u8>& inline_output) override;
void OnOpen(DeviceFD fd) override; void OnOpen(DeviceFD fd) override;
void OnClose(DeviceFD fd) override; void OnClose(DeviceFD fd) override;
@ -186,23 +186,23 @@ private:
u32_le channel_priority{}; u32_le channel_priority{};
u32_le channel_timeslice{}; u32_le channel_timeslice{};
NvResult SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output); NvResult SetNVMAPfd(std::span<const u8> input, std::vector<u8>& output);
NvResult SetClientData(const std::vector<u8>& input, std::vector<u8>& output); NvResult SetClientData(std::span<const u8> input, std::vector<u8>& output);
NvResult GetClientData(const std::vector<u8>& input, std::vector<u8>& output); NvResult GetClientData(std::span<const u8> input, std::vector<u8>& output);
NvResult ZCullBind(const std::vector<u8>& input, std::vector<u8>& output); NvResult ZCullBind(std::span<const u8> input, std::vector<u8>& output);
NvResult SetErrorNotifier(const std::vector<u8>& input, std::vector<u8>& output); NvResult SetErrorNotifier(std::span<const u8> input, std::vector<u8>& output);
NvResult SetChannelPriority(const std::vector<u8>& input, std::vector<u8>& output); NvResult SetChannelPriority(std::span<const u8> input, std::vector<u8>& output);
NvResult AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output); NvResult AllocGPFIFOEx2(std::span<const u8> input, std::vector<u8>& output);
NvResult AllocateObjectContext(const std::vector<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 SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::vector<u8>& output,
Tegra::CommandList&& entries); Tegra::CommandList&& entries);
NvResult SubmitGPFIFOBase(const std::vector<u8>& input, std::vector<u8>& output, NvResult SubmitGPFIFOBase(std::span<const u8> input, std::vector<u8>& output,
bool kickoff = false); bool kickoff = false);
NvResult SubmitGPFIFOBase(const std::vector<u8>& input, const std::vector<u8>& input_inline, NvResult SubmitGPFIFOBase(std::span<const u8> input, std::span<const u8> input_inline,
std::vector<u8>& output); std::vector<u8>& output);
NvResult GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output); NvResult GetWaitbase(std::span<const u8> input, std::vector<u8>& output);
NvResult ChannelSetTimeout(const std::vector<u8>& input, std::vector<u8>& output); NvResult ChannelSetTimeout(std::span<const u8> input, std::vector<u8>& output);
NvResult ChannelSetTimeslice(const std::vector<u8>& input, std::vector<u8>& output); NvResult ChannelSetTimeslice(std::span<const u8> input, std::vector<u8>& output);
EventInterface& events_interface; EventInterface& events_interface;
NvCore::Container& core; NvCore::Container& core;

View file

@ -15,7 +15,7 @@ nvhost_nvdec::nvhost_nvdec(Core::System& system_, NvCore::Container& core_)
: nvhost_nvdec_common{system_, core_, NvCore::ChannelType::NvDec} {} : nvhost_nvdec_common{system_, core_, NvCore::ChannelType::NvDec} {}
nvhost_nvdec::~nvhost_nvdec() = default; nvhost_nvdec::~nvhost_nvdec() = default;
NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
std::vector<u8>& output) { std::vector<u8>& output) {
switch (command.group) { switch (command.group) {
case 0x0: case 0x0:
@ -55,13 +55,13 @@ NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>&
return NvResult::NotImplemented; return NvResult::NotImplemented;
} }
NvResult nvhost_nvdec::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult nvhost_nvdec::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
const std::vector<u8>& inline_input, std::vector<u8>& output) { std::span<const u8> inline_input, std::vector<u8>& output) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented; return NvResult::NotImplemented;
} }
NvResult nvhost_nvdec::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult nvhost_nvdec::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
std::vector<u8>& output, std::vector<u8>& inline_output) { std::vector<u8>& output, std::vector<u8>& inline_output) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented; return NvResult::NotImplemented;

View file

@ -13,12 +13,12 @@ public:
explicit nvhost_nvdec(Core::System& system_, NvCore::Container& core); explicit nvhost_nvdec(Core::System& system_, NvCore::Container& core);
~nvhost_nvdec() override; ~nvhost_nvdec() override;
NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
std::vector<u8>& output) override; std::vector<u8>& output) override;
NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
const std::vector<u8>& inline_input, std::vector<u8>& output) override; std::span<const u8> inline_input, std::vector<u8>& output) override;
NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output,
std::vector<u8>& output, std::vector<u8>& inline_output) override; std::vector<u8>& inline_output) override;
void OnOpen(DeviceFD fd) override; void OnOpen(DeviceFD fd) override;
void OnClose(DeviceFD fd) override; void OnClose(DeviceFD fd) override;

View file

@ -23,7 +23,7 @@ namespace {
// Copies count amount of type T from the input vector into the dst vector. // Copies count amount of type T from the input vector into the dst vector.
// Returns the number of bytes written into dst. // Returns the number of bytes written into dst.
template <typename T> template <typename T>
std::size_t SliceVectors(const std::vector<u8>& input, std::vector<T>& dst, std::size_t count, std::size_t SliceVectors(std::span<const u8> input, std::vector<T>& dst, std::size_t count,
std::size_t offset) { std::size_t offset) {
if (dst.empty()) { if (dst.empty()) {
return 0; return 0;
@ -63,7 +63,7 @@ nvhost_nvdec_common::~nvhost_nvdec_common() {
core.Host1xDeviceFile().syncpts_accumulated.push_back(channel_syncpoint); core.Host1xDeviceFile().syncpts_accumulated.push_back(channel_syncpoint);
} }
NvResult nvhost_nvdec_common::SetNVMAPfd(const std::vector<u8>& input) { NvResult nvhost_nvdec_common::SetNVMAPfd(std::span<const u8> input) {
IoctlSetNvmapFD params{}; IoctlSetNvmapFD params{};
std::memcpy(&params, input.data(), sizeof(IoctlSetNvmapFD)); std::memcpy(&params, input.data(), sizeof(IoctlSetNvmapFD));
LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
@ -72,7 +72,7 @@ NvResult nvhost_nvdec_common::SetNVMAPfd(const std::vector<u8>& input) {
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_nvdec_common::Submit(DeviceFD fd, const std::vector<u8>& input, NvResult nvhost_nvdec_common::Submit(DeviceFD fd, std::span<const u8> input,
std::vector<u8>& output) { std::vector<u8>& output) {
IoctlSubmit params{}; IoctlSubmit params{};
std::memcpy(&params, input.data(), sizeof(IoctlSubmit)); std::memcpy(&params, input.data(), sizeof(IoctlSubmit));
@ -121,7 +121,7 @@ NvResult nvhost_nvdec_common::Submit(DeviceFD fd, const std::vector<u8>& input,
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_nvdec_common::GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_nvdec_common::GetSyncpoint(std::span<const u8> input, std::vector<u8>& output) {
IoctlGetSyncpoint params{}; IoctlGetSyncpoint params{};
std::memcpy(&params, input.data(), sizeof(IoctlGetSyncpoint)); std::memcpy(&params, input.data(), sizeof(IoctlGetSyncpoint));
LOG_DEBUG(Service_NVDRV, "called GetSyncpoint, id={}", params.param); LOG_DEBUG(Service_NVDRV, "called GetSyncpoint, id={}", params.param);
@ -133,7 +133,7 @@ NvResult nvhost_nvdec_common::GetSyncpoint(const std::vector<u8>& input, std::ve
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_nvdec_common::GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_nvdec_common::GetWaitbase(std::span<const u8> input, std::vector<u8>& output) {
IoctlGetWaitbase params{}; IoctlGetWaitbase params{};
LOG_CRITICAL(Service_NVDRV, "called WAITBASE"); LOG_CRITICAL(Service_NVDRV, "called WAITBASE");
std::memcpy(&params, input.data(), sizeof(IoctlGetWaitbase)); std::memcpy(&params, input.data(), sizeof(IoctlGetWaitbase));
@ -142,7 +142,7 @@ NvResult nvhost_nvdec_common::GetWaitbase(const std::vector<u8>& input, std::vec
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_nvdec_common::MapBuffer(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_nvdec_common::MapBuffer(std::span<const u8> input, std::vector<u8>& output) {
IoctlMapBuffer params{}; IoctlMapBuffer params{};
std::memcpy(&params, input.data(), sizeof(IoctlMapBuffer)); std::memcpy(&params, input.data(), sizeof(IoctlMapBuffer));
std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries);
@ -159,7 +159,7 @@ NvResult nvhost_nvdec_common::MapBuffer(const std::vector<u8>& input, std::vecto
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_nvdec_common::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_nvdec_common::UnmapBuffer(std::span<const u8> input, std::vector<u8>& output) {
IoctlMapBuffer params{}; IoctlMapBuffer params{};
std::memcpy(&params, input.data(), sizeof(IoctlMapBuffer)); std::memcpy(&params, input.data(), sizeof(IoctlMapBuffer));
std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries);
@ -173,8 +173,7 @@ NvResult nvhost_nvdec_common::UnmapBuffer(const std::vector<u8>& input, std::vec
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_nvdec_common::SetSubmitTimeout(const std::vector<u8>& input, NvResult nvhost_nvdec_common::SetSubmitTimeout(std::span<const u8> input, std::vector<u8>& output) {
std::vector<u8>& output) {
std::memcpy(&submit_timeout, input.data(), input.size()); std::memcpy(&submit_timeout, input.data(), input.size());
LOG_WARNING(Service_NVDRV, "(STUBBED) called"); LOG_WARNING(Service_NVDRV, "(STUBBED) called");
return NvResult::Success; return NvResult::Success;

View file

@ -107,13 +107,13 @@ protected:
static_assert(sizeof(IoctlMapBuffer) == 0x0C, "IoctlMapBuffer is incorrect size"); static_assert(sizeof(IoctlMapBuffer) == 0x0C, "IoctlMapBuffer is incorrect size");
/// Ioctl command implementations /// Ioctl command implementations
NvResult SetNVMAPfd(const std::vector<u8>& input); NvResult SetNVMAPfd(std::span<const u8> input);
NvResult Submit(DeviceFD fd, const std::vector<u8>& input, std::vector<u8>& output); NvResult Submit(DeviceFD fd, std::span<const u8> input, std::vector<u8>& output);
NvResult GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output); NvResult GetSyncpoint(std::span<const u8> input, std::vector<u8>& output);
NvResult GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output); NvResult GetWaitbase(std::span<const u8> input, std::vector<u8>& output);
NvResult MapBuffer(const std::vector<u8>& input, std::vector<u8>& output); NvResult MapBuffer(std::span<const u8> input, std::vector<u8>& output);
NvResult UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output); NvResult UnmapBuffer(std::span<const u8> input, std::vector<u8>& output);
NvResult SetSubmitTimeout(const std::vector<u8>& input, std::vector<u8>& output); NvResult SetSubmitTimeout(std::span<const u8> input, std::vector<u8>& output);
Kernel::KEvent* QueryEvent(u32 event_id) override; Kernel::KEvent* QueryEvent(u32 event_id) override;

View file

@ -12,7 +12,7 @@ namespace Service::Nvidia::Devices {
nvhost_nvjpg::nvhost_nvjpg(Core::System& system_) : nvdevice{system_} {} nvhost_nvjpg::nvhost_nvjpg(Core::System& system_) : nvdevice{system_} {}
nvhost_nvjpg::~nvhost_nvjpg() = default; nvhost_nvjpg::~nvhost_nvjpg() = default;
NvResult nvhost_nvjpg::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult nvhost_nvjpg::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
std::vector<u8>& output) { std::vector<u8>& output) {
switch (command.group) { switch (command.group) {
case 'H': case 'H':
@ -31,13 +31,13 @@ NvResult nvhost_nvjpg::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>&
return NvResult::NotImplemented; return NvResult::NotImplemented;
} }
NvResult nvhost_nvjpg::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult nvhost_nvjpg::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
const std::vector<u8>& inline_input, std::vector<u8>& output) { std::span<const u8> inline_input, std::vector<u8>& output) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented; return NvResult::NotImplemented;
} }
NvResult nvhost_nvjpg::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult nvhost_nvjpg::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
std::vector<u8>& output, std::vector<u8>& inline_output) { std::vector<u8>& output, std::vector<u8>& inline_output) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented; return NvResult::NotImplemented;
@ -46,7 +46,7 @@ NvResult nvhost_nvjpg::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>&
void nvhost_nvjpg::OnOpen(DeviceFD fd) {} void nvhost_nvjpg::OnOpen(DeviceFD fd) {}
void nvhost_nvjpg::OnClose(DeviceFD fd) {} void nvhost_nvjpg::OnClose(DeviceFD fd) {}
NvResult nvhost_nvjpg::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvhost_nvjpg::SetNVMAPfd(std::span<const u8> input, std::vector<u8>& output) {
IoctlSetNvmapFD params{}; IoctlSetNvmapFD params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());
LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);

View file

@ -15,12 +15,12 @@ public:
explicit nvhost_nvjpg(Core::System& system_); explicit nvhost_nvjpg(Core::System& system_);
~nvhost_nvjpg() override; ~nvhost_nvjpg() override;
NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
std::vector<u8>& output) override; std::vector<u8>& output) override;
NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
const std::vector<u8>& inline_input, std::vector<u8>& output) override; std::span<const u8> inline_input, std::vector<u8>& output) override;
NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output,
std::vector<u8>& output, std::vector<u8>& inline_output) override; std::vector<u8>& inline_output) override;
void OnOpen(DeviceFD fd) override; void OnOpen(DeviceFD fd) override;
void OnClose(DeviceFD fd) override; void OnClose(DeviceFD fd) override;
@ -33,7 +33,7 @@ private:
s32_le nvmap_fd{}; s32_le nvmap_fd{};
NvResult SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output); NvResult SetNVMAPfd(std::span<const u8> input, std::vector<u8>& output);
}; };
} // namespace Service::Nvidia::Devices } // namespace Service::Nvidia::Devices

View file

@ -15,7 +15,7 @@ nvhost_vic::nvhost_vic(Core::System& system_, NvCore::Container& core_)
nvhost_vic::~nvhost_vic() = default; nvhost_vic::~nvhost_vic() = default;
NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
std::vector<u8>& output) { std::vector<u8>& output) {
switch (command.group) { switch (command.group) {
case 0x0: case 0x0:
@ -55,13 +55,13 @@ NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& i
return NvResult::NotImplemented; return NvResult::NotImplemented;
} }
NvResult nvhost_vic::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult nvhost_vic::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
const std::vector<u8>& inline_input, std::vector<u8>& output) { std::span<const u8> inline_input, std::vector<u8>& output) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented; return NvResult::NotImplemented;
} }
NvResult nvhost_vic::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult nvhost_vic::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
std::vector<u8>& output, std::vector<u8>& inline_output) { std::vector<u8>& output, std::vector<u8>& inline_output) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented; return NvResult::NotImplemented;

View file

@ -12,12 +12,12 @@ public:
explicit nvhost_vic(Core::System& system_, NvCore::Container& core); explicit nvhost_vic(Core::System& system_, NvCore::Container& core);
~nvhost_vic(); ~nvhost_vic();
NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
std::vector<u8>& output) override; std::vector<u8>& output) override;
NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
const std::vector<u8>& inline_input, std::vector<u8>& output) override; std::span<const u8> inline_input, std::vector<u8>& output) override;
NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output,
std::vector<u8>& output, std::vector<u8>& inline_output) override; std::vector<u8>& inline_output) override;
void OnOpen(DeviceFD fd) override; void OnOpen(DeviceFD fd) override;
void OnClose(DeviceFD fd) override; void OnClose(DeviceFD fd) override;

View file

@ -25,7 +25,7 @@ nvmap::nvmap(Core::System& system_, NvCore::Container& container_)
nvmap::~nvmap() = default; nvmap::~nvmap() = default;
NvResult nvmap::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult nvmap::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
std::vector<u8>& output) { std::vector<u8>& output) {
switch (command.group) { switch (command.group) {
case 0x1: case 0x1:
@ -54,13 +54,13 @@ NvResult nvmap::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
return NvResult::NotImplemented; return NvResult::NotImplemented;
} }
NvResult nvmap::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult nvmap::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
const std::vector<u8>& inline_input, std::vector<u8>& output) { std::span<const u8> inline_input, std::vector<u8>& output) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented; return NvResult::NotImplemented;
} }
NvResult nvmap::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult nvmap::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
std::vector<u8>& output, std::vector<u8>& inline_output) { std::vector<u8>& output, std::vector<u8>& inline_output) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented; return NvResult::NotImplemented;
@ -69,7 +69,7 @@ NvResult nvmap::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
void nvmap::OnOpen(DeviceFD fd) {} void nvmap::OnOpen(DeviceFD fd) {}
void nvmap::OnClose(DeviceFD fd) {} void nvmap::OnClose(DeviceFD fd) {}
NvResult nvmap::IocCreate(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvmap::IocCreate(std::span<const u8> input, std::vector<u8>& output) {
IocCreateParams params; IocCreateParams params;
std::memcpy(&params, input.data(), sizeof(params)); std::memcpy(&params, input.data(), sizeof(params));
LOG_DEBUG(Service_NVDRV, "called, size=0x{:08X}", params.size); LOG_DEBUG(Service_NVDRV, "called, size=0x{:08X}", params.size);
@ -89,7 +89,7 @@ NvResult nvmap::IocCreate(const std::vector<u8>& input, std::vector<u8>& output)
return NvResult::Success; return NvResult::Success;
} }
NvResult nvmap::IocAlloc(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvmap::IocAlloc(std::span<const u8> input, std::vector<u8>& output) {
IocAllocParams params; IocAllocParams params;
std::memcpy(&params, input.data(), sizeof(params)); std::memcpy(&params, input.data(), sizeof(params));
LOG_DEBUG(Service_NVDRV, "called, addr={:X}", params.address); LOG_DEBUG(Service_NVDRV, "called, addr={:X}", params.address);
@ -137,7 +137,7 @@ NvResult nvmap::IocAlloc(const std::vector<u8>& input, std::vector<u8>& output)
return result; return result;
} }
NvResult nvmap::IocGetId(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvmap::IocGetId(std::span<const u8> input, std::vector<u8>& output) {
IocGetIdParams params; IocGetIdParams params;
std::memcpy(&params, input.data(), sizeof(params)); std::memcpy(&params, input.data(), sizeof(params));
@ -161,7 +161,7 @@ NvResult nvmap::IocGetId(const std::vector<u8>& input, std::vector<u8>& output)
return NvResult::Success; return NvResult::Success;
} }
NvResult nvmap::IocFromId(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvmap::IocFromId(std::span<const u8> input, std::vector<u8>& output) {
IocFromIdParams params; IocFromIdParams params;
std::memcpy(&params, input.data(), sizeof(params)); std::memcpy(&params, input.data(), sizeof(params));
@ -192,7 +192,7 @@ NvResult nvmap::IocFromId(const std::vector<u8>& input, std::vector<u8>& output)
return NvResult::Success; return NvResult::Success;
} }
NvResult nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvmap::IocParam(std::span<const u8> input, std::vector<u8>& output) {
enum class ParamTypes { Size = 1, Alignment = 2, Base = 3, Heap = 4, Kind = 5, Compr = 6 }; enum class ParamTypes { Size = 1, Alignment = 2, Base = 3, Heap = 4, Kind = 5, Compr = 6 };
IocParamParams params; IocParamParams params;
@ -241,7 +241,7 @@ NvResult nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output)
return NvResult::Success; return NvResult::Success;
} }
NvResult nvmap::IocFree(const std::vector<u8>& input, std::vector<u8>& output) { NvResult nvmap::IocFree(std::span<const u8> input, std::vector<u8>& output) {
IocFreeParams params; IocFreeParams params;
std::memcpy(&params, input.data(), sizeof(params)); std::memcpy(&params, input.data(), sizeof(params));

View file

@ -26,12 +26,12 @@ public:
nvmap(const nvmap&) = delete; nvmap(const nvmap&) = delete;
nvmap& operator=(const nvmap&) = delete; nvmap& operator=(const nvmap&) = delete;
NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
std::vector<u8>& output) override; std::vector<u8>& output) override;
NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
const std::vector<u8>& inline_input, std::vector<u8>& output) override; std::span<const u8> inline_input, std::vector<u8>& output) override;
NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output,
std::vector<u8>& output, std::vector<u8>& inline_output) override; std::vector<u8>& inline_output) override;
void OnOpen(DeviceFD fd) override; void OnOpen(DeviceFD fd) override;
void OnClose(DeviceFD fd) override; void OnClose(DeviceFD fd) override;
@ -106,12 +106,12 @@ private:
}; };
static_assert(sizeof(IocGetIdParams) == 8, "IocGetIdParams has wrong size"); static_assert(sizeof(IocGetIdParams) == 8, "IocGetIdParams has wrong size");
NvResult IocCreate(const std::vector<u8>& input, std::vector<u8>& output); NvResult IocCreate(std::span<const u8> input, std::vector<u8>& output);
NvResult IocAlloc(const std::vector<u8>& input, std::vector<u8>& output); NvResult IocAlloc(std::span<const u8> input, std::vector<u8>& output);
NvResult IocGetId(const std::vector<u8>& input, std::vector<u8>& output); NvResult IocGetId(std::span<const u8> input, std::vector<u8>& output);
NvResult IocFromId(const std::vector<u8>& input, std::vector<u8>& output); NvResult IocFromId(std::span<const u8> input, std::vector<u8>& output);
NvResult IocParam(const std::vector<u8>& input, std::vector<u8>& output); NvResult IocParam(std::span<const u8> input, std::vector<u8>& output);
NvResult IocFree(const std::vector<u8>& input, std::vector<u8>& output); NvResult IocFree(std::span<const u8> input, std::vector<u8>& output);
NvCore::Container& container; NvCore::Container& container;
NvCore::NvMap& file; NvCore::NvMap& file;

View file

@ -124,7 +124,7 @@ DeviceFD Module::Open(const std::string& device_name) {
return fd; return fd;
} }
NvResult Module::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Module::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
std::vector<u8>& output) { std::vector<u8>& output) {
if (fd < 0) { if (fd < 0) {
LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd); LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd);
@ -141,8 +141,8 @@ NvResult Module::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input
return itr->second->Ioctl1(fd, command, input, output); return itr->second->Ioctl1(fd, command, input, output);
} }
NvResult Module::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Module::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
const std::vector<u8>& inline_input, std::vector<u8>& output) { std::span<const u8> inline_input, std::vector<u8>& output) {
if (fd < 0) { if (fd < 0) {
LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd); LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd);
return NvResult::InvalidState; return NvResult::InvalidState;
@ -158,7 +158,7 @@ NvResult Module::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input
return itr->second->Ioctl2(fd, command, input, inline_input, output); return itr->second->Ioctl2(fd, command, input, inline_input, output);
} }
NvResult Module::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Module::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
std::vector<u8>& output, std::vector<u8>& inline_output) { std::vector<u8>& output, std::vector<u8>& inline_output) {
if (fd < 0) { if (fd < 0) {
LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd); LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd);

View file

@ -7,6 +7,7 @@
#include <functional> #include <functional>
#include <list> #include <list>
#include <memory> #include <memory>
#include <span>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
@ -79,14 +80,13 @@ public:
DeviceFD Open(const std::string& device_name); DeviceFD Open(const std::string& device_name);
/// Sends an ioctl command to the specified file descriptor. /// Sends an ioctl command to the specified file descriptor.
NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output);
std::vector<u8>& output);
NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
const std::vector<u8>& inline_input, std::vector<u8>& output); std::span<const u8> inline_input, std::vector<u8>& output);
NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output,
std::vector<u8>& output, std::vector<u8>& inline_output); std::vector<u8>& inline_output);
/// Closes a device file descriptor and returns operation success. /// Closes a device file descriptor and returns operation success.
NvResult Close(DeviceFD fd); NvResult Close(DeviceFD fd);

View file

@ -815,8 +815,8 @@ Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot,
void BufferQueueProducer::Transact(Kernel::HLERequestContext& ctx, TransactionId code, u32 flags) { void BufferQueueProducer::Transact(Kernel::HLERequestContext& ctx, TransactionId code, u32 flags) {
Status status{Status::NoError}; Status status{Status::NoError};
Parcel parcel_in{ctx.ReadBuffer()}; InputParcel parcel_in{ctx.ReadBuffer()};
Parcel parcel_out{}; OutputParcel parcel_out{};
switch (code) { switch (code) {
case TransactionId::Connect: { case TransactionId::Connect: {

View file

@ -9,7 +9,7 @@
namespace Service::android { namespace Service::android {
QueueBufferInput::QueueBufferInput(Parcel& parcel) { QueueBufferInput::QueueBufferInput(InputParcel& parcel) {
parcel.ReadFlattened(*this); parcel.ReadFlattened(*this);
} }

View file

@ -14,11 +14,11 @@
namespace Service::android { namespace Service::android {
class Parcel; class InputParcel;
#pragma pack(push, 1) #pragma pack(push, 1)
struct QueueBufferInput final { struct QueueBufferInput final {
explicit QueueBufferInput(Parcel& parcel); explicit QueueBufferInput(InputParcel& parcel);
void Deflate(s64* timestamp_, bool* is_auto_timestamp_, Common::Rectangle<s32>* crop_, void Deflate(s64* timestamp_, bool* is_auto_timestamp_, Common::Rectangle<s32>* crop_,
NativeWindowScalingMode* scaling_mode_, NativeWindowTransform* transform_, NativeWindowScalingMode* scaling_mode_, NativeWindowTransform* transform_,

View file

@ -4,6 +4,7 @@
#pragma once #pragma once
#include <memory> #include <memory>
#include <span>
#include <vector> #include <vector>
#include "common/alignment.h" #include "common/alignment.h"
@ -12,18 +13,17 @@
namespace Service::android { namespace Service::android {
class Parcel final { struct ParcelHeader {
u32 data_size;
u32 data_offset;
u32 objects_size;
u32 objects_offset;
};
static_assert(sizeof(ParcelHeader) == 16, "ParcelHeader has wrong size");
class InputParcel final {
public: public:
static constexpr std::size_t DefaultBufferSize = 0x40; explicit InputParcel(std::span<const u8> in_data) : read_buffer(std::move(in_data)) {
Parcel() : buffer(DefaultBufferSize) {}
template <typename T>
explicit Parcel(const T& out_data) : buffer(DefaultBufferSize) {
Write(out_data);
}
explicit Parcel(std::vector<u8> in_data) : buffer(std::move(in_data)) {
DeserializeHeader(); DeserializeHeader();
[[maybe_unused]] const std::u16string token = ReadInterfaceToken(); [[maybe_unused]] const std::u16string token = ReadInterfaceToken();
} }
@ -31,9 +31,9 @@ public:
template <typename T> template <typename T>
void Read(T& val) { void Read(T& val) {
static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable."); static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable.");
ASSERT(read_index + sizeof(T) <= buffer.size()); ASSERT(read_index + sizeof(T) <= read_buffer.size());
std::memcpy(&val, buffer.data() + read_index, sizeof(T)); std::memcpy(&val, read_buffer.data() + read_index, sizeof(T));
read_index += sizeof(T); read_index += sizeof(T);
read_index = Common::AlignUp(read_index, 4); read_index = Common::AlignUp(read_index, 4);
} }
@ -62,10 +62,10 @@ public:
template <typename T> template <typename T>
T ReadUnaligned() { T ReadUnaligned() {
static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable."); static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable.");
ASSERT(read_index + sizeof(T) <= buffer.size()); ASSERT(read_index + sizeof(T) <= read_buffer.size());
T val; T val;
std::memcpy(&val, buffer.data() + read_index, sizeof(T)); std::memcpy(&val, read_buffer.data() + read_index, sizeof(T));
read_index += sizeof(T); read_index += sizeof(T);
return val; return val;
} }
@ -101,6 +101,31 @@ public:
return token; return token;
} }
void DeserializeHeader() {
ASSERT(read_buffer.size() > sizeof(ParcelHeader));
ParcelHeader header{};
std::memcpy(&header, read_buffer.data(), sizeof(ParcelHeader));
read_index = header.data_offset;
}
private:
std::span<const u8> read_buffer;
std::size_t read_index = 0;
};
class OutputParcel final {
public:
static constexpr std::size_t DefaultBufferSize = 0x40;
OutputParcel() : buffer(DefaultBufferSize) {}
template <typename T>
explicit OutputParcel(const T& out_data) : buffer(DefaultBufferSize) {
Write(out_data);
}
template <typename T> template <typename T>
void Write(const T& val) { void Write(const T& val) {
static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable."); static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable.");
@ -133,40 +158,20 @@ public:
WriteObject(ptr.get()); WriteObject(ptr.get());
} }
void DeserializeHeader() {
ASSERT(buffer.size() > sizeof(Header));
Header header{};
std::memcpy(&header, buffer.data(), sizeof(Header));
read_index = header.data_offset;
}
std::vector<u8> Serialize() const { std::vector<u8> Serialize() const {
ASSERT(read_index == 0); ParcelHeader header{};
header.data_size = static_cast<u32>(write_index - sizeof(ParcelHeader));
Header header{}; header.data_offset = sizeof(ParcelHeader);
header.data_size = static_cast<u32>(write_index - sizeof(Header));
header.data_offset = sizeof(Header);
header.objects_size = 4; header.objects_size = 4;
header.objects_offset = static_cast<u32>(sizeof(Header) + header.data_size); header.objects_offset = static_cast<u32>(sizeof(ParcelHeader) + header.data_size);
std::memcpy(buffer.data(), &header, sizeof(Header)); std::memcpy(buffer.data(), &header, sizeof(ParcelHeader));
return buffer; return buffer;
} }
private: private:
struct Header {
u32 data_size;
u32 data_offset;
u32 objects_size;
u32 objects_offset;
};
static_assert(sizeof(Header) == 16, "ParcelHeader has wrong size");
mutable std::vector<u8> buffer; mutable std::vector<u8> buffer;
std::size_t read_index = 0; std::size_t write_index = sizeof(ParcelHeader);
std::size_t write_index = sizeof(Header);
}; };
} // namespace Service::android } // namespace Service::android

View file

@ -63,7 +63,7 @@ private:
return ctx.ReadBuffer(1); return ctx.ReadBuffer(1);
} }
return std::vector<u8>{}; return std::span<const u8>{};
}(); }();
LOG_DEBUG(Service_PREPO, LOG_DEBUG(Service_PREPO,
@ -90,7 +90,7 @@ private:
return ctx.ReadBuffer(1); return ctx.ReadBuffer(1);
} }
return std::vector<u8>{}; return std::span<const u8>{};
}(); }();
LOG_DEBUG(Service_PREPO, LOG_DEBUG(Service_PREPO,
@ -142,7 +142,7 @@ private:
return ctx.ReadBuffer(1); return ctx.ReadBuffer(1);
} }
return std::vector<u8>{}; return std::span<const u8>{};
}(); }();
LOG_DEBUG(Service_PREPO, "called, title_id={:016X}, data1_size={:016X}, data2_size={:016X}", LOG_DEBUG(Service_PREPO, "called, title_id={:016X}, data1_size={:016X}, data2_size={:016X}",
@ -166,7 +166,7 @@ private:
return ctx.ReadBuffer(1); return ctx.ReadBuffer(1);
} }
return std::vector<u8>{}; return std::span<const u8>{};
}(); }();
LOG_DEBUG(Service_PREPO, LOG_DEBUG(Service_PREPO,

View file

@ -208,7 +208,6 @@ void BSD::Bind(Kernel::HLERequestContext& ctx) {
const s32 fd = rp.Pop<s32>(); const s32 fd = rp.Pop<s32>();
LOG_DEBUG(Service, "called. fd={} addrlen={}", fd, ctx.GetReadBufferSize()); LOG_DEBUG(Service, "called. fd={} addrlen={}", fd, ctx.GetReadBufferSize());
BuildErrnoResponse(ctx, BindImpl(fd, ctx.ReadBuffer())); BuildErrnoResponse(ctx, BindImpl(fd, ctx.ReadBuffer()));
} }
@ -312,7 +311,7 @@ void BSD::SetSockOpt(Kernel::HLERequestContext& ctx) {
const u32 level = rp.Pop<u32>(); const u32 level = rp.Pop<u32>();
const OptName optname = static_cast<OptName>(rp.Pop<u32>()); const OptName optname = static_cast<OptName>(rp.Pop<u32>());
const std::vector<u8> buffer = ctx.ReadBuffer(); const auto buffer = ctx.ReadBuffer();
const u8* optval = buffer.empty() ? nullptr : buffer.data(); const u8* optval = buffer.empty() ? nullptr : buffer.data();
size_t optlen = buffer.size(); size_t optlen = buffer.size();
@ -489,7 +488,7 @@ std::pair<s32, Errno> BSD::SocketImpl(Domain domain, Type type, Protocol protoco
return {fd, Errno::SUCCESS}; return {fd, Errno::SUCCESS};
} }
std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::vector<u8> read_buffer, std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::span<const u8> read_buffer,
s32 nfds, s32 timeout) { s32 nfds, s32 timeout) {
if (write_buffer.size() < nfds * sizeof(PollFD)) { if (write_buffer.size() < nfds * sizeof(PollFD)) {
return {-1, Errno::INVAL}; return {-1, Errno::INVAL};
@ -584,7 +583,7 @@ std::pair<s32, Errno> BSD::AcceptImpl(s32 fd, std::vector<u8>& write_buffer) {
return {new_fd, Errno::SUCCESS}; return {new_fd, Errno::SUCCESS};
} }
Errno BSD::BindImpl(s32 fd, const std::vector<u8>& addr) { Errno BSD::BindImpl(s32 fd, std::span<const u8> addr) {
if (!IsFileDescriptorValid(fd)) { if (!IsFileDescriptorValid(fd)) {
return Errno::BADF; return Errno::BADF;
} }
@ -595,7 +594,7 @@ Errno BSD::BindImpl(s32 fd, const std::vector<u8>& addr) {
return Translate(file_descriptors[fd]->socket->Bind(Translate(addr_in))); return Translate(file_descriptors[fd]->socket->Bind(Translate(addr_in)));
} }
Errno BSD::ConnectImpl(s32 fd, const std::vector<u8>& addr) { Errno BSD::ConnectImpl(s32 fd, std::span<const u8> addr) {
if (!IsFileDescriptorValid(fd)) { if (!IsFileDescriptorValid(fd)) {
return Errno::BADF; return Errno::BADF;
} }
@ -800,15 +799,15 @@ std::pair<s32, Errno> BSD::RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& mess
return {ret, bsd_errno}; return {ret, bsd_errno};
} }
std::pair<s32, Errno> BSD::SendImpl(s32 fd, u32 flags, const std::vector<u8>& message) { std::pair<s32, Errno> BSD::SendImpl(s32 fd, u32 flags, std::span<const u8> message) {
if (!IsFileDescriptorValid(fd)) { if (!IsFileDescriptorValid(fd)) {
return {-1, Errno::BADF}; return {-1, Errno::BADF};
} }
return Translate(file_descriptors[fd]->socket->Send(message, flags)); return Translate(file_descriptors[fd]->socket->Send(message, flags));
} }
std::pair<s32, Errno> BSD::SendToImpl(s32 fd, u32 flags, const std::vector<u8>& message, std::pair<s32, Errno> BSD::SendToImpl(s32 fd, u32 flags, std::span<const u8> message,
const std::vector<u8>& addr) { std::span<const u8> addr) {
if (!IsFileDescriptorValid(fd)) { if (!IsFileDescriptorValid(fd)) {
return {-1, Errno::BADF}; return {-1, Errno::BADF};
} }

View file

@ -4,6 +4,7 @@
#pragma once #pragma once
#include <memory> #include <memory>
#include <span>
#include <vector> #include <vector>
#include "common/common_types.h" #include "common/common_types.h"
@ -44,7 +45,7 @@ private:
s32 nfds; s32 nfds;
s32 timeout; s32 timeout;
std::vector<u8> read_buffer; std::span<const u8> read_buffer;
std::vector<u8> write_buffer; std::vector<u8> write_buffer;
s32 ret{}; s32 ret{};
Errno bsd_errno{}; Errno bsd_errno{};
@ -65,7 +66,7 @@ private:
void Response(Kernel::HLERequestContext& ctx); void Response(Kernel::HLERequestContext& ctx);
s32 fd; s32 fd;
std::vector<u8> addr; std::span<const u8> addr;
Errno bsd_errno{}; Errno bsd_errno{};
}; };
@ -98,7 +99,7 @@ private:
s32 fd; s32 fd;
u32 flags; u32 flags;
std::vector<u8> message; std::span<const u8> message;
s32 ret{}; s32 ret{};
Errno bsd_errno{}; Errno bsd_errno{};
}; };
@ -109,8 +110,8 @@ private:
s32 fd; s32 fd;
u32 flags; u32 flags;
std::vector<u8> message; std::span<const u8> message;
std::vector<u8> addr; std::span<const u8> addr;
s32 ret{}; s32 ret{};
Errno bsd_errno{}; Errno bsd_errno{};
}; };
@ -143,11 +144,11 @@ private:
void ExecuteWork(Kernel::HLERequestContext& ctx, Work work); void ExecuteWork(Kernel::HLERequestContext& ctx, Work work);
std::pair<s32, Errno> SocketImpl(Domain domain, Type type, Protocol protocol); std::pair<s32, Errno> SocketImpl(Domain domain, Type type, Protocol protocol);
std::pair<s32, Errno> PollImpl(std::vector<u8>& write_buffer, std::vector<u8> read_buffer, std::pair<s32, Errno> PollImpl(std::vector<u8>& write_buffer, std::span<const u8> read_buffer,
s32 nfds, s32 timeout); s32 nfds, s32 timeout);
std::pair<s32, Errno> AcceptImpl(s32 fd, std::vector<u8>& write_buffer); std::pair<s32, Errno> AcceptImpl(s32 fd, std::vector<u8>& write_buffer);
Errno BindImpl(s32 fd, const std::vector<u8>& addr); Errno BindImpl(s32 fd, std::span<const u8> addr);
Errno ConnectImpl(s32 fd, const std::vector<u8>& addr); Errno ConnectImpl(s32 fd, std::span<const u8> addr);
Errno GetPeerNameImpl(s32 fd, std::vector<u8>& write_buffer); Errno GetPeerNameImpl(s32 fd, std::vector<u8>& write_buffer);
Errno GetSockNameImpl(s32 fd, std::vector<u8>& write_buffer); Errno GetSockNameImpl(s32 fd, std::vector<u8>& write_buffer);
Errno ListenImpl(s32 fd, s32 backlog); Errno ListenImpl(s32 fd, s32 backlog);
@ -157,9 +158,9 @@ private:
std::pair<s32, Errno> RecvImpl(s32 fd, u32 flags, std::vector<u8>& message); std::pair<s32, Errno> RecvImpl(s32 fd, u32 flags, std::vector<u8>& message);
std::pair<s32, Errno> RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& message, std::pair<s32, Errno> RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& message,
std::vector<u8>& addr); std::vector<u8>& addr);
std::pair<s32, Errno> SendImpl(s32 fd, u32 flags, const std::vector<u8>& message); std::pair<s32, Errno> SendImpl(s32 fd, u32 flags, std::span<const u8> message);
std::pair<s32, Errno> SendToImpl(s32 fd, u32 flags, const std::vector<u8>& message, std::pair<s32, Errno> SendToImpl(s32 fd, u32 flags, std::span<const u8> message,
const std::vector<u8>& addr); std::span<const u8> addr);
Errno CloseImpl(s32 fd); Errno CloseImpl(s32 fd);
s32 FindFreeFileDescriptorHandle() noexcept; s32 FindFreeFileDescriptorHandle() noexcept;

View file

@ -243,4 +243,4 @@ void SFDNSRES::GetAddrInfoRequestWithOptions(Kernel::HLERequestContext& ctx) {
rb.Push(0); rb.Push(0);
} }
} // namespace Service::Sockets } // namespace Service::Sockets

View file

@ -101,7 +101,7 @@ private:
void ImportServerPki(Kernel::HLERequestContext& ctx) { void ImportServerPki(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const auto certificate_format = rp.PopEnum<CertificateFormat>(); const auto certificate_format = rp.PopEnum<CertificateFormat>();
const auto pkcs_12_certificates = ctx.ReadBuffer(0); [[maybe_unused]] const auto pkcs_12_certificates = ctx.ReadBuffer(0);
constexpr u64 server_id = 0; constexpr u64 server_id = 0;
@ -113,13 +113,13 @@ private:
} }
void ImportClientPki(Kernel::HLERequestContext& ctx) { void ImportClientPki(Kernel::HLERequestContext& ctx) {
const auto pkcs_12_certificate = ctx.ReadBuffer(0); [[maybe_unused]] const auto pkcs_12_certificate = ctx.ReadBuffer(0);
const auto ascii_password = [&ctx] { [[maybe_unused]] const auto ascii_password = [&ctx] {
if (ctx.CanReadBuffer(1)) { if (ctx.CanReadBuffer(1)) {
return ctx.ReadBuffer(1); return ctx.ReadBuffer(1);
} }
return std::vector<u8>{}; return std::span<const u8>{};
}(); }();
constexpr u64 client_id = 0; constexpr u64 client_id = 0;

View file

@ -603,7 +603,7 @@ private:
return; return;
} }
const auto parcel = android::Parcel{NativeWindow{*buffer_queue_id}}; const auto parcel = android::OutputParcel{NativeWindow{*buffer_queue_id}};
const auto buffer_size = ctx.WriteBuffer(parcel.Serialize()); const auto buffer_size = ctx.WriteBuffer(parcel.Serialize());
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
@ -649,7 +649,7 @@ private:
return; return;
} }
const auto parcel = android::Parcel{NativeWindow{*buffer_queue_id}}; const auto parcel = android::OutputParcel{NativeWindow{*buffer_queue_id}};
const auto buffer_size = ctx.WriteBuffer(parcel.Serialize()); const auto buffer_size = ctx.WriteBuffer(parcel.Serialize());
IPC::ResponseBuilder rb{ctx, 6}; IPC::ResponseBuilder rb{ctx, 6};

View file

@ -550,7 +550,7 @@ std::pair<s32, Errno> Socket::RecvFrom(int flags, std::vector<u8>& message, Sock
return {-1, GetAndLogLastError()}; return {-1, GetAndLogLastError()};
} }
std::pair<s32, Errno> Socket::Send(const std::vector<u8>& message, int flags) { std::pair<s32, Errno> Socket::Send(std::span<const u8> message, int flags) {
ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max())); ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max()));
ASSERT(flags == 0); ASSERT(flags == 0);
@ -563,7 +563,7 @@ std::pair<s32, Errno> Socket::Send(const std::vector<u8>& message, int flags) {
return {-1, GetAndLogLastError()}; return {-1, GetAndLogLastError()};
} }
std::pair<s32, Errno> Socket::SendTo(u32 flags, const std::vector<u8>& message, std::pair<s32, Errno> Socket::SendTo(u32 flags, std::span<const u8> message,
const SockAddrIn* addr) { const SockAddrIn* addr) {
ASSERT(flags == 0); ASSERT(flags == 0);

View file

@ -182,7 +182,7 @@ std::pair<s32, Errno> ProxySocket::ReceivePacket(int flags, std::vector<u8>& mes
return {static_cast<u32>(read_bytes), Errno::SUCCESS}; return {static_cast<u32>(read_bytes), Errno::SUCCESS};
} }
std::pair<s32, Errno> ProxySocket::Send(const std::vector<u8>& message, int flags) { std::pair<s32, Errno> ProxySocket::Send(std::span<const u8> message, int flags) {
LOG_WARNING(Network, "(STUBBED) called"); LOG_WARNING(Network, "(STUBBED) called");
ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max())); ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max()));
ASSERT(flags == 0); ASSERT(flags == 0);
@ -200,7 +200,7 @@ void ProxySocket::SendPacket(ProxyPacket& packet) {
} }
} }
std::pair<s32, Errno> ProxySocket::SendTo(u32 flags, const std::vector<u8>& message, std::pair<s32, Errno> ProxySocket::SendTo(u32 flags, std::span<const u8> message,
const SockAddrIn* addr) { const SockAddrIn* addr) {
ASSERT(flags == 0); ASSERT(flags == 0);

View file

@ -4,6 +4,7 @@
#pragma once #pragma once
#include <mutex> #include <mutex>
#include <span>
#include <vector> #include <vector>
#include <queue> #include <queue>
@ -48,11 +49,11 @@ public:
std::pair<s32, Errno> ReceivePacket(int flags, std::vector<u8>& message, SockAddrIn* addr, std::pair<s32, Errno> ReceivePacket(int flags, std::vector<u8>& message, SockAddrIn* addr,
std::size_t max_length); std::size_t max_length);
std::pair<s32, Errno> Send(const std::vector<u8>& message, int flags) override; std::pair<s32, Errno> Send(std::span<const u8> message, int flags) override;
void SendPacket(ProxyPacket& packet); void SendPacket(ProxyPacket& packet);
std::pair<s32, Errno> SendTo(u32 flags, const std::vector<u8>& message, std::pair<s32, Errno> SendTo(u32 flags, std::span<const u8> message,
const SockAddrIn* addr) override; const SockAddrIn* addr) override;
Errno SetLinger(bool enable, u32 linger) override; Errno SetLinger(bool enable, u32 linger) override;

View file

@ -5,6 +5,7 @@
#include <map> #include <map>
#include <memory> #include <memory>
#include <span>
#include <utility> #include <utility>
#if defined(_WIN32) #if defined(_WIN32)
@ -66,9 +67,9 @@ public:
virtual std::pair<s32, Errno> RecvFrom(int flags, std::vector<u8>& message, virtual std::pair<s32, Errno> RecvFrom(int flags, std::vector<u8>& message,
SockAddrIn* addr) = 0; SockAddrIn* addr) = 0;
virtual std::pair<s32, Errno> Send(const std::vector<u8>& message, int flags) = 0; virtual std::pair<s32, Errno> Send(std::span<const u8> message, int flags) = 0;
virtual std::pair<s32, Errno> SendTo(u32 flags, const std::vector<u8>& message, virtual std::pair<s32, Errno> SendTo(u32 flags, std::span<const u8> message,
const SockAddrIn* addr) = 0; const SockAddrIn* addr) = 0;
virtual Errno SetLinger(bool enable, u32 linger) = 0; virtual Errno SetLinger(bool enable, u32 linger) = 0;
@ -138,9 +139,9 @@ public:
std::pair<s32, Errno> RecvFrom(int flags, std::vector<u8>& message, SockAddrIn* addr) override; std::pair<s32, Errno> RecvFrom(int flags, std::vector<u8>& message, SockAddrIn* addr) override;
std::pair<s32, Errno> Send(const std::vector<u8>& message, int flags) override; std::pair<s32, Errno> Send(std::span<const u8> message, int flags) override;
std::pair<s32, Errno> SendTo(u32 flags, const std::vector<u8>& message, std::pair<s32, Errno> SendTo(u32 flags, std::span<const u8> message,
const SockAddrIn* addr) override; const SockAddrIn* addr) override;
Errno SetLinger(bool enable, u32 linger) override; Errno SetLinger(bool enable, u32 linger) override;

View file

@ -312,7 +312,7 @@ void Reporter::SaveUnimplementedAppletReport(
} }
void Reporter::SavePlayReport(PlayReportType type, u64 title_id, void Reporter::SavePlayReport(PlayReportType type, u64 title_id,
const std::vector<std::vector<u8>>& data, const std::vector<std::span<const u8>>& data,
std::optional<u64> process_id, std::optional<u128> user_id) const { std::optional<u64> process_id, std::optional<u128> user_id) const {
if (!IsReportingEnabled()) { if (!IsReportingEnabled()) {
return; return;

View file

@ -5,6 +5,7 @@
#include <array> #include <array>
#include <optional> #include <optional>
#include <span>
#include <string> #include <string>
#include <vector> #include <vector>
#include "common/common_types.h" #include "common/common_types.h"
@ -56,7 +57,8 @@ public:
System, System,
}; };
void SavePlayReport(PlayReportType type, u64 title_id, const std::vector<std::vector<u8>>& data, void SavePlayReport(PlayReportType type, u64 title_id,
const std::vector<std::span<const u8>>& data,
std::optional<u64> process_id = {}, std::optional<u128> user_id = {}) const; std::optional<u64> process_id = {}, std::optional<u128> user_id = {}) const;
// Used by error applet // Used by error applet

View file

@ -668,12 +668,10 @@ std::string Joycons::JoyconName(Joycon::ControllerType type) const {
return "Right Joycon"; return "Right Joycon";
case Joycon::ControllerType::Pro: case Joycon::ControllerType::Pro:
return "Pro Controller"; return "Pro Controller";
case Joycon::ControllerType::Grip:
return "Grip Controller";
case Joycon::ControllerType::Dual: case Joycon::ControllerType::Dual:
return "Dual Joycon"; return "Dual Joycon";
default: default:
return "Unknown Joycon"; return "Unknown Switch Controller";
} }
} }
} // namespace InputCommon } // namespace InputCommon

View file

@ -15,7 +15,7 @@ using SerialNumber = std::array<u8, 15>;
struct Battery; struct Battery;
struct Color; struct Color;
struct MotionData; struct MotionData;
enum class ControllerType; enum class ControllerType : u8;
enum class DriverResult; enum class DriverResult;
enum class IrsResolution; enum class IrsResolution;
class JoyconDriver; class JoyconDriver;

View file

@ -162,14 +162,14 @@ void JoyconDriver::InputThread(std::stop_token stop_token) {
} }
void JoyconDriver::OnNewData(std::span<u8> buffer) { void JoyconDriver::OnNewData(std::span<u8> buffer) {
const auto report_mode = static_cast<InputReport>(buffer[0]); const auto report_mode = static_cast<ReportMode>(buffer[0]);
// Packages can be a litte bit inconsistent. Average the delta time to provide a smoother motion // Packages can be a litte bit inconsistent. Average the delta time to provide a smoother motion
// experience // experience
switch (report_mode) { switch (report_mode) {
case InputReport::STANDARD_FULL_60HZ: case ReportMode::STANDARD_FULL_60HZ:
case InputReport::NFC_IR_MODE_60HZ: case ReportMode::NFC_IR_MODE_60HZ:
case InputReport::SIMPLE_HID_MODE: { case ReportMode::SIMPLE_HID_MODE: {
const auto now = std::chrono::steady_clock::now(); const auto now = std::chrono::steady_clock::now();
const auto new_delta_time = static_cast<u64>( const auto new_delta_time = static_cast<u64>(
std::chrono::duration_cast<std::chrono::microseconds>(now - last_update).count()); std::chrono::duration_cast<std::chrono::microseconds>(now - last_update).count());
@ -190,7 +190,7 @@ void JoyconDriver::OnNewData(std::span<u8> buffer) {
}; };
// TODO: Remove this when calibration is properly loaded and not calculated // TODO: Remove this when calibration is properly loaded and not calculated
if (ring_connected && report_mode == InputReport::STANDARD_FULL_60HZ) { if (ring_connected && report_mode == ReportMode::STANDARD_FULL_60HZ) {
InputReportActive data{}; InputReportActive data{};
memcpy(&data, buffer.data(), sizeof(InputReportActive)); memcpy(&data, buffer.data(), sizeof(InputReportActive));
calibration_protocol->GetRingCalibration(ring_calibration, data.ring_input); calibration_protocol->GetRingCalibration(ring_calibration, data.ring_input);
@ -228,16 +228,16 @@ void JoyconDriver::OnNewData(std::span<u8> buffer) {
} }
switch (report_mode) { switch (report_mode) {
case InputReport::STANDARD_FULL_60HZ: case ReportMode::STANDARD_FULL_60HZ:
joycon_poller->ReadActiveMode(buffer, motion_status, ring_status); joycon_poller->ReadActiveMode(buffer, motion_status, ring_status);
break; break;
case InputReport::NFC_IR_MODE_60HZ: case ReportMode::NFC_IR_MODE_60HZ:
joycon_poller->ReadNfcIRMode(buffer, motion_status); joycon_poller->ReadNfcIRMode(buffer, motion_status);
break; break;
case InputReport::SIMPLE_HID_MODE: case ReportMode::SIMPLE_HID_MODE:
joycon_poller->ReadPassiveMode(buffer); joycon_poller->ReadPassiveMode(buffer);
break; break;
case InputReport::SUBCMD_REPLY: case ReportMode::SUBCMD_REPLY:
LOG_DEBUG(Input, "Unhandled command reply"); LOG_DEBUG(Input, "Unhandled command reply");
break; break;
default: default:

View file

@ -22,12 +22,9 @@ void JoyconCommonProtocol::SetNonBlocking() {
} }
DriverResult JoyconCommonProtocol::GetDeviceType(ControllerType& controller_type) { DriverResult JoyconCommonProtocol::GetDeviceType(ControllerType& controller_type) {
std::array<u8, 1> buffer{}; const auto result = ReadSPI(SpiAddress::DEVICE_TYPE, controller_type);
const auto result = ReadRawSPI(SpiAddress::DEVICE_TYPE, buffer);
controller_type = ControllerType::None;
if (result == DriverResult::Success) { if (result == DriverResult::Success) {
controller_type = static_cast<ControllerType>(buffer[0]);
// Fallback to 3rd party pro controllers // Fallback to 3rd party pro controllers
if (controller_type == ControllerType::None) { if (controller_type == ControllerType::None) {
controller_type = ControllerType::Pro; controller_type = ControllerType::Pro;
@ -40,6 +37,7 @@ DriverResult JoyconCommonProtocol::GetDeviceType(ControllerType& controller_type
DriverResult JoyconCommonProtocol::CheckDeviceAccess(SDL_hid_device_info* device_info) { DriverResult JoyconCommonProtocol::CheckDeviceAccess(SDL_hid_device_info* device_info) {
ControllerType controller_type{ControllerType::None}; ControllerType controller_type{ControllerType::None};
const auto result = GetDeviceType(controller_type); const auto result = GetDeviceType(controller_type);
if (result != DriverResult::Success || controller_type == ControllerType::None) { if (result != DriverResult::Success || controller_type == ControllerType::None) {
return DriverResult::UnsupportedControllerType; return DriverResult::UnsupportedControllerType;
} }
@ -62,7 +60,7 @@ DriverResult JoyconCommonProtocol::SetReportMode(ReportMode report_mode) {
return SendSubCommand(SubCommand::SET_REPORT_MODE, buffer); return SendSubCommand(SubCommand::SET_REPORT_MODE, buffer);
} }
DriverResult JoyconCommonProtocol::SendData(std::span<const u8> buffer) { DriverResult JoyconCommonProtocol::SendRawData(std::span<const u8> buffer) {
const auto result = SDL_hid_write(hidapi_handle->handle, buffer.data(), buffer.size()); const auto result = SDL_hid_write(hidapi_handle->handle, buffer.data(), buffer.size());
if (result == -1) { if (result == -1) {
@ -72,15 +70,15 @@ DriverResult JoyconCommonProtocol::SendData(std::span<const u8> buffer) {
return DriverResult::Success; return DriverResult::Success;
} }
DriverResult JoyconCommonProtocol::GetSubCommandResponse(SubCommand sc, std::vector<u8>& output) { DriverResult JoyconCommonProtocol::GetSubCommandResponse(SubCommand sc,
SubCommandResponse& output) {
constexpr int timeout_mili = 66; constexpr int timeout_mili = 66;
constexpr int MaxTries = 15; constexpr int MaxTries = 15;
int tries = 0; int tries = 0;
output.resize(MaxSubCommandResponseSize);
do { do {
int result = SDL_hid_read_timeout(hidapi_handle->handle, output.data(), int result = SDL_hid_read_timeout(hidapi_handle->handle, reinterpret_cast<u8*>(&output),
MaxSubCommandResponseSize, timeout_mili); sizeof(SubCommandResponse), timeout_mili);
if (result < 1) { if (result < 1) {
LOG_ERROR(Input, "No response from joycon"); LOG_ERROR(Input, "No response from joycon");
@ -88,27 +86,28 @@ DriverResult JoyconCommonProtocol::GetSubCommandResponse(SubCommand sc, std::vec
if (tries++ > MaxTries) { if (tries++ > MaxTries) {
return DriverResult::Timeout; return DriverResult::Timeout;
} }
} while (output[0] != 0x21 && output[14] != static_cast<u8>(sc)); } while (output.input_report.report_mode != ReportMode::SUBCMD_REPLY &&
output.sub_command != sc);
if (output[0] != 0x21 && output[14] != static_cast<u8>(sc)) {
return DriverResult::WrongReply;
}
return DriverResult::Success; return DriverResult::Success;
} }
DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, std::span<const u8> buffer, DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, std::span<const u8> buffer,
std::vector<u8>& output) { SubCommandResponse& output) {
std::vector<u8> local_buffer(MaxResponseSize); SubCommandPacket packet{
.output_report = OutputReport::RUMBLE_AND_SUBCMD,
.packet_counter = GetCounter(),
.sub_command = sc,
.command_data = {},
};
local_buffer[0] = static_cast<u8>(OutputReport::RUMBLE_AND_SUBCMD); if (buffer.size() > packet.command_data.size()) {
local_buffer[1] = GetCounter(); return DriverResult::InvalidParameters;
local_buffer[10] = static_cast<u8>(sc);
for (std::size_t i = 0; i < buffer.size(); ++i) {
local_buffer[11 + i] = buffer[i];
} }
auto result = SendData(local_buffer); memcpy(packet.command_data.data(), buffer.data(), buffer.size());
auto result = SendData(packet);
if (result != DriverResult::Success) { if (result != DriverResult::Success) {
return result; return result;
@ -120,46 +119,57 @@ DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, std::span<const
} }
DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, std::span<const u8> buffer) { DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, std::span<const u8> buffer) {
std::vector<u8> output; SubCommandResponse output{};
return SendSubCommand(sc, buffer, output); return SendSubCommand(sc, buffer, output);
} }
DriverResult JoyconCommonProtocol::SendMCUCommand(SubCommand sc, std::span<const u8> buffer) { DriverResult JoyconCommonProtocol::SendMCUCommand(SubCommand sc, std::span<const u8> buffer) {
std::vector<u8> local_buffer(MaxResponseSize); SubCommandPacket packet{
.output_report = OutputReport::MCU_DATA,
.packet_counter = GetCounter(),
.sub_command = sc,
.command_data = {},
};
local_buffer[0] = static_cast<u8>(OutputReport::MCU_DATA); if (buffer.size() > packet.command_data.size()) {
local_buffer[1] = GetCounter(); return DriverResult::InvalidParameters;
local_buffer[10] = static_cast<u8>(sc);
for (std::size_t i = 0; i < buffer.size(); ++i) {
local_buffer[11 + i] = buffer[i];
} }
return SendData(local_buffer); memcpy(packet.command_data.data(), buffer.data(), buffer.size());
return SendData(packet);
} }
DriverResult JoyconCommonProtocol::SendVibrationReport(std::span<const u8> buffer) { DriverResult JoyconCommonProtocol::SendVibrationReport(std::span<const u8> buffer) {
std::vector<u8> local_buffer(MaxResponseSize); VibrationPacket packet{
.output_report = OutputReport::RUMBLE_ONLY,
.packet_counter = GetCounter(),
.vibration_data = {},
};
local_buffer[0] = static_cast<u8>(Joycon::OutputReport::RUMBLE_ONLY); if (buffer.size() > packet.vibration_data.size()) {
local_buffer[1] = GetCounter(); return DriverResult::InvalidParameters;
}
memcpy(local_buffer.data() + 2, buffer.data(), buffer.size()); memcpy(packet.vibration_data.data(), buffer.data(), buffer.size());
return SendData(local_buffer); return SendData(packet);
} }
DriverResult JoyconCommonProtocol::ReadRawSPI(SpiAddress addr, std::span<u8> output) { DriverResult JoyconCommonProtocol::ReadRawSPI(SpiAddress addr, std::span<u8> output) {
constexpr std::size_t HeaderSize = 20; constexpr std::size_t HeaderSize = 5;
constexpr std::size_t MaxTries = 10; constexpr std::size_t MaxTries = 10;
const auto size = output.size();
std::size_t tries = 0; std::size_t tries = 0;
std::array<u8, 5> buffer = {0x00, 0x00, 0x00, 0x00, static_cast<u8>(size)}; SubCommandResponse response{};
std::vector<u8> local_buffer{}; std::array<u8, sizeof(ReadSpiPacket)> buffer{};
const ReadSpiPacket packet_data{
.spi_address = addr,
.size = static_cast<u8>(output.size()),
};
buffer[0] = static_cast<u8>(static_cast<u16>(addr) & 0x00FF); memcpy(buffer.data(), &packet_data, sizeof(ReadSpiPacket));
buffer[1] = static_cast<u8>((static_cast<u16>(addr) & 0xFF00) >> 8);
do { do {
const auto result = SendSubCommand(SubCommand::SPI_FLASH_READ, buffer, local_buffer); const auto result = SendSubCommand(SubCommand::SPI_FLASH_READ, buffer, response);
if (result != DriverResult::Success) { if (result != DriverResult::Success) {
return result; return result;
} }
@ -167,14 +177,14 @@ DriverResult JoyconCommonProtocol::ReadRawSPI(SpiAddress addr, std::span<u8> out
if (tries++ > MaxTries) { if (tries++ > MaxTries) {
return DriverResult::Timeout; return DriverResult::Timeout;
} }
} while (local_buffer[15] != buffer[0] || local_buffer[16] != buffer[1]); } while (response.spi_address != addr);
if (local_buffer.size() < size + HeaderSize) { if (response.command_data.size() < packet_data.size + HeaderSize) {
return DriverResult::WrongReply; return DriverResult::WrongReply;
} }
// Remove header from output // Remove header from output
memcpy(output.data(), local_buffer.data() + HeaderSize, size); memcpy(output.data(), response.command_data.data() + HeaderSize, packet_data.size);
return DriverResult::Success; return DriverResult::Success;
} }
@ -183,7 +193,7 @@ DriverResult JoyconCommonProtocol::EnableMCU(bool enable) {
const auto result = SendSubCommand(SubCommand::SET_MCU_STATE, mcu_state); const auto result = SendSubCommand(SubCommand::SET_MCU_STATE, mcu_state);
if (result != DriverResult::Success) { if (result != DriverResult::Success) {
LOG_ERROR(Input, "SendMCUData failed with error {}", result); LOG_ERROR(Input, "Failed with error {}", result);
} }
return result; return result;
@ -198,22 +208,21 @@ DriverResult JoyconCommonProtocol::ConfigureMCU(const MCUConfig& config) {
const auto result = SendSubCommand(SubCommand::SET_MCU_CONFIG, config_buffer); const auto result = SendSubCommand(SubCommand::SET_MCU_CONFIG, config_buffer);
if (result != DriverResult::Success) { if (result != DriverResult::Success) {
LOG_ERROR(Input, "Set MCU config failed with error {}", result); LOG_ERROR(Input, "Failed with error {}", result);
} }
return result; return result;
} }
DriverResult JoyconCommonProtocol::GetMCUDataResponse(ReportMode report_mode_, DriverResult JoyconCommonProtocol::GetMCUDataResponse(ReportMode report_mode,
std::vector<u8>& output) { MCUCommandResponse& output) {
const int report_mode = static_cast<u8>(report_mode_);
constexpr int TimeoutMili = 200; constexpr int TimeoutMili = 200;
constexpr int MaxTries = 9; constexpr int MaxTries = 9;
int tries = 0; int tries = 0;
output.resize(0x170);
do { do {
int result = SDL_hid_read_timeout(hidapi_handle->handle, output.data(), 0x170, TimeoutMili); int result = SDL_hid_read_timeout(hidapi_handle->handle, reinterpret_cast<u8*>(&output),
sizeof(MCUCommandResponse), TimeoutMili);
if (result < 1) { if (result < 1) {
LOG_ERROR(Input, "No response from joycon attempt {}", tries); LOG_ERROR(Input, "No response from joycon attempt {}", tries);
@ -221,28 +230,29 @@ DriverResult JoyconCommonProtocol::GetMCUDataResponse(ReportMode report_mode_,
if (tries++ > MaxTries) { if (tries++ > MaxTries) {
return DriverResult::Timeout; return DriverResult::Timeout;
} }
} while (output[0] != report_mode || output[49] == 0xFF); } while (output.input_report.report_mode != report_mode ||
output.mcu_report == MCUReport::EmptyAwaitingCmd);
if (output[0] != report_mode || output[49] == 0xFF) {
return DriverResult::WrongReply;
}
return DriverResult::Success; return DriverResult::Success;
} }
DriverResult JoyconCommonProtocol::SendMCUData(ReportMode report_mode, SubCommand sc, DriverResult JoyconCommonProtocol::SendMCUData(ReportMode report_mode, SubCommand sc,
std::span<const u8> buffer, std::span<const u8> buffer,
std::vector<u8>& output) { MCUCommandResponse& output) {
std::vector<u8> local_buffer(MaxResponseSize); SubCommandPacket packet{
.output_report = OutputReport::MCU_DATA,
.packet_counter = GetCounter(),
.sub_command = sc,
.command_data = {},
};
local_buffer[0] = static_cast<u8>(OutputReport::MCU_DATA); if (buffer.size() > packet.command_data.size()) {
local_buffer[1] = GetCounter(); return DriverResult::InvalidParameters;
local_buffer[9] = static_cast<u8>(sc);
for (std::size_t i = 0; i < buffer.size(); ++i) {
local_buffer[10 + i] = buffer[i];
} }
auto result = SendData(local_buffer); memcpy(packet.command_data.data(), buffer.data(), buffer.size());
auto result = SendData(packet);
if (result != DriverResult::Success) { if (result != DriverResult::Success) {
return result; return result;
@ -254,7 +264,7 @@ DriverResult JoyconCommonProtocol::SendMCUData(ReportMode report_mode, SubComman
} }
DriverResult JoyconCommonProtocol::WaitSetMCUMode(ReportMode report_mode, MCUMode mode) { DriverResult JoyconCommonProtocol::WaitSetMCUMode(ReportMode report_mode, MCUMode mode) {
std::vector<u8> output; MCUCommandResponse output{};
constexpr std::size_t MaxTries{8}; constexpr std::size_t MaxTries{8};
std::size_t tries{}; std::size_t tries{};
@ -269,7 +279,8 @@ DriverResult JoyconCommonProtocol::WaitSetMCUMode(ReportMode report_mode, MCUMod
if (tries++ > MaxTries) { if (tries++ > MaxTries) {
return DriverResult::WrongReply; return DriverResult::WrongReply;
} }
} while (output[49] != 1 || output[56] != static_cast<u8>(mode)); } while (output.mcu_report != MCUReport::StateReport ||
output.mcu_data[6] != static_cast<u8>(mode));
return DriverResult::Success; return DriverResult::Success;
} }

View file

@ -57,22 +57,30 @@ public:
* Sends data to the joycon device * Sends data to the joycon device
* @param buffer data to be send * @param buffer data to be send
*/ */
DriverResult SendData(std::span<const u8> buffer); DriverResult SendRawData(std::span<const u8> buffer);
template <typename Output>
requires std::is_trivially_copyable_v<Output> DriverResult SendData(const Output& output) {
std::array<u8, sizeof(Output)> buffer;
std::memcpy(buffer.data(), &output, sizeof(Output));
return SendRawData(buffer);
}
/** /**
* Waits for incoming data of the joycon device that matchs the subcommand * Waits for incoming data of the joycon device that matchs the subcommand
* @param sub_command type of data to be returned * @param sub_command type of data to be returned
* @returns a buffer containing the responce * @returns a buffer containing the response
*/ */
DriverResult GetSubCommandResponse(SubCommand sub_command, std::vector<u8>& output); DriverResult GetSubCommandResponse(SubCommand sub_command, SubCommandResponse& output);
/** /**
* Sends a sub command to the device and waits for it's reply * Sends a sub command to the device and waits for it's reply
* @param sc sub command to be send * @param sc sub command to be send
* @param buffer data to be send * @param buffer data to be send
* @returns output buffer containing the responce * @returns output buffer containing the response
*/ */
DriverResult SendSubCommand(SubCommand sc, std::span<const u8> buffer, std::vector<u8>& output); DriverResult SendSubCommand(SubCommand sc, std::span<const u8> buffer,
SubCommandResponse& output);
/** /**
* Sends a sub command to the device and waits for it's reply and ignores the output * Sends a sub command to the device and waits for it's reply and ignores the output
@ -97,14 +105,14 @@ public:
/** /**
* Reads the SPI memory stored on the joycon * Reads the SPI memory stored on the joycon
* @param Initial address location * @param Initial address location
* @returns output buffer containing the responce * @returns output buffer containing the response
*/ */
DriverResult ReadRawSPI(SpiAddress addr, std::span<u8> output); DriverResult ReadRawSPI(SpiAddress addr, std::span<u8> output);
/** /**
* Reads the SPI memory stored on the joycon * Reads the SPI memory stored on the joycon
* @param Initial address location * @param Initial address location
* @returns output object containing the responce * @returns output object containing the response
*/ */
template <typename Output> template <typename Output>
requires std::is_trivially_copyable_v<Output> DriverResult ReadSPI(SpiAddress addr, requires std::is_trivially_copyable_v<Output> DriverResult ReadSPI(SpiAddress addr,
@ -136,19 +144,19 @@ public:
/** /**
* Waits until there's MCU data available. On timeout returns error * Waits until there's MCU data available. On timeout returns error
* @param report mode of the expected reply * @param report mode of the expected reply
* @returns a buffer containing the responce * @returns a buffer containing the response
*/ */
DriverResult GetMCUDataResponse(ReportMode report_mode_, std::vector<u8>& output); DriverResult GetMCUDataResponse(ReportMode report_mode_, MCUCommandResponse& output);
/** /**
* Sends data to the MCU chip and waits for it's reply * Sends data to the MCU chip and waits for it's reply
* @param report mode of the expected reply * @param report mode of the expected reply
* @param sub command to be send * @param sub command to be send
* @param buffer data to be send * @param buffer data to be send
* @returns output buffer containing the responce * @returns output buffer containing the response
*/ */
DriverResult SendMCUData(ReportMode report_mode, SubCommand sc, std::span<const u8> buffer, DriverResult SendMCUData(ReportMode report_mode, SubCommand sc, std::span<const u8> buffer,
std::vector<u8>& output); MCUCommandResponse& output);
/** /**
* Wait's until the MCU chip is on the specified mode * Wait's until the MCU chip is on the specified mode

View file

@ -32,13 +32,13 @@ DriverResult GenericProtocol::TriggersElapsed() {
DriverResult GenericProtocol::GetDeviceInfo(DeviceInfo& device_info) { DriverResult GenericProtocol::GetDeviceInfo(DeviceInfo& device_info) {
ScopedSetBlocking sb(this); ScopedSetBlocking sb(this);
std::vector<u8> output; SubCommandResponse output{};
const auto result = SendSubCommand(SubCommand::REQ_DEV_INFO, {}, output); const auto result = SendSubCommand(SubCommand::REQ_DEV_INFO, {}, output);
device_info = {}; device_info = {};
if (result == DriverResult::Success) { if (result == DriverResult::Success) {
memcpy(&device_info, output.data(), sizeof(DeviceInfo)); device_info = output.device_info;
} }
return result; return result;

View file

@ -132,7 +132,7 @@ DriverResult IrsProtocol::RequestImage(std::span<u8> buffer) {
DriverResult IrsProtocol::ConfigureIrs() { DriverResult IrsProtocol::ConfigureIrs() {
LOG_DEBUG(Input, "Configure IRS"); LOG_DEBUG(Input, "Configure IRS");
constexpr std::size_t max_tries = 28; constexpr std::size_t max_tries = 28;
std::vector<u8> output; SubCommandResponse output{};
std::size_t tries = 0; std::size_t tries = 0;
const IrsConfigure irs_configuration{ const IrsConfigure irs_configuration{
@ -158,7 +158,7 @@ DriverResult IrsProtocol::ConfigureIrs() {
if (tries++ >= max_tries) { if (tries++ >= max_tries) {
return DriverResult::WrongReply; return DriverResult::WrongReply;
} }
} while (output[15] != 0x0b); } while (output.command_data[0] != 0x0b);
return DriverResult::Success; return DriverResult::Success;
} }
@ -167,7 +167,7 @@ DriverResult IrsProtocol::WriteRegistersStep1() {
LOG_DEBUG(Input, "WriteRegistersStep1"); LOG_DEBUG(Input, "WriteRegistersStep1");
DriverResult result{DriverResult::Success}; DriverResult result{DriverResult::Success};
constexpr std::size_t max_tries = 28; constexpr std::size_t max_tries = 28;
std::vector<u8> output; SubCommandResponse output{};
std::size_t tries = 0; std::size_t tries = 0;
const IrsWriteRegisters irs_registers{ const IrsWriteRegisters irs_registers{
@ -218,7 +218,8 @@ DriverResult IrsProtocol::WriteRegistersStep1() {
if (tries++ >= max_tries) { if (tries++ >= max_tries) {
return DriverResult::WrongReply; return DriverResult::WrongReply;
} }
} while (!(output[15] == 0x13 && output[17] == 0x07) && output[15] != 0x23); } while (!(output.command_data[0] == 0x13 && output.command_data[2] == 0x07) &&
output.command_data[0] != 0x23);
return DriverResult::Success; return DriverResult::Success;
} }
@ -226,7 +227,7 @@ DriverResult IrsProtocol::WriteRegistersStep1() {
DriverResult IrsProtocol::WriteRegistersStep2() { DriverResult IrsProtocol::WriteRegistersStep2() {
LOG_DEBUG(Input, "WriteRegistersStep2"); LOG_DEBUG(Input, "WriteRegistersStep2");
constexpr std::size_t max_tries = 28; constexpr std::size_t max_tries = 28;
std::vector<u8> output; SubCommandResponse output{};
std::size_t tries = 0; std::size_t tries = 0;
const IrsWriteRegisters irs_registers{ const IrsWriteRegisters irs_registers{
@ -260,7 +261,7 @@ DriverResult IrsProtocol::WriteRegistersStep2() {
if (tries++ >= max_tries) { if (tries++ >= max_tries) {
return DriverResult::WrongReply; return DriverResult::WrongReply;
} }
} while (output[15] != 0x13 && output[15] != 0x23); } while (output.command_data[0] != 0x13 && output.command_data[0] != 0x23);
return DriverResult::Success; return DriverResult::Success;
} }

View file

@ -19,20 +19,24 @@
namespace InputCommon::Joycon { namespace InputCommon::Joycon {
constexpr u32 MaxErrorCount = 50; constexpr u32 MaxErrorCount = 50;
constexpr u32 MaxBufferSize = 368; constexpr u32 MaxBufferSize = 368;
constexpr u32 MaxResponseSize = 49;
constexpr u32 MaxSubCommandResponseSize = 64;
constexpr std::array<u8, 8> DefaultVibrationBuffer{0x0, 0x1, 0x40, 0x40, 0x0, 0x1, 0x40, 0x40}; constexpr std::array<u8, 8> DefaultVibrationBuffer{0x0, 0x1, 0x40, 0x40, 0x0, 0x1, 0x40, 0x40};
using MacAddress = std::array<u8, 6>; using MacAddress = std::array<u8, 6>;
using SerialNumber = std::array<u8, 15>; using SerialNumber = std::array<u8, 15>;
enum class ControllerType { enum class ControllerType : u8 {
None, None = 0x00,
Left, Left = 0x01,
Right, Right = 0x02,
Pro, Pro = 0x03,
Grip, Dual = 0x05, // TODO: Verify this id
Dual, LarkHvc1 = 0x07,
LarkHvc2 = 0x08,
LarkNesLeft = 0x09,
LarkNesRight = 0x0A,
Lucia = 0x0B,
Lagon = 0x0C,
Lager = 0x0D,
}; };
enum class PadAxes { enum class PadAxes {
@ -99,14 +103,6 @@ enum class OutputReport : u8 {
USB_CMD = 0x80, USB_CMD = 0x80,
}; };
enum class InputReport : u8 {
SUBCMD_REPLY = 0x21,
STANDARD_FULL_60HZ = 0x30,
NFC_IR_MODE_60HZ = 0x31,
SIMPLE_HID_MODE = 0x3F,
INPUT_USB_RESPONSE = 0x81,
};
enum class FeatureReport : u8 { enum class FeatureReport : u8 {
Last_SUBCMD = 0x02, Last_SUBCMD = 0x02,
OTA_GW_UPGRADE = 0x70, OTA_GW_UPGRADE = 0x70,
@ -143,9 +139,10 @@ enum class SubCommand : u8 {
ENABLE_VIBRATION = 0x48, ENABLE_VIBRATION = 0x48,
GET_REGULATED_VOLTAGE = 0x50, GET_REGULATED_VOLTAGE = 0x50,
SET_EXTERNAL_CONFIG = 0x58, SET_EXTERNAL_CONFIG = 0x58,
UNKNOWN_RINGCON = 0x59, GET_EXTERNAL_DEVICE_INFO = 0x59,
UNKNOWN_RINGCON2 = 0x5A, ENABLE_EXTERNAL_POLLING = 0x5A,
UNKNOWN_RINGCON3 = 0x5C, DISABLE_EXTERNAL_POLLING = 0x5B,
SET_EXTERNAL_FORMAT_CONFIG = 0x5C,
}; };
enum class UsbSubCommand : u8 { enum class UsbSubCommand : u8 {
@ -164,20 +161,26 @@ enum class CalibrationMagic : u8 {
USR_MAGIC_1 = 0xA1, USR_MAGIC_1 = 0xA1,
}; };
enum class SpiAddress { enum class SpiAddress : u16 {
SERIAL_NUMBER = 0X6000, MAGIC = 0x0000,
DEVICE_TYPE = 0X6012, MAC_ADDRESS = 0x0015,
COLOR_EXIST = 0X601B, PAIRING_INFO = 0x2000,
FACT_LEFT_DATA = 0X603d, SHIPMENT = 0x5000,
FACT_RIGHT_DATA = 0X6046, SERIAL_NUMBER = 0x6000,
COLOR_DATA = 0X6050, DEVICE_TYPE = 0x6012,
FACT_IMU_DATA = 0X6020, FORMAT_VERSION = 0x601B,
USER_LEFT_MAGIC = 0X8010, FACT_IMU_DATA = 0x6020,
USER_LEFT_DATA = 0X8012, FACT_LEFT_DATA = 0x603d,
USER_RIGHT_MAGIC = 0X801B, FACT_RIGHT_DATA = 0x6046,
USER_RIGHT_DATA = 0X801D, COLOR_DATA = 0x6050,
USER_IMU_MAGIC = 0X8026, DESIGN_VARIATION = 0x605C,
USER_IMU_DATA = 0X8028, SENSOR_DATA = 0x6080,
USER_LEFT_MAGIC = 0x8010,
USER_LEFT_DATA = 0x8012,
USER_RIGHT_MAGIC = 0x801B,
USER_RIGHT_DATA = 0x801D,
USER_IMU_MAGIC = 0x8026,
USER_IMU_DATA = 0x8028,
}; };
enum class ReportMode : u8 { enum class ReportMode : u8 {
@ -185,10 +188,12 @@ enum class ReportMode : u8 {
ACTIVE_POLLING_NFC_IR_CAMERA_CONFIGURATION = 0x01, ACTIVE_POLLING_NFC_IR_CAMERA_CONFIGURATION = 0x01,
ACTIVE_POLLING_NFC_IR_CAMERA_DATA_CONFIGURATION = 0x02, ACTIVE_POLLING_NFC_IR_CAMERA_DATA_CONFIGURATION = 0x02,
ACTIVE_POLLING_IR_CAMERA_DATA = 0x03, ACTIVE_POLLING_IR_CAMERA_DATA = 0x03,
SUBCMD_REPLY = 0x21,
MCU_UPDATE_STATE = 0x23, MCU_UPDATE_STATE = 0x23,
STANDARD_FULL_60HZ = 0x30, STANDARD_FULL_60HZ = 0x30,
NFC_IR_MODE_60HZ = 0x31, NFC_IR_MODE_60HZ = 0x31,
SIMPLE_HID_MODE = 0x3F, SIMPLE_HID_MODE = 0x3F,
INPUT_USB_RESPONSE = 0x81,
}; };
enum class GyroSensitivity : u8 { enum class GyroSensitivity : u8 {
@ -359,10 +364,16 @@ enum class IrRegistersAddress : u16 {
DenoiseColor = 0x6901, DenoiseColor = 0x6901,
}; };
enum class ExternalDeviceId : u16 {
RingController = 0x2000,
Starlink = 0x2800,
};
enum class DriverResult { enum class DriverResult {
Success, Success,
WrongReply, WrongReply,
Timeout, Timeout,
InvalidParameters,
UnsupportedControllerType, UnsupportedControllerType,
HandleInUse, HandleInUse,
ErrorReadingData, ErrorReadingData,
@ -485,7 +496,7 @@ static_assert(sizeof(MCUConfig) == 0x26, "MCUConfig is an invalid size");
#pragma pack(push, 1) #pragma pack(push, 1)
struct InputReportPassive { struct InputReportPassive {
InputReport report_mode; ReportMode report_mode;
u16 button_input; u16 button_input;
u8 stick_state; u8 stick_state;
std::array<u8, 10> unknown_data; std::array<u8, 10> unknown_data;
@ -493,7 +504,7 @@ struct InputReportPassive {
static_assert(sizeof(InputReportPassive) == 0xE, "InputReportPassive is an invalid size"); static_assert(sizeof(InputReportPassive) == 0xE, "InputReportPassive is an invalid size");
struct InputReportActive { struct InputReportActive {
InputReport report_mode; ReportMode report_mode;
u8 packet_id; u8 packet_id;
Battery battery_status; Battery battery_status;
std::array<u8, 3> button_input; std::array<u8, 3> button_input;
@ -507,7 +518,7 @@ struct InputReportActive {
static_assert(sizeof(InputReportActive) == 0x29, "InputReportActive is an invalid size"); static_assert(sizeof(InputReportActive) == 0x29, "InputReportActive is an invalid size");
struct InputReportNfcIr { struct InputReportNfcIr {
InputReport report_mode; ReportMode report_mode;
u8 packet_id; u8 packet_id;
Battery battery_status; Battery battery_status;
std::array<u8, 3> button_input; std::array<u8, 3> button_input;
@ -605,9 +616,11 @@ static_assert(sizeof(FirmwareVersion) == 0x2, "FirmwareVersion is an invalid siz
struct DeviceInfo { struct DeviceInfo {
FirmwareVersion firmware; FirmwareVersion firmware;
std::array<u8, 2> unknown_1;
MacAddress mac_address; MacAddress mac_address;
std::array<u8, 2> unknown_2;
}; };
static_assert(sizeof(DeviceInfo) == 0x8, "DeviceInfo is an invalid size"); static_assert(sizeof(DeviceInfo) == 0xC, "DeviceInfo is an invalid size");
struct MotionStatus { struct MotionStatus {
bool is_enabled; bool is_enabled;
@ -623,6 +636,53 @@ struct RingStatus {
s16 min_value; s16 min_value;
}; };
struct VibrationPacket {
OutputReport output_report;
u8 packet_counter;
std::array<u8, 0x8> vibration_data;
};
static_assert(sizeof(VibrationPacket) == 0xA, "VibrationPacket is an invalid size");
struct SubCommandPacket {
OutputReport output_report;
u8 packet_counter;
INSERT_PADDING_BYTES(0x8); // This contains vibration data
SubCommand sub_command;
std::array<u8, 0x26> command_data;
};
static_assert(sizeof(SubCommandPacket) == 0x31, "SubCommandPacket is an invalid size");
#pragma pack(push, 1)
struct ReadSpiPacket {
SpiAddress spi_address;
INSERT_PADDING_BYTES(0x2);
u8 size;
};
static_assert(sizeof(ReadSpiPacket) == 0x5, "ReadSpiPacket is an invalid size");
struct SubCommandResponse {
InputReportPassive input_report;
SubCommand sub_command;
union {
std::array<u8, 0x30> command_data;
SpiAddress spi_address; // Reply from SPI_FLASH_READ subcommand
ExternalDeviceId external_device_id; // Reply from GET_EXTERNAL_DEVICE_INFO subcommand
DeviceInfo device_info; // Reply from REQ_DEV_INFO subcommand
};
u8 crc; // This is never used
};
static_assert(sizeof(SubCommandResponse) == 0x40, "SubCommandResponse is an invalid size");
#pragma pack(pop)
struct MCUCommandResponse {
InputReportNfcIr input_report;
INSERT_PADDING_BYTES(0x8);
MCUReport mcu_report;
std::array<u8, 0x13D> mcu_data;
u8 crc;
};
static_assert(sizeof(MCUCommandResponse) == 0x170, "MCUCommandResponse is an invalid size");
struct JoyconCallbacks { struct JoyconCallbacks {
std::function<void(Battery)> on_battery_data; std::function<void(Battery)> on_battery_data;
std::function<void(Color)> on_color_data; std::function<void(Color)> on_color_data;

View file

@ -110,7 +110,7 @@ bool NfcProtocol::HasAmiibo() {
DriverResult NfcProtocol::WaitUntilNfcIsReady() { DriverResult NfcProtocol::WaitUntilNfcIsReady() {
constexpr std::size_t timeout_limit = 10; constexpr std::size_t timeout_limit = 10;
std::vector<u8> output; MCUCommandResponse output{};
std::size_t tries = 0; std::size_t tries = 0;
do { do {
@ -122,8 +122,9 @@ DriverResult NfcProtocol::WaitUntilNfcIsReady() {
if (tries++ > timeout_limit) { if (tries++ > timeout_limit) {
return DriverResult::Timeout; return DriverResult::Timeout;
} }
} while (output[49] != 0x2a || (output[51] << 8) + output[50] != 0x0500 || output[55] != 0x31 || } while (output.mcu_report != MCUReport::NFCState ||
output[56] != 0x00); (output.mcu_data[1] << 8) + output.mcu_data[0] != 0x0500 ||
output.mcu_data[5] != 0x31 || output.mcu_data[6] != 0x00);
return DriverResult::Success; return DriverResult::Success;
} }
@ -131,7 +132,7 @@ DriverResult NfcProtocol::WaitUntilNfcIsReady() {
DriverResult NfcProtocol::StartPolling(TagFoundData& data) { DriverResult NfcProtocol::StartPolling(TagFoundData& data) {
LOG_DEBUG(Input, "Start Polling for tag"); LOG_DEBUG(Input, "Start Polling for tag");
constexpr std::size_t timeout_limit = 7; constexpr std::size_t timeout_limit = 7;
std::vector<u8> output; MCUCommandResponse output{};
std::size_t tries = 0; std::size_t tries = 0;
do { do {
@ -142,18 +143,20 @@ DriverResult NfcProtocol::StartPolling(TagFoundData& data) {
if (tries++ > timeout_limit) { if (tries++ > timeout_limit) {
return DriverResult::Timeout; return DriverResult::Timeout;
} }
} while (output[49] != 0x2a || (output[51] << 8) + output[50] != 0x0500 || output[56] != 0x09); } while (output.mcu_report != MCUReport::NFCState ||
(output.mcu_data[1] << 8) + output.mcu_data[0] != 0x0500 ||
output.mcu_data[6] != 0x09);
data.type = output[62]; data.type = output.mcu_data[12];
data.uuid.resize(output[64]); data.uuid.resize(output.mcu_data[14]);
memcpy(data.uuid.data(), output.data() + 65, data.uuid.size()); memcpy(data.uuid.data(), output.mcu_data.data() + 15, data.uuid.size());
return DriverResult::Success; return DriverResult::Success;
} }
DriverResult NfcProtocol::ReadTag(const TagFoundData& data) { DriverResult NfcProtocol::ReadTag(const TagFoundData& data) {
constexpr std::size_t timeout_limit = 10; constexpr std::size_t timeout_limit = 10;
std::vector<u8> output; MCUCommandResponse output{};
std::size_t tries = 0; std::size_t tries = 0;
std::string uuid_string; std::string uuid_string;
@ -168,23 +171,24 @@ DriverResult NfcProtocol::ReadTag(const TagFoundData& data) {
// Read Tag data // Read Tag data
while (true) { while (true) {
auto result = SendReadAmiiboRequest(output, ntag_pages); auto result = SendReadAmiiboRequest(output, ntag_pages);
const auto mcu_report = static_cast<MCUReport>(output[49]); const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]);
const auto nfc_status = static_cast<NFCStatus>(output[56]);
if (result != DriverResult::Success) { if (result != DriverResult::Success) {
return result; return result;
} }
if ((mcu_report == MCUReport::NFCReadData || mcu_report == MCUReport::NFCState) && if ((output.mcu_report == MCUReport::NFCReadData ||
output.mcu_report == MCUReport::NFCState) &&
nfc_status == NFCStatus::TagLost) { nfc_status == NFCStatus::TagLost) {
return DriverResult::ErrorReadingData; return DriverResult::ErrorReadingData;
} }
if (mcu_report == MCUReport::NFCReadData && output[51] == 0x07 && output[52] == 0x01) { if (output.mcu_report == MCUReport::NFCReadData && output.mcu_data[1] == 0x07 &&
output.mcu_data[2] == 0x01) {
if (data.type != 2) { if (data.type != 2) {
continue; continue;
} }
switch (output[74]) { switch (output.mcu_data[24]) {
case 0: case 0:
ntag_pages = NFCPages::Block135; ntag_pages = NFCPages::Block135;
break; break;
@ -200,14 +204,14 @@ DriverResult NfcProtocol::ReadTag(const TagFoundData& data) {
continue; continue;
} }
if (mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::LastPackage) { if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::LastPackage) {
// finished // finished
SendStopPollingRequest(output); SendStopPollingRequest(output);
return DriverResult::Success; return DriverResult::Success;
} }
// Ignore other state reports // Ignore other state reports
if (mcu_report == MCUReport::NFCState) { if (output.mcu_report == MCUReport::NFCState) {
continue; continue;
} }
@ -221,7 +225,7 @@ DriverResult NfcProtocol::ReadTag(const TagFoundData& data) {
DriverResult NfcProtocol::GetAmiiboData(std::vector<u8>& ntag_data) { DriverResult NfcProtocol::GetAmiiboData(std::vector<u8>& ntag_data) {
constexpr std::size_t timeout_limit = 10; constexpr std::size_t timeout_limit = 10;
std::vector<u8> output; MCUCommandResponse output{};
std::size_t tries = 0; std::size_t tries = 0;
NFCPages ntag_pages = NFCPages::Block135; NFCPages ntag_pages = NFCPages::Block135;
@ -229,36 +233,38 @@ DriverResult NfcProtocol::GetAmiiboData(std::vector<u8>& ntag_data) {
// Read Tag data // Read Tag data
while (true) { while (true) {
auto result = SendReadAmiiboRequest(output, ntag_pages); auto result = SendReadAmiiboRequest(output, ntag_pages);
const auto mcu_report = static_cast<MCUReport>(output[49]); const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]);
const auto nfc_status = static_cast<NFCStatus>(output[56]);
if (result != DriverResult::Success) { if (result != DriverResult::Success) {
return result; return result;
} }
if ((mcu_report == MCUReport::NFCReadData || mcu_report == MCUReport::NFCState) && if ((output.mcu_report == MCUReport::NFCReadData ||
output.mcu_report == MCUReport::NFCState) &&
nfc_status == NFCStatus::TagLost) { nfc_status == NFCStatus::TagLost) {
return DriverResult::ErrorReadingData; return DriverResult::ErrorReadingData;
} }
if (mcu_report == MCUReport::NFCReadData && output[51] == 0x07) { if (output.mcu_report == MCUReport::NFCReadData && output.mcu_data[1] == 0x07) {
std::size_t payload_size = (output[54] << 8 | output[55]) & 0x7FF; std::size_t payload_size = (output.mcu_data[4] << 8 | output.mcu_data[5]) & 0x7FF;
if (output[52] == 0x01) { if (output.mcu_data[2] == 0x01) {
memcpy(ntag_data.data() + ntag_buffer_pos, output.data() + 116, payload_size - 60); memcpy(ntag_data.data() + ntag_buffer_pos, output.mcu_data.data() + 66,
payload_size - 60);
ntag_buffer_pos += payload_size - 60; ntag_buffer_pos += payload_size - 60;
} else { } else {
memcpy(ntag_data.data() + ntag_buffer_pos, output.data() + 56, payload_size); memcpy(ntag_data.data() + ntag_buffer_pos, output.mcu_data.data() + 6,
payload_size);
} }
continue; continue;
} }
if (mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::LastPackage) { if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::LastPackage) {
LOG_INFO(Input, "Finished reading amiibo"); LOG_INFO(Input, "Finished reading amiibo");
return DriverResult::Success; return DriverResult::Success;
} }
// Ignore other state reports // Ignore other state reports
if (mcu_report == MCUReport::NFCState) { if (output.mcu_report == MCUReport::NFCState) {
continue; continue;
} }
@ -270,7 +276,7 @@ DriverResult NfcProtocol::GetAmiiboData(std::vector<u8>& ntag_data) {
return DriverResult::Success; return DriverResult::Success;
} }
DriverResult NfcProtocol::SendStartPollingRequest(std::vector<u8>& output) { DriverResult NfcProtocol::SendStartPollingRequest(MCUCommandResponse& output) {
NFCRequestState request{ NFCRequestState request{
.sub_command = MCUSubCommand::ReadDeviceMode, .sub_command = MCUSubCommand::ReadDeviceMode,
.command_argument = NFCReadCommand::StartPolling, .command_argument = NFCReadCommand::StartPolling,
@ -294,7 +300,7 @@ DriverResult NfcProtocol::SendStartPollingRequest(std::vector<u8>& output) {
return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output); return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output);
} }
DriverResult NfcProtocol::SendStopPollingRequest(std::vector<u8>& output) { DriverResult NfcProtocol::SendStopPollingRequest(MCUCommandResponse& output) {
NFCRequestState request{ NFCRequestState request{
.sub_command = MCUSubCommand::ReadDeviceMode, .sub_command = MCUSubCommand::ReadDeviceMode,
.command_argument = NFCReadCommand::StopPolling, .command_argument = NFCReadCommand::StopPolling,
@ -311,7 +317,7 @@ DriverResult NfcProtocol::SendStopPollingRequest(std::vector<u8>& output) {
return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output); return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output);
} }
DriverResult NfcProtocol::SendStartWaitingRecieveRequest(std::vector<u8>& output) { DriverResult NfcProtocol::SendStartWaitingRecieveRequest(MCUCommandResponse& output) {
NFCRequestState request{ NFCRequestState request{
.sub_command = MCUSubCommand::ReadDeviceMode, .sub_command = MCUSubCommand::ReadDeviceMode,
.command_argument = NFCReadCommand::StartWaitingRecieve, .command_argument = NFCReadCommand::StartWaitingRecieve,
@ -328,7 +334,7 @@ DriverResult NfcProtocol::SendStartWaitingRecieveRequest(std::vector<u8>& output
return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output); return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output);
} }
DriverResult NfcProtocol::SendReadAmiiboRequest(std::vector<u8>& output, NFCPages ntag_pages) { DriverResult NfcProtocol::SendReadAmiiboRequest(MCUCommandResponse& output, NFCPages ntag_pages) {
NFCRequestState request{ NFCRequestState request{
.sub_command = MCUSubCommand::ReadDeviceMode, .sub_command = MCUSubCommand::ReadDeviceMode,
.command_argument = NFCReadCommand::Ntag, .command_argument = NFCReadCommand::Ntag,

View file

@ -45,13 +45,13 @@ private:
DriverResult GetAmiiboData(std::vector<u8>& data); DriverResult GetAmiiboData(std::vector<u8>& data);
DriverResult SendStartPollingRequest(std::vector<u8>& output); DriverResult SendStartPollingRequest(MCUCommandResponse& output);
DriverResult SendStopPollingRequest(std::vector<u8>& output); DriverResult SendStopPollingRequest(MCUCommandResponse& output);
DriverResult SendStartWaitingRecieveRequest(std::vector<u8>& output); DriverResult SendStartWaitingRecieveRequest(MCUCommandResponse& output);
DriverResult SendReadAmiiboRequest(std::vector<u8>& output, NFCPages ntag_pages); DriverResult SendReadAmiiboRequest(MCUCommandResponse& output, NFCPages ntag_pages);
NFCReadBlockCommand GetReadBlockCommand(NFCPages pages) const; NFCReadBlockCommand GetReadBlockCommand(NFCPages pages) const;

View file

@ -31,9 +31,7 @@ void JoyconPoller::ReadActiveMode(std::span<u8> buffer, const MotionStatus& moti
case Joycon::ControllerType::Pro: case Joycon::ControllerType::Pro:
UpdateActiveProPadInput(data, motion_status); UpdateActiveProPadInput(data, motion_status);
break; break;
case Joycon::ControllerType::Grip: default:
case Joycon::ControllerType::Dual:
case Joycon::ControllerType::None:
break; break;
} }
@ -58,9 +56,7 @@ void JoyconPoller::ReadPassiveMode(std::span<u8> buffer) {
case Joycon::ControllerType::Pro: case Joycon::ControllerType::Pro:
UpdatePasiveProPadInput(data); UpdatePasiveProPadInput(data);
break; break;
case Joycon::ControllerType::Grip: default:
case Joycon::ControllerType::Dual:
case Joycon::ControllerType::None:
break; break;
} }
} }

View file

@ -70,14 +70,12 @@ DriverResult RingConProtocol::StartRingconPolling() {
DriverResult RingConProtocol::IsRingConnected(bool& is_connected) { DriverResult RingConProtocol::IsRingConnected(bool& is_connected) {
LOG_DEBUG(Input, "IsRingConnected"); LOG_DEBUG(Input, "IsRingConnected");
constexpr std::size_t max_tries = 28; constexpr std::size_t max_tries = 28;
constexpr u8 ring_controller_id = 0x20; SubCommandResponse output{};
std::vector<u8> output;
std::size_t tries = 0; std::size_t tries = 0;
is_connected = false; is_connected = false;
do { do {
std::array<u8, 1> empty_data{}; const auto result = SendSubCommand(SubCommand::GET_EXTERNAL_DEVICE_INFO, {}, output);
const auto result = SendSubCommand(SubCommand::UNKNOWN_RINGCON, empty_data, output);
if (result != DriverResult::Success) { if (result != DriverResult::Success) {
return result; return result;
@ -86,7 +84,7 @@ DriverResult RingConProtocol::IsRingConnected(bool& is_connected) {
if (tries++ >= max_tries) { if (tries++ >= max_tries) {
return DriverResult::NoDeviceDetected; return DriverResult::NoDeviceDetected;
} }
} while (output[16] != ring_controller_id); } while (output.external_device_id != ExternalDeviceId::RingController);
is_connected = true; is_connected = true;
return DriverResult::Success; return DriverResult::Success;
@ -100,14 +98,14 @@ DriverResult RingConProtocol::ConfigureRing() {
0x00, 0x00, 0x00, 0x0A, 0x64, 0x0B, 0xE6, 0xA9, 0x22, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x64, 0x0B, 0xE6, 0xA9, 0x22, 0x00, 0x00, 0x04, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0xA8, 0xE1, 0x34, 0x36}; 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0xA8, 0xE1, 0x34, 0x36};
const DriverResult result = SendSubCommand(SubCommand::UNKNOWN_RINGCON3, ring_config); const DriverResult result = SendSubCommand(SubCommand::SET_EXTERNAL_FORMAT_CONFIG, ring_config);
if (result != DriverResult::Success) { if (result != DriverResult::Success) {
return result; return result;
} }
static constexpr std::array<u8, 4> ringcon_data{0x04, 0x01, 0x01, 0x02}; static constexpr std::array<u8, 4> ringcon_data{0x04, 0x01, 0x01, 0x02};
return SendSubCommand(SubCommand::UNKNOWN_RINGCON2, ringcon_data); return SendSubCommand(SubCommand::ENABLE_EXTERNAL_POLLING, ringcon_data);
} }
bool RingConProtocol::IsEnabled() const { bool RingConProtocol::IsEnabled() const {

View file

@ -16,10 +16,10 @@ public:
class InputFromButton final : public Common::Input::InputDevice { class InputFromButton final : public Common::Input::InputDevice {
public: public:
explicit InputFromButton(PadIdentifier identifier_, int button_, bool toggle_, bool inverted_, explicit InputFromButton(PadIdentifier identifier_, int button_, bool turbo_, bool toggle_,
InputEngine* input_engine_) bool inverted_, InputEngine* input_engine_)
: identifier(identifier_), button(button_), toggle(toggle_), inverted(inverted_), : identifier(identifier_), button(button_), turbo(turbo_), toggle(toggle_),
input_engine(input_engine_) { inverted(inverted_), input_engine(input_engine_) {
UpdateCallback engine_callback{[this]() { OnChange(); }}; UpdateCallback engine_callback{[this]() { OnChange(); }};
const InputIdentifier input_identifier{ const InputIdentifier input_identifier{
.identifier = identifier, .identifier = identifier,
@ -40,6 +40,7 @@ public:
.value = input_engine->GetButton(identifier, button), .value = input_engine->GetButton(identifier, button),
.inverted = inverted, .inverted = inverted,
.toggle = toggle, .toggle = toggle,
.turbo = turbo,
}; };
} }
@ -68,6 +69,7 @@ public:
private: private:
const PadIdentifier identifier; const PadIdentifier identifier;
const int button; const int button;
const bool turbo;
const bool toggle; const bool toggle;
const bool inverted; const bool inverted;
int callback_key; int callback_key;
@ -77,10 +79,10 @@ private:
class InputFromHatButton final : public Common::Input::InputDevice { class InputFromHatButton final : public Common::Input::InputDevice {
public: public:
explicit InputFromHatButton(PadIdentifier identifier_, int button_, u8 direction_, bool toggle_, explicit InputFromHatButton(PadIdentifier identifier_, int button_, u8 direction_, bool turbo_,
bool inverted_, InputEngine* input_engine_) bool toggle_, bool inverted_, InputEngine* input_engine_)
: identifier(identifier_), button(button_), direction(direction_), toggle(toggle_), : identifier(identifier_), button(button_), direction(direction_), turbo(turbo_),
inverted(inverted_), input_engine(input_engine_) { toggle(toggle_), inverted(inverted_), input_engine(input_engine_) {
UpdateCallback engine_callback{[this]() { OnChange(); }}; UpdateCallback engine_callback{[this]() { OnChange(); }};
const InputIdentifier input_identifier{ const InputIdentifier input_identifier{
.identifier = identifier, .identifier = identifier,
@ -101,6 +103,7 @@ public:
.value = input_engine->GetHatButton(identifier, button, direction), .value = input_engine->GetHatButton(identifier, button, direction),
.inverted = inverted, .inverted = inverted,
.toggle = toggle, .toggle = toggle,
.turbo = turbo,
}; };
} }
@ -130,6 +133,7 @@ private:
const PadIdentifier identifier; const PadIdentifier identifier;
const int button; const int button;
const u8 direction; const u8 direction;
const bool turbo;
const bool toggle; const bool toggle;
const bool inverted; const bool inverted;
int callback_key; int callback_key;
@ -853,14 +857,15 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateButtonDevice(
const auto keyboard_key = params.Get("code", 0); const auto keyboard_key = params.Get("code", 0);
const auto toggle = params.Get("toggle", false) != 0; const auto toggle = params.Get("toggle", false) != 0;
const auto inverted = params.Get("inverted", false) != 0; const auto inverted = params.Get("inverted", false) != 0;
const auto turbo = params.Get("turbo", false) != 0;
input_engine->PreSetController(identifier); input_engine->PreSetController(identifier);
input_engine->PreSetButton(identifier, button_id); input_engine->PreSetButton(identifier, button_id);
input_engine->PreSetButton(identifier, keyboard_key); input_engine->PreSetButton(identifier, keyboard_key);
if (keyboard_key != 0) { if (keyboard_key != 0) {
return std::make_unique<InputFromButton>(identifier, keyboard_key, toggle, inverted, return std::make_unique<InputFromButton>(identifier, keyboard_key, turbo, toggle, inverted,
input_engine.get()); input_engine.get());
} }
return std::make_unique<InputFromButton>(identifier, button_id, toggle, inverted, return std::make_unique<InputFromButton>(identifier, button_id, turbo, toggle, inverted,
input_engine.get()); input_engine.get());
} }
@ -876,11 +881,12 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateHatButtonDevice(
const auto direction = input_engine->GetHatButtonId(params.Get("direction", "")); const auto direction = input_engine->GetHatButtonId(params.Get("direction", ""));
const auto toggle = params.Get("toggle", false) != 0; const auto toggle = params.Get("toggle", false) != 0;
const auto inverted = params.Get("inverted", false) != 0; const auto inverted = params.Get("inverted", false) != 0;
const auto turbo = params.Get("turbo", false) != 0;
input_engine->PreSetController(identifier); input_engine->PreSetController(identifier);
input_engine->PreSetHatButton(identifier, button_id); input_engine->PreSetHatButton(identifier, button_id);
return std::make_unique<InputFromHatButton>(identifier, button_id, direction, toggle, inverted, return std::make_unique<InputFromHatButton>(identifier, button_id, direction, turbo, toggle,
input_engine.get()); inverted, input_engine.get());
} }
std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateStickDevice( std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateStickDevice(

View file

@ -45,6 +45,8 @@ set(SHADER_FILES
smaa_neighborhood_blending.vert smaa_neighborhood_blending.vert
smaa_neighborhood_blending.frag smaa_neighborhood_blending.frag
vulkan_blit_depth_stencil.frag vulkan_blit_depth_stencil.frag
vulkan_color_clear.frag
vulkan_color_clear.vert
vulkan_fidelityfx_fsr_easu_fp16.comp vulkan_fidelityfx_fsr_easu_fp16.comp
vulkan_fidelityfx_fsr_easu_fp32.comp vulkan_fidelityfx_fsr_easu_fp32.comp
vulkan_fidelityfx_fsr_rcas_fp16.comp vulkan_fidelityfx_fsr_rcas_fp16.comp

View file

@ -12,6 +12,8 @@
#include "video_core/host_shaders/convert_s8d24_to_abgr8_frag_spv.h" #include "video_core/host_shaders/convert_s8d24_to_abgr8_frag_spv.h"
#include "video_core/host_shaders/full_screen_triangle_vert_spv.h" #include "video_core/host_shaders/full_screen_triangle_vert_spv.h"
#include "video_core/host_shaders/vulkan_blit_depth_stencil_frag_spv.h" #include "video_core/host_shaders/vulkan_blit_depth_stencil_frag_spv.h"
#include "video_core/host_shaders/vulkan_color_clear_frag_spv.h"
#include "video_core/host_shaders/vulkan_color_clear_vert_spv.h"
#include "video_core/renderer_vulkan/blit_image.h" #include "video_core/renderer_vulkan/blit_image.h"
#include "video_core/renderer_vulkan/maxwell_to_vk.h" #include "video_core/renderer_vulkan/maxwell_to_vk.h"
#include "video_core/renderer_vulkan/vk_scheduler.h" #include "video_core/renderer_vulkan/vk_scheduler.h"
@ -69,10 +71,11 @@ constexpr VkDescriptorSetLayoutCreateInfo TWO_TEXTURES_DESCRIPTOR_SET_LAYOUT_CRE
.bindingCount = static_cast<u32>(TWO_TEXTURES_DESCRIPTOR_SET_LAYOUT_BINDINGS.size()), .bindingCount = static_cast<u32>(TWO_TEXTURES_DESCRIPTOR_SET_LAYOUT_BINDINGS.size()),
.pBindings = TWO_TEXTURES_DESCRIPTOR_SET_LAYOUT_BINDINGS.data(), .pBindings = TWO_TEXTURES_DESCRIPTOR_SET_LAYOUT_BINDINGS.data(),
}; };
constexpr VkPushConstantRange PUSH_CONSTANT_RANGE{ template <VkShaderStageFlags stageFlags, size_t size>
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT, inline constexpr VkPushConstantRange PUSH_CONSTANT_RANGE{
.stageFlags = stageFlags,
.offset = 0, .offset = 0,
.size = sizeof(PushConstants), .size = static_cast<u32>(size),
}; };
constexpr VkPipelineVertexInputStateCreateInfo PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO{ constexpr VkPipelineVertexInputStateCreateInfo PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO{
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
@ -125,10 +128,8 @@ constexpr VkPipelineMultisampleStateCreateInfo PIPELINE_MULTISAMPLE_STATE_CREATE
.alphaToCoverageEnable = VK_FALSE, .alphaToCoverageEnable = VK_FALSE,
.alphaToOneEnable = VK_FALSE, .alphaToOneEnable = VK_FALSE,
}; };
constexpr std::array DYNAMIC_STATES{ constexpr std::array DYNAMIC_STATES{VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR,
VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_BLEND_CONSTANTS};
VK_DYNAMIC_STATE_SCISSOR,
};
constexpr VkPipelineDynamicStateCreateInfo PIPELINE_DYNAMIC_STATE_CREATE_INFO{ constexpr VkPipelineDynamicStateCreateInfo PIPELINE_DYNAMIC_STATE_CREATE_INFO{
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
@ -205,15 +206,15 @@ inline constexpr VkSamplerCreateInfo SAMPLER_CREATE_INFO{
}; };
constexpr VkPipelineLayoutCreateInfo PipelineLayoutCreateInfo( constexpr VkPipelineLayoutCreateInfo PipelineLayoutCreateInfo(
const VkDescriptorSetLayout* set_layout) { const VkDescriptorSetLayout* set_layout, vk::Span<VkPushConstantRange> push_constants) {
return VkPipelineLayoutCreateInfo{ return VkPipelineLayoutCreateInfo{
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
.flags = 0, .flags = 0,
.setLayoutCount = 1, .setLayoutCount = (set_layout != nullptr ? 1u : 0u),
.pSetLayouts = set_layout, .pSetLayouts = set_layout,
.pushConstantRangeCount = 1, .pushConstantRangeCount = push_constants.size(),
.pPushConstantRanges = &PUSH_CONSTANT_RANGE, .pPushConstantRanges = push_constants.data(),
}; };
} }
@ -302,8 +303,7 @@ void UpdateTwoTexturesDescriptorSet(const Device& device, VkDescriptorSet descri
device.GetLogical().UpdateDescriptorSets(write_descriptor_sets, nullptr); device.GetLogical().UpdateDescriptorSets(write_descriptor_sets, nullptr);
} }
void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, const Region2D& dst_region, void BindBlitState(vk::CommandBuffer cmdbuf, const Region2D& dst_region) {
const Region2D& src_region, const Extent3D& src_size = {1, 1, 1}) {
const VkOffset2D offset{ const VkOffset2D offset{
.x = std::min(dst_region.start.x, dst_region.end.x), .x = std::min(dst_region.start.x, dst_region.end.x),
.y = std::min(dst_region.start.y, dst_region.end.y), .y = std::min(dst_region.start.y, dst_region.end.y),
@ -325,6 +325,13 @@ void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, const Regi
.offset = offset, .offset = offset,
.extent = extent, .extent = extent,
}; };
cmdbuf.SetViewport(0, viewport);
cmdbuf.SetScissor(0, scissor);
}
void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, const Region2D& dst_region,
const Region2D& src_region, const Extent3D& src_size = {1, 1, 1}) {
BindBlitState(cmdbuf, dst_region);
const float scale_x = static_cast<float>(src_region.end.x - src_region.start.x) / const float scale_x = static_cast<float>(src_region.end.x - src_region.start.x) /
static_cast<float>(src_size.width); static_cast<float>(src_size.width);
const float scale_y = static_cast<float>(src_region.end.y - src_region.start.y) / const float scale_y = static_cast<float>(src_region.end.y - src_region.start.y) /
@ -335,8 +342,6 @@ void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, const Regi
static_cast<float>(src_region.start.y) / static_cast<float>(src_region.start.y) /
static_cast<float>(src_size.height)}, static_cast<float>(src_size.height)},
}; };
cmdbuf.SetViewport(0, viewport);
cmdbuf.SetScissor(0, scissor);
cmdbuf.PushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT, push_constants); cmdbuf.PushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT, push_constants);
} }
@ -408,13 +413,20 @@ BlitImageHelper::BlitImageHelper(const Device& device_, Scheduler& scheduler_,
descriptor_pool.Allocator(*one_texture_set_layout, TEXTURE_DESCRIPTOR_BANK_INFO<1>)}, descriptor_pool.Allocator(*one_texture_set_layout, TEXTURE_DESCRIPTOR_BANK_INFO<1>)},
two_textures_descriptor_allocator{ two_textures_descriptor_allocator{
descriptor_pool.Allocator(*two_textures_set_layout, TEXTURE_DESCRIPTOR_BANK_INFO<2>)}, descriptor_pool.Allocator(*two_textures_set_layout, TEXTURE_DESCRIPTOR_BANK_INFO<2>)},
one_texture_pipeline_layout(device.GetLogical().CreatePipelineLayout( one_texture_pipeline_layout(device.GetLogical().CreatePipelineLayout(PipelineLayoutCreateInfo(
PipelineLayoutCreateInfo(one_texture_set_layout.address()))), one_texture_set_layout.address(),
two_textures_pipeline_layout(device.GetLogical().CreatePipelineLayout( PUSH_CONSTANT_RANGE<VK_SHADER_STAGE_VERTEX_BIT, sizeof(PushConstants)>))),
PipelineLayoutCreateInfo(two_textures_set_layout.address()))), two_textures_pipeline_layout(
device.GetLogical().CreatePipelineLayout(PipelineLayoutCreateInfo(
two_textures_set_layout.address(),
PUSH_CONSTANT_RANGE<VK_SHADER_STAGE_VERTEX_BIT, sizeof(PushConstants)>))),
clear_color_pipeline_layout(device.GetLogical().CreatePipelineLayout(PipelineLayoutCreateInfo(
nullptr, PUSH_CONSTANT_RANGE<VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(float) * 4>))),
full_screen_vert(BuildShader(device, FULL_SCREEN_TRIANGLE_VERT_SPV)), full_screen_vert(BuildShader(device, FULL_SCREEN_TRIANGLE_VERT_SPV)),
blit_color_to_color_frag(BuildShader(device, BLIT_COLOR_FLOAT_FRAG_SPV)), blit_color_to_color_frag(BuildShader(device, BLIT_COLOR_FLOAT_FRAG_SPV)),
blit_depth_stencil_frag(BuildShader(device, VULKAN_BLIT_DEPTH_STENCIL_FRAG_SPV)), blit_depth_stencil_frag(BuildShader(device, VULKAN_BLIT_DEPTH_STENCIL_FRAG_SPV)),
clear_color_vert(BuildShader(device, VULKAN_COLOR_CLEAR_VERT_SPV)),
clear_color_frag(BuildShader(device, VULKAN_COLOR_CLEAR_FRAG_SPV)),
convert_depth_to_float_frag(BuildShader(device, CONVERT_DEPTH_TO_FLOAT_FRAG_SPV)), convert_depth_to_float_frag(BuildShader(device, CONVERT_DEPTH_TO_FLOAT_FRAG_SPV)),
convert_float_to_depth_frag(BuildShader(device, CONVERT_FLOAT_TO_DEPTH_FRAG_SPV)), convert_float_to_depth_frag(BuildShader(device, CONVERT_FLOAT_TO_DEPTH_FRAG_SPV)),
convert_abgr8_to_d24s8_frag(BuildShader(device, CONVERT_ABGR8_TO_D24S8_FRAG_SPV)), convert_abgr8_to_d24s8_frag(BuildShader(device, CONVERT_ABGR8_TO_D24S8_FRAG_SPV)),
@ -553,6 +565,30 @@ void BlitImageHelper::ConvertS8D24ToABGR8(const Framebuffer* dst_framebuffer,
ConvertDepthStencil(*convert_s8d24_to_abgr8_pipeline, dst_framebuffer, src_image_view); ConvertDepthStencil(*convert_s8d24_to_abgr8_pipeline, dst_framebuffer, src_image_view);
} }
void BlitImageHelper::ClearColor(const Framebuffer* dst_framebuffer, u8 color_mask,
const std::array<f32, 4>& clear_color,
const Region2D& dst_region) {
const BlitImagePipelineKey key{
.renderpass = dst_framebuffer->RenderPass(),
.operation = Tegra::Engines::Fermi2D::Operation::BlendPremult,
};
const VkPipeline pipeline = FindOrEmplaceClearColorPipeline(key);
const VkPipelineLayout layout = *clear_color_pipeline_layout;
scheduler.RequestRenderpass(dst_framebuffer);
scheduler.Record(
[pipeline, layout, color_mask, clear_color, dst_region](vk::CommandBuffer cmdbuf) {
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
const std::array blend_color = {
(color_mask & 0x1) ? 1.0f : 0.0f, (color_mask & 0x2) ? 1.0f : 0.0f,
(color_mask & 0x4) ? 1.0f : 0.0f, (color_mask & 0x8) ? 1.0f : 0.0f};
cmdbuf.SetBlendConstants(blend_color.data());
BindBlitState(cmdbuf, dst_region);
cmdbuf.PushConstants(layout, VK_SHADER_STAGE_FRAGMENT_BIT, clear_color);
cmdbuf.Draw(3, 1, 0, 0);
});
scheduler.InvalidateState();
}
void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
const ImageView& src_image_view) { const ImageView& src_image_view) {
const VkPipelineLayout layout = *one_texture_pipeline_layout; const VkPipelineLayout layout = *one_texture_pipeline_layout;
@ -728,6 +764,58 @@ VkPipeline BlitImageHelper::FindOrEmplaceDepthStencilPipeline(const BlitImagePip
return *blit_depth_stencil_pipelines.back(); return *blit_depth_stencil_pipelines.back();
} }
VkPipeline BlitImageHelper::FindOrEmplaceClearColorPipeline(const BlitImagePipelineKey& key) {
const auto it = std::ranges::find(clear_color_keys, key);
if (it != clear_color_keys.end()) {
return *clear_color_pipelines[std::distance(clear_color_keys.begin(), it)];
}
clear_color_keys.push_back(key);
const std::array stages = MakeStages(*clear_color_vert, *clear_color_frag);
const VkPipelineColorBlendAttachmentState color_blend_attachment_state{
.blendEnable = VK_TRUE,
.srcColorBlendFactor = VK_BLEND_FACTOR_CONSTANT_COLOR,
.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR,
.colorBlendOp = VK_BLEND_OP_ADD,
.srcAlphaBlendFactor = VK_BLEND_FACTOR_CONSTANT_ALPHA,
.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA,
.alphaBlendOp = VK_BLEND_OP_ADD,
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
};
const VkPipelineColorBlendStateCreateInfo color_blend_state_generic_create_info{
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.logicOpEnable = VK_FALSE,
.logicOp = VK_LOGIC_OP_CLEAR,
.attachmentCount = 1,
.pAttachments = &color_blend_attachment_state,
.blendConstants = {0.0f, 0.0f, 0.0f, 0.0f},
};
clear_color_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.stageCount = static_cast<u32>(stages.size()),
.pStages = stages.data(),
.pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
.pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
.pTessellationState = nullptr,
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
.pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
.pDepthStencilState = &PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
.pColorBlendState = &color_blend_state_generic_create_info,
.pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO,
.layout = *clear_color_pipeline_layout,
.renderPass = key.renderpass,
.subpass = 0,
.basePipelineHandle = VK_NULL_HANDLE,
.basePipelineIndex = 0,
}));
return *clear_color_pipelines.back();
}
void BlitImageHelper::ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass, void BlitImageHelper::ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass,
bool is_target_depth) { bool is_target_depth) {
if (pipeline) { if (pipeline) {

View file

@ -61,6 +61,9 @@ public:
void ConvertS8D24ToABGR8(const Framebuffer* dst_framebuffer, ImageView& src_image_view); void ConvertS8D24ToABGR8(const Framebuffer* dst_framebuffer, ImageView& src_image_view);
void ClearColor(const Framebuffer* dst_framebuffer, u8 color_mask,
const std::array<f32, 4>& clear_color, const Region2D& dst_region);
private: private:
void Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, void Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
const ImageView& src_image_view); const ImageView& src_image_view);
@ -72,6 +75,8 @@ private:
[[nodiscard]] VkPipeline FindOrEmplaceDepthStencilPipeline(const BlitImagePipelineKey& key); [[nodiscard]] VkPipeline FindOrEmplaceDepthStencilPipeline(const BlitImagePipelineKey& key);
[[nodiscard]] VkPipeline FindOrEmplaceClearColorPipeline(const BlitImagePipelineKey& key);
void ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass, bool is_target_depth); void ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass, bool is_target_depth);
void ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass); void ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass);
@ -97,9 +102,12 @@ private:
DescriptorAllocator two_textures_descriptor_allocator; DescriptorAllocator two_textures_descriptor_allocator;
vk::PipelineLayout one_texture_pipeline_layout; vk::PipelineLayout one_texture_pipeline_layout;
vk::PipelineLayout two_textures_pipeline_layout; vk::PipelineLayout two_textures_pipeline_layout;
vk::PipelineLayout clear_color_pipeline_layout;
vk::ShaderModule full_screen_vert; vk::ShaderModule full_screen_vert;
vk::ShaderModule blit_color_to_color_frag; vk::ShaderModule blit_color_to_color_frag;
vk::ShaderModule blit_depth_stencil_frag; vk::ShaderModule blit_depth_stencil_frag;
vk::ShaderModule clear_color_vert;
vk::ShaderModule clear_color_frag;
vk::ShaderModule convert_depth_to_float_frag; vk::ShaderModule convert_depth_to_float_frag;
vk::ShaderModule convert_float_to_depth_frag; vk::ShaderModule convert_float_to_depth_frag;
vk::ShaderModule convert_abgr8_to_d24s8_frag; vk::ShaderModule convert_abgr8_to_d24s8_frag;
@ -112,6 +120,8 @@ private:
std::vector<vk::Pipeline> blit_color_pipelines; std::vector<vk::Pipeline> blit_color_pipelines;
std::vector<BlitImagePipelineKey> blit_depth_stencil_keys; std::vector<BlitImagePipelineKey> blit_depth_stencil_keys;
std::vector<vk::Pipeline> blit_depth_stencil_pipelines; std::vector<vk::Pipeline> blit_depth_stencil_pipelines;
std::vector<BlitImagePipelineKey> clear_color_keys;
std::vector<vk::Pipeline> clear_color_pipelines;
vk::Pipeline convert_d32_to_r32_pipeline; vk::Pipeline convert_d32_to_r32_pipeline;
vk::Pipeline convert_r32_to_d32_pipeline; vk::Pipeline convert_r32_to_d32_pipeline;
vk::Pipeline convert_d16_to_r16_pipeline; vk::Pipeline convert_d16_to_r16_pipeline;

View file

@ -394,7 +394,15 @@ void RasterizerVulkan::Clear(u32 layer_count) {
cmdbuf.ClearAttachments(attachment, clear_rect); cmdbuf.ClearAttachments(attachment, clear_rect);
}); });
} else { } else {
UNIMPLEMENTED_MSG("Unimplemented Clear only the specified channel"); u8 color_mask = static_cast<u8>(regs.clear_surface.R | regs.clear_surface.G << 1 |
regs.clear_surface.B << 2 | regs.clear_surface.A << 3);
Region2D dst_region = {
Offset2D{.x = clear_rect.rect.offset.x, .y = clear_rect.rect.offset.y},
Offset2D{.x = clear_rect.rect.offset.x +
static_cast<s32>(clear_rect.rect.extent.width),
.y = clear_rect.rect.offset.y +
static_cast<s32>(clear_rect.rect.extent.height)}};
blit_image.ClearColor(framebuffer, color_mask, regs.clear_color, dst_region);
} }
} }

View file

@ -575,7 +575,7 @@ void QtSoftwareKeyboardDialog::MoveAndResizeWindow(QPoint pos, QSize size) {
QDialog::resize(size); QDialog::resize(size);
// High DPI // High DPI
const float dpi_scale = qApp->screenAt(pos)->logicalDotsPerInch() / 96.0f; const float dpi_scale = screen()->logicalDotsPerInch() / 96.0f;
RescaleKeyboardElements(size.width(), size.height(), dpi_scale); RescaleKeyboardElements(size.width(), size.height(), dpi_scale);
} }

View file

@ -182,12 +182,13 @@ QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) {
const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : ""); const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : "");
const QString inverted = QString::fromStdString(param.Get("inverted", false) ? "!" : ""); const QString inverted = QString::fromStdString(param.Get("inverted", false) ? "!" : "");
const QString invert = QString::fromStdString(param.Get("invert", "+") == "-" ? "-" : ""); const QString invert = QString::fromStdString(param.Get("invert", "+") == "-" ? "-" : "");
const QString turbo = QString::fromStdString(param.Get("turbo", false) ? "$" : "");
const auto common_button_name = input_subsystem->GetButtonName(param); const auto common_button_name = input_subsystem->GetButtonName(param);
// Retrieve the names from Qt // Retrieve the names from Qt
if (param.Get("engine", "") == "keyboard") { if (param.Get("engine", "") == "keyboard") {
const QString button_str = GetKeyName(param.Get("code", 0)); const QString button_str = GetKeyName(param.Get("code", 0));
return QObject::tr("%1%2%3").arg(toggle, inverted, button_str); return QObject::tr("%1%2%3%4").arg(turbo, toggle, inverted, button_str);
} }
if (common_button_name == Common::Input::ButtonNames::Invalid) { if (common_button_name == Common::Input::ButtonNames::Invalid) {
@ -201,7 +202,7 @@ QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) {
if (common_button_name == Common::Input::ButtonNames::Value) { if (common_button_name == Common::Input::ButtonNames::Value) {
if (param.Has("hat")) { if (param.Has("hat")) {
const QString hat = GetDirectionName(param.Get("direction", "")); const QString hat = GetDirectionName(param.Get("direction", ""));
return QObject::tr("%1%2Hat %3").arg(toggle, inverted, hat); return QObject::tr("%1%2%3Hat %4").arg(turbo, toggle, inverted, hat);
} }
if (param.Has("axis")) { if (param.Has("axis")) {
const QString axis = QString::fromStdString(param.Get("axis", "")); const QString axis = QString::fromStdString(param.Get("axis", ""));
@ -219,13 +220,13 @@ QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) {
} }
if (param.Has("button")) { if (param.Has("button")) {
const QString button = QString::fromStdString(param.Get("button", "")); const QString button = QString::fromStdString(param.Get("button", ""));
return QObject::tr("%1%2Button %3").arg(toggle, inverted, button); return QObject::tr("%1%2%3Button %4").arg(turbo, toggle, inverted, button);
} }
} }
QString button_name = GetButtonName(common_button_name); QString button_name = GetButtonName(common_button_name);
if (param.Has("hat")) { if (param.Has("hat")) {
return QObject::tr("%1%2Hat %3").arg(toggle, inverted, button_name); return QObject::tr("%1%2%3Hat %4").arg(turbo, toggle, inverted, button_name);
} }
if (param.Has("axis")) { if (param.Has("axis")) {
return QObject::tr("%1%2Axis %3").arg(toggle, inverted, button_name); return QObject::tr("%1%2Axis %3").arg(toggle, inverted, button_name);
@ -234,7 +235,7 @@ QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) {
return QObject::tr("%1%2Axis %3").arg(toggle, inverted, button_name); return QObject::tr("%1%2Axis %3").arg(toggle, inverted, button_name);
} }
if (param.Has("button")) { if (param.Has("button")) {
return QObject::tr("%1%2Button %3").arg(toggle, inverted, button_name); return QObject::tr("%1%2%3Button %4").arg(turbo, toggle, inverted, button_name);
} }
return QObject::tr("[unknown]"); return QObject::tr("[unknown]");
@ -395,6 +396,12 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
button_map[button_id]->setText(ButtonToText(param)); button_map[button_id]->setText(ButtonToText(param));
emulated_controller->SetButtonParam(button_id, param); emulated_controller->SetButtonParam(button_id, param);
}); });
context_menu.addAction(tr("Turbo button"), [&] {
const bool turbo_value = !param.Get("turbo", false);
param.Set("turbo", turbo_value);
button_map[button_id]->setText(ButtonToText(param));
emulated_controller->SetButtonParam(button_id, param);
});
} }
if (param.Has("axis")) { if (param.Has("axis")) {
context_menu.addAction(tr("Invert axis"), [&] { context_menu.addAction(tr("Invert axis"), [&] {

View file

@ -81,7 +81,6 @@ void PlayerControlPreview::UpdateColors() {
colors.outline = QColor(0, 0, 0); colors.outline = QColor(0, 0, 0);
colors.primary = QColor(225, 225, 225); colors.primary = QColor(225, 225, 225);
colors.button = QColor(109, 111, 114); colors.button = QColor(109, 111, 114);
colors.button2 = QColor(109, 111, 114);
colors.button2 = QColor(77, 80, 84); colors.button2 = QColor(77, 80, 84);
colors.slider_arrow = QColor(65, 68, 73); colors.slider_arrow = QColor(65, 68, 73);
colors.font2 = QColor(0, 0, 0); colors.font2 = QColor(0, 0, 0);
@ -100,6 +99,7 @@ void PlayerControlPreview::UpdateColors() {
colors.led_off = QColor(170, 238, 255); colors.led_off = QColor(170, 238, 255);
colors.indicator2 = QColor(59, 165, 93); colors.indicator2 = QColor(59, 165, 93);
colors.charging = QColor(250, 168, 26); colors.charging = QColor(250, 168, 26);
colors.button_turbo = QColor(217, 158, 4);
colors.left = colors.primary; colors.left = colors.primary;
colors.right = colors.primary; colors.right = colors.primary;
@ -2469,7 +2469,6 @@ void PlayerControlPreview::DrawJoystickDot(QPainter& p, const QPointF center,
void PlayerControlPreview::DrawRoundButton(QPainter& p, QPointF center, void PlayerControlPreview::DrawRoundButton(QPainter& p, QPointF center,
const Common::Input::ButtonStatus& pressed, float width, const Common::Input::ButtonStatus& pressed, float width,
float height, Direction direction, float radius) { float height, Direction direction, float radius) {
p.setBrush(button_color);
if (pressed.value) { if (pressed.value) {
switch (direction) { switch (direction) {
case Direction::Left: case Direction::Left:
@ -2487,16 +2486,16 @@ void PlayerControlPreview::DrawRoundButton(QPainter& p, QPointF center,
case Direction::None: case Direction::None:
break; break;
} }
p.setBrush(colors.highlight);
} }
QRectF rect = {center.x() - width, center.y() - height, width * 2.0f, height * 2.0f}; QRectF rect = {center.x() - width, center.y() - height, width * 2.0f, height * 2.0f};
p.setBrush(GetButtonColor(button_color, pressed.value, pressed.turbo));
p.drawRoundedRect(rect, radius, radius); p.drawRoundedRect(rect, radius, radius);
} }
void PlayerControlPreview::DrawMinusButton(QPainter& p, const QPointF center, void PlayerControlPreview::DrawMinusButton(QPainter& p, const QPointF center,
const Common::Input::ButtonStatus& pressed, const Common::Input::ButtonStatus& pressed,
int button_size) { int button_size) {
p.setPen(colors.outline); p.setPen(colors.outline);
p.setBrush(pressed.value ? colors.highlight : colors.button); p.setBrush(GetButtonColor(colors.button, pressed.value, pressed.turbo));
DrawRectangle(p, center, button_size, button_size / 3.0f); DrawRectangle(p, center, button_size, button_size / 3.0f);
} }
void PlayerControlPreview::DrawPlusButton(QPainter& p, const QPointF center, void PlayerControlPreview::DrawPlusButton(QPainter& p, const QPointF center,
@ -2504,7 +2503,7 @@ void PlayerControlPreview::DrawPlusButton(QPainter& p, const QPointF center,
int button_size) { int button_size) {
// Draw outer line // Draw outer line
p.setPen(colors.outline); p.setPen(colors.outline);
p.setBrush(pressed.value ? colors.highlight : colors.button); p.setBrush(GetButtonColor(colors.button, pressed.value, pressed.turbo));
DrawRectangle(p, center, button_size, button_size / 3.0f); DrawRectangle(p, center, button_size, button_size / 3.0f);
DrawRectangle(p, center, button_size / 3.0f, button_size); DrawRectangle(p, center, button_size / 3.0f, button_size);
@ -2526,7 +2525,7 @@ void PlayerControlPreview::DrawGCButtonX(QPainter& p, const QPointF center,
} }
p.setPen(colors.outline); p.setPen(colors.outline);
p.setBrush(pressed.value ? colors.highlight : colors.button); p.setBrush(GetButtonColor(colors.button, pressed.value, pressed.turbo));
DrawPolygon(p, button_x); DrawPolygon(p, button_x);
} }
@ -2539,7 +2538,7 @@ void PlayerControlPreview::DrawGCButtonY(QPainter& p, const QPointF center,
} }
p.setPen(colors.outline); p.setPen(colors.outline);
p.setBrush(pressed.value ? colors.highlight : colors.button); p.setBrush(GetButtonColor(colors.button, pressed.value, pressed.turbo));
DrawPolygon(p, button_x); DrawPolygon(p, button_x);
} }
@ -2553,17 +2552,15 @@ void PlayerControlPreview::DrawGCButtonZ(QPainter& p, const QPointF center,
} }
p.setPen(colors.outline); p.setPen(colors.outline);
p.setBrush(pressed.value ? colors.highlight : colors.button2); p.setBrush(GetButtonColor(colors.button2, pressed.value, pressed.turbo));
DrawPolygon(p, button_x); DrawPolygon(p, button_x);
} }
void PlayerControlPreview::DrawCircleButton(QPainter& p, const QPointF center, void PlayerControlPreview::DrawCircleButton(QPainter& p, const QPointF center,
const Common::Input::ButtonStatus& pressed, const Common::Input::ButtonStatus& pressed,
float button_size) { float button_size) {
p.setBrush(button_color);
if (pressed.value) { p.setBrush(GetButtonColor(button_color, pressed.value, pressed.turbo));
p.setBrush(colors.highlight);
}
p.drawEllipse(center, button_size, button_size); p.drawEllipse(center, button_size, button_size);
} }
@ -2620,7 +2617,7 @@ void PlayerControlPreview::DrawArrowButton(QPainter& p, const QPointF center,
// Draw arrow button // Draw arrow button
p.setPen(pressed.value ? colors.highlight : colors.button); p.setPen(pressed.value ? colors.highlight : colors.button);
p.setBrush(pressed.value ? colors.highlight : colors.button); p.setBrush(GetButtonColor(colors.button, pressed.value, pressed.turbo));
DrawPolygon(p, arrow_button); DrawPolygon(p, arrow_button);
switch (direction) { switch (direction) {
@ -2672,10 +2669,20 @@ void PlayerControlPreview::DrawTriggerButton(QPainter& p, const QPointF center,
// Draw arrow button // Draw arrow button
p.setPen(colors.outline); p.setPen(colors.outline);
p.setBrush(pressed.value ? colors.highlight : colors.button); p.setBrush(GetButtonColor(colors.button, pressed.value, pressed.turbo));
DrawPolygon(p, qtrigger_button); DrawPolygon(p, qtrigger_button);
} }
QColor PlayerControlPreview::GetButtonColor(QColor default_color, bool is_pressed, bool turbo) {
if (is_pressed && turbo) {
return colors.button_turbo;
}
if (is_pressed) {
return colors.highlight;
}
return default_color;
}
void PlayerControlPreview::DrawBattery(QPainter& p, QPointF center, void PlayerControlPreview::DrawBattery(QPainter& p, QPointF center,
Common::Input::BatteryLevel battery) { Common::Input::BatteryLevel battery) {
if (battery == Common::Input::BatteryLevel::None) { if (battery == Common::Input::BatteryLevel::None) {

View file

@ -81,6 +81,7 @@ private:
QColor right{}; QColor right{};
QColor button{}; QColor button{};
QColor button2{}; QColor button2{};
QColor button_turbo{};
QColor font{}; QColor font{};
QColor font2{}; QColor font2{};
QColor highlight{}; QColor highlight{};
@ -183,6 +184,7 @@ private:
const Common::Input::ButtonStatus& pressed, float size = 1.0f); const Common::Input::ButtonStatus& pressed, float size = 1.0f);
void DrawTriggerButton(QPainter& p, QPointF center, Direction direction, void DrawTriggerButton(QPainter& p, QPointF center, Direction direction,
const Common::Input::ButtonStatus& pressed); const Common::Input::ButtonStatus& pressed);
QColor GetButtonColor(QColor default_color, bool is_pressed, bool turbo);
// Draw battery functions // Draw battery functions
void DrawBattery(QPainter& p, QPointF center, Common::Input::BatteryLevel battery); void DrawBattery(QPainter& p, QPointF center, Common::Input::BatteryLevel battery);

View file

@ -38,7 +38,7 @@ void DiscordImpl::Update() {
system.GetAppLoader().ReadTitle(title); system.GetAppLoader().ReadTitle(title);
} }
DiscordRichPresence presence{}; DiscordRichPresence presence{};
presence.largeImageKey = "yuzu_logo"; presence.largeImageKey = "yuzu_logo_ea";
presence.largeImageText = "yuzu is an emulator for the Nintendo Switch"; presence.largeImageText = "yuzu is an emulator for the Nintendo Switch";
if (system.IsPoweredOn()) { if (system.IsPoweredOn()) {
presence.state = title.c_str(); presence.state = title.c_str();

View file

@ -680,8 +680,10 @@ void GMainWindow::SoftwareKeyboardShowNormal() {
const auto y = layout.screen.top; const auto y = layout.screen.top;
const auto w = layout.screen.GetWidth(); const auto w = layout.screen.GetWidth();
const auto h = layout.screen.GetHeight(); const auto h = layout.screen.GetHeight();
const auto scale_ratio = devicePixelRatioF();
software_keyboard->ShowNormalKeyboard(render_window->mapToGlobal(QPoint(x, y)), QSize(w, h)); software_keyboard->ShowNormalKeyboard(render_window->mapToGlobal(QPoint(x, y) / scale_ratio),
QSize(w, h) / scale_ratio);
} }
void GMainWindow::SoftwareKeyboardShowTextCheck( void GMainWindow::SoftwareKeyboardShowTextCheck(
@ -714,9 +716,11 @@ void GMainWindow::SoftwareKeyboardShowInline(
(1.0f - appear_parameters.key_top_scale_y)))); (1.0f - appear_parameters.key_top_scale_y))));
const auto w = static_cast<int>(layout.screen.GetWidth() * appear_parameters.key_top_scale_x); const auto w = static_cast<int>(layout.screen.GetWidth() * appear_parameters.key_top_scale_x);
const auto h = static_cast<int>(layout.screen.GetHeight() * appear_parameters.key_top_scale_y); const auto h = static_cast<int>(layout.screen.GetHeight() * appear_parameters.key_top_scale_y);
const auto scale_ratio = devicePixelRatioF();
software_keyboard->ShowInlineKeyboard(std::move(appear_parameters), software_keyboard->ShowInlineKeyboard(std::move(appear_parameters),
render_window->mapToGlobal(QPoint(x, y)), QSize(w, h)); render_window->mapToGlobal(QPoint(x, y) / scale_ratio),
QSize(w, h) / scale_ratio);
} }
void GMainWindow::SoftwareKeyboardHideInline() { void GMainWindow::SoftwareKeyboardHideInline() {
@ -796,10 +800,11 @@ void GMainWindow::WebBrowserOpenWebPage(const std::string& main_url,
} }
const auto& layout = render_window->GetFramebufferLayout(); const auto& layout = render_window->GetFramebufferLayout();
web_browser_view.resize(layout.screen.GetWidth(), layout.screen.GetHeight()); const auto scale_ratio = devicePixelRatioF();
web_browser_view.move(layout.screen.left, layout.screen.top + menuBar()->height()); web_browser_view.resize(layout.screen.GetWidth() / scale_ratio,
web_browser_view.setZoomFactor(static_cast<qreal>(layout.screen.GetWidth()) / layout.screen.GetHeight() / scale_ratio);
static_cast<qreal>(Layout::ScreenUndocked::Width)); web_browser_view.move(layout.screen.left / scale_ratio,
(layout.screen.top / scale_ratio) + menuBar()->height());
web_browser_view.setFocus(); web_browser_view.setFocus();
web_browser_view.show(); web_browser_view.show();
@ -4390,6 +4395,55 @@ void GMainWindow::changeEvent(QEvent* event) {
#undef main #undef main
#endif #endif
static void SetHighDPIAttributes() {
#ifdef _WIN32
// For Windows, we want to avoid scaling artifacts on fractional scaling ratios.
// This is done by setting the optimal scaling policy for the primary screen.
// Create a temporary QApplication.
int temp_argc = 0;
char** temp_argv = nullptr;
QApplication temp{temp_argc, temp_argv};
// Get the current screen geometry.
const QScreen* primary_screen = QGuiApplication::primaryScreen();
if (primary_screen == nullptr) {
return;
}
const QRect screen_rect = primary_screen->geometry();
const int real_width = screen_rect.width();
const int real_height = screen_rect.height();
const float real_ratio = primary_screen->logicalDotsPerInch() / 96.0f;
// Recommended minimum width and height for proper window fit.
// Any screen with a lower resolution than this will still have a scale of 1.
constexpr float minimum_width = 1350.0f;
constexpr float minimum_height = 900.0f;
const float width_ratio = std::max(1.0f, real_width / minimum_width);
const float height_ratio = std::max(1.0f, real_height / minimum_height);
// Get the lower of the 2 ratios and truncate, this is the maximum integer scale.
const float max_ratio = std::trunc(std::min(width_ratio, height_ratio));
if (max_ratio > real_ratio) {
QApplication::setHighDpiScaleFactorRoundingPolicy(
Qt::HighDpiScaleFactorRoundingPolicy::Round);
} else {
QApplication::setHighDpiScaleFactorRoundingPolicy(
Qt::HighDpiScaleFactorRoundingPolicy::Floor);
}
#else
// Other OSes should be better than Windows at fractional scaling.
QApplication::setHighDpiScaleFactorRoundingPolicy(
Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
#endif
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
}
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
std::unique_ptr<Config> config = std::make_unique<Config>(); std::unique_ptr<Config> config = std::make_unique<Config>();
bool has_broken_vulkan = false; bool has_broken_vulkan = false;
@ -4445,6 +4499,8 @@ int main(int argc, char* argv[]) {
} }
#endif #endif
SetHighDPIAttributes();
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
// Disables the "?" button on all dialogs. Disabled by default on Qt6. // Disables the "?" button on all dialogs. Disabled by default on Qt6.
QCoreApplication::setAttribute(Qt::AA_DisableWindowContextHelpButton); QCoreApplication::setAttribute(Qt::AA_DisableWindowContextHelpButton);
@ -4452,6 +4508,7 @@ int main(int argc, char* argv[]) {
// Enables the core to make the qt created contexts current on std::threads // Enables the core to make the qt created contexts current on std::threads
QCoreApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity); QCoreApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity);
QApplication app(argc, argv); QApplication app(argc, argv);
#ifdef _WIN32 #ifdef _WIN32

View file

@ -163,7 +163,7 @@ void OverlayDialog::MoveAndResizeWindow() {
const auto height = static_cast<float>(parentWidget()->height()); const auto height = static_cast<float>(parentWidget()->height());
// High DPI // High DPI
const float dpi_scale = parentWidget()->windowHandle()->screen()->logicalDotsPerInch() / 96.0f; const float dpi_scale = screen()->logicalDotsPerInch() / 96.0f;
const auto title_text_font_size = BASE_TITLE_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale; const auto title_text_font_size = BASE_TITLE_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale;
const auto body_text_font_size = const auto body_text_font_size =