early-access version 3347
parent
3457f75f51
commit
ebd748d55f
|
@ -1,7 +1,7 @@
|
||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 3345.
|
This is the source code for early-access 3347.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 25 KiB |
|
@ -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 |
|
@ -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{};
|
||||||
};
|
};
|
||||||
|
|
|
@ -41,17 +41,18 @@ bool StoppableTimedWait(std::stop_token token, const std::chrono::duration<Rep,
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <list>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
namespace polyfill {
|
namespace polyfill {
|
||||||
|
|
||||||
using stop_state_callbacks = list<function<void()>>;
|
using stop_state_callback = size_t;
|
||||||
|
|
||||||
class stop_state {
|
class stop_state {
|
||||||
public:
|
public:
|
||||||
|
@ -59,61 +60,69 @@ public:
|
||||||
~stop_state() = default;
|
~stop_state() = default;
|
||||||
|
|
||||||
bool request_stop() {
|
bool request_stop() {
|
||||||
stop_state_callbacks callbacks;
|
unique_lock lk{m_lock};
|
||||||
|
|
||||||
{
|
if (m_stop_requested) {
|
||||||
scoped_lock lk{m_lock};
|
// Already set, nothing to do.
|
||||||
|
return false;
|
||||||
if (m_stop_requested.load()) {
|
|
||||||
// Already set, nothing to do
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set as requested
|
|
||||||
m_stop_requested = true;
|
|
||||||
|
|
||||||
// Copy callback list
|
|
||||||
callbacks = m_callbacks;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto callback : callbacks) {
|
// Mark stop requested.
|
||||||
callback();
|
m_stop_requested = true;
|
||||||
|
|
||||||
|
while (!m_callbacks.empty()) {
|
||||||
|
// Get an iterator to the first element.
|
||||||
|
const auto it = m_callbacks.begin();
|
||||||
|
|
||||||
|
// Move the callback function out of the map.
|
||||||
|
function<void()> f;
|
||||||
|
swap(it->second, f);
|
||||||
|
|
||||||
|
// Erase the now-empty map element.
|
||||||
|
m_callbacks.erase(it);
|
||||||
|
|
||||||
|
// Run the callback.
|
||||||
|
if (f) {
|
||||||
|
f();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool stop_requested() const {
|
bool stop_requested() const {
|
||||||
return m_stop_requested.load();
|
unique_lock lk{m_lock};
|
||||||
|
return m_stop_requested;
|
||||||
}
|
}
|
||||||
|
|
||||||
stop_state_callbacks::const_iterator insert_callback(function<void()> f) {
|
stop_state_callback insert_callback(function<void()> f) {
|
||||||
stop_state_callbacks::const_iterator ret{};
|
unique_lock lk{m_lock};
|
||||||
bool should_run{};
|
|
||||||
|
|
||||||
{
|
if (m_stop_requested) {
|
||||||
scoped_lock lk{m_lock};
|
// Stop already requested. Don't insert anything,
|
||||||
should_run = m_stop_requested.load();
|
// just run the callback synchronously.
|
||||||
m_callbacks.push_front(f);
|
if (f) {
|
||||||
ret = m_callbacks.begin();
|
f();
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
if (should_run) {
|
|
||||||
f();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Insert the callback.
|
||||||
|
stop_state_callback ret = ++m_next_callback;
|
||||||
|
m_callbacks.emplace(ret, move(f));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove_callback(stop_state_callbacks::const_iterator it) {
|
void remove_callback(stop_state_callback cb) {
|
||||||
scoped_lock lk{m_lock};
|
unique_lock lk{m_lock};
|
||||||
m_callbacks.erase(it);
|
m_callbacks.erase(cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutex m_lock;
|
mutable recursive_mutex m_lock;
|
||||||
atomic<bool> m_stop_requested;
|
map<stop_state_callback, function<void()>> m_callbacks;
|
||||||
stop_state_callbacks m_callbacks;
|
stop_state_callback m_next_callback{0};
|
||||||
|
bool m_stop_requested{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace polyfill
|
} // namespace polyfill
|
||||||
|
@ -223,7 +232,7 @@ public:
|
||||||
}
|
}
|
||||||
~stop_callback() {
|
~stop_callback() {
|
||||||
if (m_stop_state && m_callback) {
|
if (m_stop_state && m_callback) {
|
||||||
m_stop_state->remove_callback(*m_callback);
|
m_stop_state->remove_callback(m_callback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,7 +243,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
shared_ptr<polyfill::stop_state> m_stop_state;
|
shared_ptr<polyfill::stop_state> m_stop_state;
|
||||||
optional<polyfill::stop_state_callbacks::const_iterator> m_callback;
|
polyfill::stop_state_callback m_callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Callback>
|
template <typename Callback>
|
||||||
|
|
|
@ -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'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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};
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -0,0 +1,358 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hardware_properties.h"
|
||||||
|
#include "core/hle/kernel/k_capabilities.h"
|
||||||
|
#include "core/hle/kernel/k_memory_layout.h"
|
||||||
|
#include "core/hle/kernel/k_page_table.h"
|
||||||
|
#include "core/hle/kernel/kernel.h"
|
||||||
|
#include "core/hle/kernel/svc_results.h"
|
||||||
|
#include "core/hle/kernel/svc_version.h"
|
||||||
|
|
||||||
|
namespace Kernel {
|
||||||
|
|
||||||
|
Result KCapabilities::InitializeForKIP(std::span<const u32> kern_caps, KPageTable* page_table) {
|
||||||
|
// We're initializing an initial process.
|
||||||
|
m_svc_access_flags.reset();
|
||||||
|
m_irq_access_flags.reset();
|
||||||
|
m_debug_capabilities = 0;
|
||||||
|
m_handle_table_size = 0;
|
||||||
|
m_intended_kernel_version = 0;
|
||||||
|
m_program_type = 0;
|
||||||
|
|
||||||
|
// Initial processes may run on all cores.
|
||||||
|
constexpr u64 VirtMask = Core::Hardware::VirtualCoreMask;
|
||||||
|
constexpr u64 PhysMask = Core::Hardware::ConvertVirtualCoreMaskToPhysical(VirtMask);
|
||||||
|
|
||||||
|
m_core_mask = VirtMask;
|
||||||
|
m_phys_core_mask = PhysMask;
|
||||||
|
|
||||||
|
// Initial processes may use any user priority they like.
|
||||||
|
m_priority_mask = ~0xFULL;
|
||||||
|
|
||||||
|
// Here, Nintendo sets the kernel version to the current kernel version.
|
||||||
|
// We will follow suit and set the version to the highest supported kernel version.
|
||||||
|
KernelVersion intended_kernel_version{};
|
||||||
|
intended_kernel_version.major_version.Assign(Svc::SupportedKernelMajorVersion);
|
||||||
|
intended_kernel_version.minor_version.Assign(Svc::SupportedKernelMinorVersion);
|
||||||
|
m_intended_kernel_version = intended_kernel_version.raw;
|
||||||
|
|
||||||
|
// Parse the capabilities array.
|
||||||
|
R_RETURN(this->SetCapabilities(kern_caps, page_table));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result KCapabilities::InitializeForUser(std::span<const u32> user_caps, KPageTable* page_table) {
|
||||||
|
// We're initializing a user process.
|
||||||
|
m_svc_access_flags.reset();
|
||||||
|
m_irq_access_flags.reset();
|
||||||
|
m_debug_capabilities = 0;
|
||||||
|
m_handle_table_size = 0;
|
||||||
|
m_intended_kernel_version = 0;
|
||||||
|
m_program_type = 0;
|
||||||
|
|
||||||
|
// User processes must specify what cores/priorities they can use.
|
||||||
|
m_core_mask = 0;
|
||||||
|
m_priority_mask = 0;
|
||||||
|
|
||||||
|
// Parse the user capabilities array.
|
||||||
|
R_RETURN(this->SetCapabilities(user_caps, page_table));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result KCapabilities::SetCorePriorityCapability(const u32 cap) {
|
||||||
|
// We can't set core/priority if we've already set them.
|
||||||
|
R_UNLESS(m_core_mask == 0, ResultInvalidArgument);
|
||||||
|
R_UNLESS(m_priority_mask == 0, ResultInvalidArgument);
|
||||||
|
|
||||||
|
// Validate the core/priority.
|
||||||
|
CorePriority pack{cap};
|
||||||
|
const u32 min_core = pack.minimum_core_id;
|
||||||
|
const u32 max_core = pack.maximum_core_id;
|
||||||
|
const u32 max_prio = pack.lowest_thread_priority;
|
||||||
|
const u32 min_prio = pack.highest_thread_priority;
|
||||||
|
|
||||||
|
R_UNLESS(min_core <= max_core, ResultInvalidCombination);
|
||||||
|
R_UNLESS(min_prio <= max_prio, ResultInvalidCombination);
|
||||||
|
R_UNLESS(max_core < Core::Hardware::NumVirtualCores, ResultInvalidCoreId);
|
||||||
|
|
||||||
|
ASSERT(max_prio < Common::BitSize<u64>());
|
||||||
|
|
||||||
|
// Set core mask.
|
||||||
|
for (auto core_id = min_core; core_id <= max_core; core_id++) {
|
||||||
|
m_core_mask |= (1ULL << core_id);
|
||||||
|
}
|
||||||
|
ASSERT((m_core_mask & Core::Hardware::VirtualCoreMask) == m_core_mask);
|
||||||
|
|
||||||
|
// Set physical core mask.
|
||||||
|
m_phys_core_mask = Core::Hardware::ConvertVirtualCoreMaskToPhysical(m_core_mask);
|
||||||
|
|
||||||
|
// Set priority mask.
|
||||||
|
for (auto prio = min_prio; prio <= max_prio; prio++) {
|
||||||
|
m_priority_mask |= (1ULL << prio);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We must have some core/priority we can use.
|
||||||
|
R_UNLESS(m_core_mask != 0, ResultInvalidArgument);
|
||||||
|
R_UNLESS(m_priority_mask != 0, ResultInvalidArgument);
|
||||||
|
|
||||||
|
// Processes must not have access to kernel thread priorities.
|
||||||
|
R_UNLESS((m_priority_mask & 0xF) == 0, ResultInvalidArgument);
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result KCapabilities::SetSyscallMaskCapability(const u32 cap, u32& set_svc) {
|
||||||
|
// Validate the index.
|
||||||
|
SyscallMask pack{cap};
|
||||||
|
const u32 mask = pack.mask;
|
||||||
|
const u32 index = pack.index;
|
||||||
|
|
||||||
|
const u32 index_flag = (1U << index);
|
||||||
|
R_UNLESS((set_svc & index_flag) == 0, ResultInvalidCombination);
|
||||||
|
set_svc |= index_flag;
|
||||||
|
|
||||||
|
// Set SVCs.
|
||||||
|
for (size_t i = 0; i < decltype(SyscallMask::mask)::bits; i++) {
|
||||||
|
const u32 svc_id = static_cast<u32>(decltype(SyscallMask::mask)::bits* index + i);
|
||||||
|
if (mask & (1U << i)) {
|
||||||
|
R_UNLESS(this->SetSvcAllowed(svc_id), ResultOutOfRange);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result KCapabilities::MapRange_(const u32 cap, const u32 size_cap, KPageTable* page_table) {
|
||||||
|
const auto range_pack = MapRange{cap};
|
||||||
|
const auto size_pack = MapRangeSize{size_cap};
|
||||||
|
|
||||||
|
// Get/validate address/size
|
||||||
|
const u64 phys_addr = range_pack.address.Value() * PageSize;
|
||||||
|
|
||||||
|
// Validate reserved bits are unused.
|
||||||
|
R_UNLESS(size_pack.reserved.Value() == 0, ResultOutOfRange);
|
||||||
|
|
||||||
|
const size_t num_pages = size_pack.pages;
|
||||||
|
const size_t size = num_pages * PageSize;
|
||||||
|
R_UNLESS(num_pages != 0, ResultInvalidSize);
|
||||||
|
R_UNLESS(phys_addr < phys_addr + size, ResultInvalidAddress);
|
||||||
|
R_UNLESS(((phys_addr + size - 1) & ~PhysicalMapAllowedMask) == 0, ResultInvalidAddress);
|
||||||
|
|
||||||
|
// Do the mapping.
|
||||||
|
[[maybe_unused]] const KMemoryPermission perm = range_pack.read_only.Value()
|
||||||
|
? KMemoryPermission::UserRead
|
||||||
|
: KMemoryPermission::UserReadWrite;
|
||||||
|
if (MapRangeSize{size_cap}.normal) {
|
||||||
|
// R_RETURN(page_table->MapStatic(phys_addr, size, perm));
|
||||||
|
} else {
|
||||||
|
// R_RETURN(page_table->MapIo(phys_addr, size, perm));
|
||||||
|
}
|
||||||
|
|
||||||
|
UNIMPLEMENTED();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result KCapabilities::MapIoPage_(const u32 cap, KPageTable* page_table) {
|
||||||
|
// Get/validate address/size
|
||||||
|
const u64 phys_addr = MapIoPage{cap}.address.Value() * PageSize;
|
||||||
|
const size_t num_pages = 1;
|
||||||
|
const size_t size = num_pages * PageSize;
|
||||||
|
R_UNLESS(num_pages != 0, ResultInvalidSize);
|
||||||
|
R_UNLESS(phys_addr < phys_addr + size, ResultInvalidAddress);
|
||||||
|
R_UNLESS(((phys_addr + size - 1) & ~PhysicalMapAllowedMask) == 0, ResultInvalidAddress);
|
||||||
|
|
||||||
|
// Do the mapping.
|
||||||
|
// R_RETURN(page_table->MapIo(phys_addr, size, KMemoryPermission_UserReadWrite));
|
||||||
|
|
||||||
|
UNIMPLEMENTED();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
Result KCapabilities::ProcessMapRegionCapability(const u32 cap, F f) {
|
||||||
|
// Define the allowed memory regions.
|
||||||
|
constexpr std::array<KMemoryRegionType, 4> MemoryRegions{
|
||||||
|
KMemoryRegionType_None,
|
||||||
|
KMemoryRegionType_KernelTraceBuffer,
|
||||||
|
KMemoryRegionType_OnMemoryBootImage,
|
||||||
|
KMemoryRegionType_DTB,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Extract regions/read only.
|
||||||
|
const MapRegion pack{cap};
|
||||||
|
const std::array<RegionType, 3> types{pack.region0, pack.region1, pack.region2};
|
||||||
|
const std::array<u32, 3> ro{pack.read_only0, pack.read_only1, pack.read_only2};
|
||||||
|
|
||||||
|
for (size_t i = 0; i < types.size(); i++) {
|
||||||
|
const auto type = types[i];
|
||||||
|
const auto perm = ro[i] ? KMemoryPermission::UserRead : KMemoryPermission::UserReadWrite;
|
||||||
|
switch (type) {
|
||||||
|
case RegionType::NoMapping:
|
||||||
|
break;
|
||||||
|
case RegionType::KernelTraceBuffer:
|
||||||
|
case RegionType::OnMemoryBootImage:
|
||||||
|
case RegionType::DTB:
|
||||||
|
R_TRY(f(MemoryRegions[static_cast<u32>(type)], perm));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
R_THROW(ResultNotFound);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result KCapabilities::MapRegion_(const u32 cap, KPageTable* page_table) {
|
||||||
|
// Map each region into the process's page table.
|
||||||
|
R_RETURN(ProcessMapRegionCapability(
|
||||||
|
cap, [](KMemoryRegionType region_type, KMemoryPermission perm) -> Result {
|
||||||
|
// R_RETURN(page_table->MapRegion(region_type, perm));
|
||||||
|
UNIMPLEMENTED();
|
||||||
|
R_SUCCEED();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result KCapabilities::CheckMapRegion(KernelCore& kernel, const u32 cap) {
|
||||||
|
// Check that each region has a physical backing store.
|
||||||
|
R_RETURN(ProcessMapRegionCapability(
|
||||||
|
cap, [&](KMemoryRegionType region_type, KMemoryPermission perm) -> Result {
|
||||||
|
R_UNLESS(kernel.MemoryLayout().GetPhysicalMemoryRegionTree().FindFirstDerived(
|
||||||
|
region_type) != nullptr,
|
||||||
|
ResultOutOfRange);
|
||||||
|
R_SUCCEED();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result KCapabilities::SetInterruptPairCapability(const u32 cap) {
|
||||||
|
// Extract interrupts.
|
||||||
|
const InterruptPair pack{cap};
|
||||||
|
const std::array<u32, 2> ids{pack.interrupt_id0, pack.interrupt_id1};
|
||||||
|
|
||||||
|
for (size_t i = 0; i < ids.size(); i++) {
|
||||||
|
if (ids[i] != PaddingInterruptId) {
|
||||||
|
UNIMPLEMENTED();
|
||||||
|
// R_UNLESS(Kernel::GetInterruptManager().IsInterruptDefined(ids[i]), ResultOutOfRange);
|
||||||
|
// R_UNLESS(this->SetInterruptPermitted(ids[i]), ResultOutOfRange);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result KCapabilities::SetProgramTypeCapability(const u32 cap) {
|
||||||
|
// Validate.
|
||||||
|
const ProgramType pack{cap};
|
||||||
|
R_UNLESS(pack.reserved == 0, ResultReservedUsed);
|
||||||
|
|
||||||
|
m_program_type = pack.type;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result KCapabilities::SetKernelVersionCapability(const u32 cap) {
|
||||||
|
// Ensure we haven't set our version before.
|
||||||
|
R_UNLESS(KernelVersion{m_intended_kernel_version}.major_version == 0, ResultInvalidArgument);
|
||||||
|
|
||||||
|
// Set, ensure that we set a valid version.
|
||||||
|
m_intended_kernel_version = cap;
|
||||||
|
R_UNLESS(KernelVersion{m_intended_kernel_version}.major_version != 0, ResultInvalidArgument);
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result KCapabilities::SetHandleTableCapability(const u32 cap) {
|
||||||
|
// Validate.
|
||||||
|
const HandleTable pack{cap};
|
||||||
|
R_UNLESS(pack.reserved == 0, ResultReservedUsed);
|
||||||
|
|
||||||
|
m_handle_table_size = pack.size;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result KCapabilities::SetDebugFlagsCapability(const u32 cap) {
|
||||||
|
// Validate.
|
||||||
|
const DebugFlags pack{cap};
|
||||||
|
R_UNLESS(pack.reserved == 0, ResultReservedUsed);
|
||||||
|
|
||||||
|
DebugFlags debug_capabilities{m_debug_capabilities};
|
||||||
|
debug_capabilities.allow_debug.Assign(pack.allow_debug);
|
||||||
|
debug_capabilities.force_debug.Assign(pack.force_debug);
|
||||||
|
m_debug_capabilities = debug_capabilities.raw;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result KCapabilities::SetCapability(const u32 cap, u32& set_flags, u32& set_svc,
|
||||||
|
KPageTable* page_table) {
|
||||||
|
// Validate this is a capability we can act on.
|
||||||
|
const auto type = GetCapabilityType(cap);
|
||||||
|
R_UNLESS(type != CapabilityType::Invalid, ResultInvalidArgument);
|
||||||
|
|
||||||
|
// If the type is padding, we have no work to do.
|
||||||
|
R_SUCCEED_IF(type == CapabilityType::Padding);
|
||||||
|
|
||||||
|
// Check that we haven't already processed this capability.
|
||||||
|
const auto flag = GetCapabilityFlag(type);
|
||||||
|
R_UNLESS(((set_flags & InitializeOnceFlags) & flag) == 0, ResultInvalidCombination);
|
||||||
|
set_flags |= flag;
|
||||||
|
|
||||||
|
// Process the capability.
|
||||||
|
switch (type) {
|
||||||
|
case CapabilityType::CorePriority:
|
||||||
|
R_RETURN(this->SetCorePriorityCapability(cap));
|
||||||
|
case CapabilityType::SyscallMask:
|
||||||
|
R_RETURN(this->SetSyscallMaskCapability(cap, set_svc));
|
||||||
|
case CapabilityType::MapIoPage:
|
||||||
|
R_RETURN(this->MapIoPage_(cap, page_table));
|
||||||
|
case CapabilityType::MapRegion:
|
||||||
|
R_RETURN(this->MapRegion_(cap, page_table));
|
||||||
|
case CapabilityType::InterruptPair:
|
||||||
|
R_RETURN(this->SetInterruptPairCapability(cap));
|
||||||
|
case CapabilityType::ProgramType:
|
||||||
|
R_RETURN(this->SetProgramTypeCapability(cap));
|
||||||
|
case CapabilityType::KernelVersion:
|
||||||
|
R_RETURN(this->SetKernelVersionCapability(cap));
|
||||||
|
case CapabilityType::HandleTable:
|
||||||
|
R_RETURN(this->SetHandleTableCapability(cap));
|
||||||
|
case CapabilityType::DebugFlags:
|
||||||
|
R_RETURN(this->SetDebugFlagsCapability(cap));
|
||||||
|
default:
|
||||||
|
R_THROW(ResultInvalidArgument);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result KCapabilities::SetCapabilities(std::span<const u32> caps, KPageTable* page_table) {
|
||||||
|
u32 set_flags = 0, set_svc = 0;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < caps.size(); i++) {
|
||||||
|
const u32 cap{caps[i]};
|
||||||
|
|
||||||
|
if (GetCapabilityType(cap) == CapabilityType::MapRange) {
|
||||||
|
// Check that the pair cap exists.
|
||||||
|
R_UNLESS((++i) < caps.size(), ResultInvalidCombination);
|
||||||
|
|
||||||
|
// Check the pair cap is a map range cap.
|
||||||
|
const u32 size_cap{caps[i]};
|
||||||
|
R_UNLESS(GetCapabilityType(size_cap) == CapabilityType::MapRange,
|
||||||
|
ResultInvalidCombination);
|
||||||
|
|
||||||
|
// Map the range.
|
||||||
|
R_TRY(this->MapRange_(cap, size_cap, page_table));
|
||||||
|
} else {
|
||||||
|
R_TRY(this->SetCapability(cap, set_flags, set_svc, page_table));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result KCapabilities::CheckCapabilities(KernelCore& kernel, std::span<const u32> caps) {
|
||||||
|
for (auto cap : caps) {
|
||||||
|
// Check the capability refers to a valid region.
|
||||||
|
if (GetCapabilityType(cap) == CapabilityType::MapRegion) {
|
||||||
|
R_TRY(CheckMapRegion(kernel, cap));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Kernel
|
|
@ -0,0 +1,295 @@
|
||||||
|
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <bitset>
|
||||||
|
#include <span>
|
||||||
|
|
||||||
|
#include "common/bit_field.h"
|
||||||
|
#include "common/common_types.h"
|
||||||
|
|
||||||
|
#include "core/hle/kernel/svc_types.h"
|
||||||
|
#include "core/hle/result.h"
|
||||||
|
|
||||||
|
namespace Kernel {
|
||||||
|
|
||||||
|
class KPageTable;
|
||||||
|
class KernelCore;
|
||||||
|
|
||||||
|
class KCapabilities {
|
||||||
|
public:
|
||||||
|
constexpr explicit KCapabilities() = default;
|
||||||
|
|
||||||
|
Result InitializeForKIP(std::span<const u32> kern_caps, KPageTable* page_table);
|
||||||
|
Result InitializeForUser(std::span<const u32> user_caps, KPageTable* page_table);
|
||||||
|
|
||||||
|
static Result CheckCapabilities(KernelCore& kernel, std::span<const u32> user_caps);
|
||||||
|
|
||||||
|
constexpr u64 GetCoreMask() const {
|
||||||
|
return m_core_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr u64 GetPhysicalCoreMask() const {
|
||||||
|
return m_phys_core_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr u64 GetPriorityMask() const {
|
||||||
|
return m_priority_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr s32 GetHandleTableSize() const {
|
||||||
|
return m_handle_table_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const Svc::SvcAccessFlagSet& GetSvcPermissions() const {
|
||||||
|
return m_svc_access_flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool IsPermittedSvc(u32 id) const {
|
||||||
|
return (id < m_svc_access_flags.size()) && m_svc_access_flags[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool IsPermittedInterrupt(u32 id) const {
|
||||||
|
return (id < m_irq_access_flags.size()) && m_irq_access_flags[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool IsPermittedDebug() const {
|
||||||
|
return DebugFlags{m_debug_capabilities}.allow_debug.Value() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool CanForceDebug() const {
|
||||||
|
return DebugFlags{m_debug_capabilities}.force_debug.Value() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr u32 GetIntendedKernelMajorVersion() const {
|
||||||
|
return KernelVersion{m_intended_kernel_version}.major_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr u32 GetIntendedKernelMinorVersion() const {
|
||||||
|
return KernelVersion{m_intended_kernel_version}.minor_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr size_t InterruptIdCount = 0x400;
|
||||||
|
using InterruptFlagSet = std::bitset<InterruptIdCount>;
|
||||||
|
|
||||||
|
enum class CapabilityType : u32 {
|
||||||
|
CorePriority = (1U << 3) - 1,
|
||||||
|
SyscallMask = (1U << 4) - 1,
|
||||||
|
MapRange = (1U << 6) - 1,
|
||||||
|
MapIoPage = (1U << 7) - 1,
|
||||||
|
MapRegion = (1U << 10) - 1,
|
||||||
|
InterruptPair = (1U << 11) - 1,
|
||||||
|
ProgramType = (1U << 13) - 1,
|
||||||
|
KernelVersion = (1U << 14) - 1,
|
||||||
|
HandleTable = (1U << 15) - 1,
|
||||||
|
DebugFlags = (1U << 16) - 1,
|
||||||
|
|
||||||
|
Invalid = 0U,
|
||||||
|
Padding = ~0U,
|
||||||
|
};
|
||||||
|
|
||||||
|
using RawCapabilityValue = u32;
|
||||||
|
|
||||||
|
static constexpr CapabilityType GetCapabilityType(const RawCapabilityValue value) {
|
||||||
|
return static_cast<CapabilityType>((~value & (value + 1)) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr u32 GetCapabilityFlag(CapabilityType type) {
|
||||||
|
return static_cast<u32>(type) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <CapabilityType Type>
|
||||||
|
static constexpr inline u32 CapabilityFlag = static_cast<u32>(Type) + 1;
|
||||||
|
|
||||||
|
template <CapabilityType Type>
|
||||||
|
static constexpr inline u32 CapabilityId = std::countr_zero(CapabilityFlag<Type>);
|
||||||
|
|
||||||
|
union CorePriority {
|
||||||
|
static_assert(CapabilityId<CapabilityType::CorePriority> + 1 == 4);
|
||||||
|
|
||||||
|
RawCapabilityValue raw;
|
||||||
|
BitField<0, 4, CapabilityType> id;
|
||||||
|
BitField<4, 6, u32> lowest_thread_priority;
|
||||||
|
BitField<10, 6, u32> highest_thread_priority;
|
||||||
|
BitField<16, 8, u32> minimum_core_id;
|
||||||
|
BitField<24, 8, u32> maximum_core_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
union SyscallMask {
|
||||||
|
static_assert(CapabilityId<CapabilityType::SyscallMask> + 1 == 5);
|
||||||
|
|
||||||
|
RawCapabilityValue raw;
|
||||||
|
BitField<0, 5, CapabilityType> id;
|
||||||
|
BitField<5, 24, u32> mask;
|
||||||
|
BitField<29, 3, u32> index;
|
||||||
|
};
|
||||||
|
|
||||||
|
// #undef MESOSPHERE_ENABLE_LARGE_PHYSICAL_ADDRESS_CAPABILITIES
|
||||||
|
static constexpr u64 PhysicalMapAllowedMask = (1ULL << 36) - 1;
|
||||||
|
|
||||||
|
union MapRange {
|
||||||
|
static_assert(CapabilityId<CapabilityType::MapRange> + 1 == 7);
|
||||||
|
|
||||||
|
RawCapabilityValue raw;
|
||||||
|
BitField<0, 7, CapabilityType> id;
|
||||||
|
BitField<7, 24, u32> address;
|
||||||
|
BitField<31, 1, u32> read_only;
|
||||||
|
};
|
||||||
|
|
||||||
|
union MapRangeSize {
|
||||||
|
static_assert(CapabilityId<CapabilityType::MapRange> + 1 == 7);
|
||||||
|
|
||||||
|
RawCapabilityValue raw;
|
||||||
|
BitField<0, 7, CapabilityType> id;
|
||||||
|
BitField<7, 20, u32> pages;
|
||||||
|
BitField<27, 4, u32> reserved;
|
||||||
|
BitField<31, 1, u32> normal;
|
||||||
|
};
|
||||||
|
|
||||||
|
union MapIoPage {
|
||||||
|
static_assert(CapabilityId<CapabilityType::MapIoPage> + 1 == 8);
|
||||||
|
|
||||||
|
RawCapabilityValue raw;
|
||||||
|
BitField<0, 8, CapabilityType> id;
|
||||||
|
BitField<8, 24, u32> address;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class RegionType : u32 {
|
||||||
|
NoMapping = 0,
|
||||||
|
KernelTraceBuffer = 1,
|
||||||
|
OnMemoryBootImage = 2,
|
||||||
|
DTB = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
union MapRegion {
|
||||||
|
static_assert(CapabilityId<CapabilityType::MapRegion> + 1 == 11);
|
||||||
|
|
||||||
|
RawCapabilityValue raw;
|
||||||
|
BitField<0, 11, CapabilityType> id;
|
||||||
|
BitField<11, 6, RegionType> region0;
|
||||||
|
BitField<17, 1, u32> read_only0;
|
||||||
|
BitField<18, 6, RegionType> region1;
|
||||||
|
BitField<24, 1, u32> read_only1;
|
||||||
|
BitField<25, 6, RegionType> region2;
|
||||||
|
BitField<31, 1, u32> read_only2;
|
||||||
|
};
|
||||||
|
|
||||||
|
union InterruptPair {
|
||||||
|
static_assert(CapabilityId<CapabilityType::InterruptPair> + 1 == 12);
|
||||||
|
|
||||||
|
RawCapabilityValue raw;
|
||||||
|
BitField<0, 12, CapabilityType> id;
|
||||||
|
BitField<12, 10, u32> interrupt_id0;
|
||||||
|
BitField<22, 10, u32> interrupt_id1;
|
||||||
|
};
|
||||||
|
|
||||||
|
union ProgramType {
|
||||||
|
static_assert(CapabilityId<CapabilityType::ProgramType> + 1 == 14);
|
||||||
|
|
||||||
|
RawCapabilityValue raw;
|
||||||
|
BitField<0, 14, CapabilityType> id;
|
||||||
|
BitField<14, 3, u32> type;
|
||||||
|
BitField<17, 15, u32> reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
union KernelVersion {
|
||||||
|
static_assert(CapabilityId<CapabilityType::KernelVersion> + 1 == 15);
|
||||||
|
|
||||||
|
RawCapabilityValue raw;
|
||||||
|
BitField<0, 15, CapabilityType> id;
|
||||||
|
BitField<15, 4, u32> major_version;
|
||||||
|
BitField<19, 13, u32> minor_version;
|
||||||
|
};
|
||||||
|
|
||||||
|
union HandleTable {
|
||||||
|
static_assert(CapabilityId<CapabilityType::HandleTable> + 1 == 16);
|
||||||
|
|
||||||
|
RawCapabilityValue raw;
|
||||||
|
BitField<0, 16, CapabilityType> id;
|
||||||
|
BitField<16, 10, u32> size;
|
||||||
|
BitField<26, 6, u32> reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
union DebugFlags {
|
||||||
|
static_assert(CapabilityId<CapabilityType::DebugFlags> + 1 == 17);
|
||||||
|
|
||||||
|
RawCapabilityValue raw;
|
||||||
|
BitField<0, 17, CapabilityType> id;
|
||||||
|
BitField<17, 1, u32> allow_debug;
|
||||||
|
BitField<18, 1, u32> force_debug;
|
||||||
|
BitField<19, 13, u32> reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(CorePriority) == 4);
|
||||||
|
static_assert(sizeof(SyscallMask) == 4);
|
||||||
|
static_assert(sizeof(MapRange) == 4);
|
||||||
|
static_assert(sizeof(MapRangeSize) == 4);
|
||||||
|
static_assert(sizeof(MapIoPage) == 4);
|
||||||
|
static_assert(sizeof(MapRegion) == 4);
|
||||||
|
static_assert(sizeof(InterruptPair) == 4);
|
||||||
|
static_assert(sizeof(ProgramType) == 4);
|
||||||
|
static_assert(sizeof(KernelVersion) == 4);
|
||||||
|
static_assert(sizeof(HandleTable) == 4);
|
||||||
|
static_assert(sizeof(DebugFlags) == 4);
|
||||||
|
|
||||||
|
static constexpr u32 InitializeOnceFlags =
|
||||||
|
CapabilityFlag<CapabilityType::CorePriority> | CapabilityFlag<CapabilityType::ProgramType> |
|
||||||
|
CapabilityFlag<CapabilityType::KernelVersion> |
|
||||||
|
CapabilityFlag<CapabilityType::HandleTable> | CapabilityFlag<CapabilityType::DebugFlags>;
|
||||||
|
|
||||||
|
static const u32 PaddingInterruptId = 0x3FF;
|
||||||
|
static_assert(PaddingInterruptId < InterruptIdCount);
|
||||||
|
|
||||||
|
private:
|
||||||
|
constexpr bool SetSvcAllowed(u32 id) {
|
||||||
|
if (id < m_svc_access_flags.size()) [[likely]] {
|
||||||
|
m_svc_access_flags[id] = true;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool SetInterruptPermitted(u32 id) {
|
||||||
|
if (id < m_irq_access_flags.size()) [[likely]] {
|
||||||
|
m_irq_access_flags[id] = true;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result SetCorePriorityCapability(const u32 cap);
|
||||||
|
Result SetSyscallMaskCapability(const u32 cap, u32& set_svc);
|
||||||
|
Result MapRange_(const u32 cap, const u32 size_cap, KPageTable* page_table);
|
||||||
|
Result MapIoPage_(const u32 cap, KPageTable* page_table);
|
||||||
|
Result MapRegion_(const u32 cap, KPageTable* page_table);
|
||||||
|
Result SetInterruptPairCapability(const u32 cap);
|
||||||
|
Result SetProgramTypeCapability(const u32 cap);
|
||||||
|
Result SetKernelVersionCapability(const u32 cap);
|
||||||
|
Result SetHandleTableCapability(const u32 cap);
|
||||||
|
Result SetDebugFlagsCapability(const u32 cap);
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
static Result ProcessMapRegionCapability(const u32 cap, F f);
|
||||||
|
static Result CheckMapRegion(KernelCore& kernel, const u32 cap);
|
||||||
|
|
||||||
|
Result SetCapability(const u32 cap, u32& set_flags, u32& set_svc, KPageTable* page_table);
|
||||||
|
Result SetCapabilities(std::span<const u32> caps, KPageTable* page_table);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Svc::SvcAccessFlagSet m_svc_access_flags{};
|
||||||
|
InterruptFlagSet m_irq_access_flags{};
|
||||||
|
u64 m_core_mask{};
|
||||||
|
u64 m_phys_core_mask{};
|
||||||
|
u64 m_priority_mask{};
|
||||||
|
u32 m_debug_capabilities{};
|
||||||
|
s32 m_handle_table_size{};
|
||||||
|
u32 m_intended_kernel_version{};
|
||||||
|
u32 m_program_type{};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Kernel
|
|
@ -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
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/bit_field.h"
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "common/literals.h"
|
||||||
|
|
||||||
|
namespace Kernel::Svc {
|
||||||
|
|
||||||
|
constexpr inline u32 ConvertToSvcMajorVersion(u32 sdk) {
|
||||||
|
return sdk + 4;
|
||||||
|
}
|
||||||
|
constexpr inline u32 ConvertToSdkMajorVersion(u32 svc) {
|
||||||
|
return svc - 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr inline u32 ConvertToSvcMinorVersion(u32 sdk) {
|
||||||
|
return sdk;
|
||||||
|
}
|
||||||
|
constexpr inline u32 ConvertToSdkMinorVersion(u32 svc) {
|
||||||
|
return svc;
|
||||||
|
}
|
||||||
|
|
||||||
|
union KernelVersion {
|
||||||
|
u32 value;
|
||||||
|
BitField<0, 4, u32> minor_version;
|
||||||
|
BitField<4, 13, u32> major_version;
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr inline u32 EncodeKernelVersion(u32 major, u32 minor) {
|
||||||
|
return decltype(KernelVersion::minor_version)::FormatValue(minor) |
|
||||||
|
decltype(KernelVersion::major_version)::FormatValue(major);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr inline u32 GetKernelMajorVersion(u32 encoded) {
|
||||||
|
return std::bit_cast<decltype(KernelVersion::major_version)>(encoded).Value();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr inline u32 GetKernelMinorVersion(u32 encoded) {
|
||||||
|
return std::bit_cast<decltype(KernelVersion::minor_version)>(encoded).Value();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nintendo doesn't support programs targeting SVC versions < 3.0.
|
||||||
|
constexpr inline u32 RequiredKernelMajorVersion = 3;
|
||||||
|
constexpr inline u32 RequiredKernelMinorVersion = 0;
|
||||||
|
constexpr inline u32 RequiredKernelVersion =
|
||||||
|
EncodeKernelVersion(RequiredKernelMajorVersion, RequiredKernelMinorVersion);
|
||||||
|
|
||||||
|
// This is the highest SVC version supported, to be updated on new kernel releases.
|
||||||
|
// NOTE: Official kernel versions have SVC major = SDK major + 4, SVC minor = SDK minor.
|
||||||
|
constexpr inline u32 SupportedKernelMajorVersion = ConvertToSvcMajorVersion(15);
|
||||||
|
constexpr inline u32 SupportedKernelMinorVersion = ConvertToSvcMinorVersion(3);
|
||||||
|
constexpr inline u32 SupportedKernelVersion =
|
||||||
|
EncodeKernelVersion(SupportedKernelMajorVersion, SupportedKernelMinorVersion);
|
||||||
|
|
||||||
|
} // namespace Kernel::Svc
|
|
@ -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);
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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!");
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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(¶ms, input.data(), input.size());
|
std::memcpy(¶ms, 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(¶ms, input.data(), input.size());
|
std::memcpy(¶ms, 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(¶ms, input.data(), input.size());
|
std::memcpy(¶ms, 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(¶ms, input.data(), input.size());
|
std::memcpy(¶ms, 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(¶ms, input.data(), input.size());
|
std::memcpy(¶ms, 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(¶ms, input.data(), input.size());
|
std::memcpy(¶ms, 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(¶ms, input.data(), input.size());
|
std::memcpy(¶ms, 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(¶ms, input.data(), input.size());
|
std::memcpy(¶ms, input.data(), input.size());
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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(¶ms, input.data(), sizeof(params));
|
std::memcpy(¶ms, 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(¶ms, input.data(), sizeof(params));
|
std::memcpy(¶ms, 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(¶ms, input.data(), sizeof(params));
|
std::memcpy(¶ms, 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(¶ms, input.data(), sizeof(params));
|
std::memcpy(¶ms, 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(¶ms, input.data(), sizeof(params));
|
std::memcpy(¶ms, 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(¶ms, input.data(), sizeof(params));
|
std::memcpy(¶ms, input.data(), sizeof(params));
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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(¶ms, input.data(), input.size());
|
std::memcpy(¶ms, 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(¶ms, input.data(), input.size());
|
std::memcpy(¶ms, 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(¶ms, input.data(), input.size());
|
std::memcpy(¶ms, 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{};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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(¶ms, input.data(), input.size());
|
std::memcpy(¶ms, 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(¶ms, input.data(), input.size());
|
std::memcpy(¶ms, 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(¶ms, input.data(), input.size());
|
std::memcpy(¶ms, 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(¶ms, input.data(), input.size());
|
std::memcpy(¶ms, 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(¶ms, input.data(), sizeof(IoctlGetWaitbase));
|
std::memcpy(¶ms, 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(¶ms, input.data(), sizeof(IoctlChannelSetTimeout));
|
std::memcpy(¶ms, 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(¶ms, input.data(), sizeof(IoctlSetTimeslice));
|
std::memcpy(¶ms, input.data(), sizeof(IoctlSetTimeslice));
|
||||||
LOG_INFO(Service_NVDRV, "called, timeslice=0x{:X}", params.timeslice);
|
LOG_INFO(Service_NVDRV, "called, timeslice=0x{:X}", params.timeslice);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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(¶ms, input.data(), sizeof(IoctlSetNvmapFD));
|
std::memcpy(¶ms, 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(¶ms, input.data(), sizeof(IoctlSubmit));
|
std::memcpy(¶ms, 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(¶ms, input.data(), sizeof(IoctlGetSyncpoint));
|
std::memcpy(¶ms, 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(¶ms, input.data(), sizeof(IoctlGetWaitbase));
|
std::memcpy(¶ms, 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(¶ms, input.data(), sizeof(IoctlMapBuffer));
|
std::memcpy(¶ms, 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(¶ms, input.data(), sizeof(IoctlMapBuffer));
|
std::memcpy(¶ms, 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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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(¶ms, input.data(), input.size());
|
std::memcpy(¶ms, input.data(), input.size());
|
||||||
LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
|
LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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(¶ms, input.data(), sizeof(params));
|
std::memcpy(¶ms, 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(¶ms, input.data(), sizeof(params));
|
std::memcpy(¶ms, 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(¶ms, input.data(), sizeof(params));
|
std::memcpy(¶ms, 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(¶ms, input.data(), sizeof(params));
|
std::memcpy(¶ms, 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(¶ms, input.data(), sizeof(params));
|
std::memcpy(¶ms, input.data(), sizeof(params));
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
namespace Service::android {
|
namespace Service::android {
|
||||||
|
|
||||||
QueueBufferInput::QueueBufferInput(Parcel& parcel) {
|
QueueBufferInput::QueueBufferInput(InputParcel& parcel) {
|
||||||
parcel.ReadFlattened(*this);
|
parcel.ReadFlattened(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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_,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -243,4 +243,4 @@ void SFDNSRES::GetAddrInfoRequestWithOptions(Kernel::HLERequestContext& ctx) {
|
||||||
rb.Push(0);
|
rb.Push(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::Sockets
|
} // namespace Service::Sockets
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -13,34 +13,34 @@ CalibrationProtocol::CalibrationProtocol(std::shared_ptr<JoyconHandle> handle)
|
||||||
|
|
||||||
DriverResult CalibrationProtocol::GetLeftJoyStickCalibration(JoyStickCalibration& calibration) {
|
DriverResult CalibrationProtocol::GetLeftJoyStickCalibration(JoyStickCalibration& calibration) {
|
||||||
ScopedSetBlocking sb(this);
|
ScopedSetBlocking sb(this);
|
||||||
std::vector<u8> buffer;
|
|
||||||
DriverResult result{DriverResult::Success};
|
DriverResult result{DriverResult::Success};
|
||||||
|
JoystickLeftSpiCalibration spi_calibration{};
|
||||||
|
bool has_user_calibration = false;
|
||||||
calibration = {};
|
calibration = {};
|
||||||
|
|
||||||
result = ReadSPI(CalAddr::USER_LEFT_MAGIC, sizeof(u16), buffer);
|
|
||||||
|
|
||||||
if (result == DriverResult::Success) {
|
if (result == DriverResult::Success) {
|
||||||
const bool has_user_calibration = buffer[0] == 0xB2 && buffer[1] == 0xA1;
|
result = HasUserCalibration(SpiAddress::USER_LEFT_MAGIC, has_user_calibration);
|
||||||
if (has_user_calibration) {
|
}
|
||||||
result = ReadSPI(CalAddr::USER_LEFT_DATA, 9, buffer);
|
|
||||||
} else {
|
// Read User defined calibration
|
||||||
result = ReadSPI(CalAddr::FACT_LEFT_DATA, 9, buffer);
|
if (result == DriverResult::Success && has_user_calibration) {
|
||||||
}
|
result = ReadSPI(SpiAddress::USER_LEFT_DATA, spi_calibration);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read Factory calibration
|
||||||
|
if (result == DriverResult::Success && !has_user_calibration) {
|
||||||
|
result = ReadSPI(SpiAddress::FACT_LEFT_DATA, spi_calibration);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == DriverResult::Success) {
|
if (result == DriverResult::Success) {
|
||||||
calibration.x.max = static_cast<u16>(((buffer[1] & 0x0F) << 8) | buffer[0]);
|
calibration.x.center = GetXAxisCalibrationValue(spi_calibration.center);
|
||||||
calibration.y.max = static_cast<u16>((buffer[2] << 4) | (buffer[1] >> 4));
|
calibration.y.center = GetYAxisCalibrationValue(spi_calibration.center);
|
||||||
calibration.x.center = static_cast<u16>(((buffer[4] & 0x0F) << 8) | buffer[3]);
|
calibration.x.min = GetXAxisCalibrationValue(spi_calibration.min);
|
||||||
calibration.y.center = static_cast<u16>((buffer[5] << 4) | (buffer[4] >> 4));
|
calibration.y.min = GetYAxisCalibrationValue(spi_calibration.min);
|
||||||
calibration.x.min = static_cast<u16>(((buffer[7] & 0x0F) << 8) | buffer[6]);
|
calibration.x.max = GetXAxisCalibrationValue(spi_calibration.max);
|
||||||
calibration.y.min = static_cast<u16>((buffer[8] << 4) | (buffer[7] >> 4));
|
calibration.y.max = GetYAxisCalibrationValue(spi_calibration.max);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nintendo fix for drifting stick
|
|
||||||
// result = ReadSPI(0x60, 0x86 ,buffer, 16);
|
|
||||||
// calibration.deadzone = (u16)((buffer[4] << 8) & 0xF00 | buffer[3]);
|
|
||||||
|
|
||||||
// Set a valid default calibration if data is missing
|
// Set a valid default calibration if data is missing
|
||||||
ValidateCalibration(calibration);
|
ValidateCalibration(calibration);
|
||||||
|
|
||||||
|
@ -49,34 +49,34 @@ DriverResult CalibrationProtocol::GetLeftJoyStickCalibration(JoyStickCalibration
|
||||||
|
|
||||||
DriverResult CalibrationProtocol::GetRightJoyStickCalibration(JoyStickCalibration& calibration) {
|
DriverResult CalibrationProtocol::GetRightJoyStickCalibration(JoyStickCalibration& calibration) {
|
||||||
ScopedSetBlocking sb(this);
|
ScopedSetBlocking sb(this);
|
||||||
std::vector<u8> buffer;
|
|
||||||
DriverResult result{DriverResult::Success};
|
DriverResult result{DriverResult::Success};
|
||||||
|
JoystickRightSpiCalibration spi_calibration{};
|
||||||
|
bool has_user_calibration = false;
|
||||||
calibration = {};
|
calibration = {};
|
||||||
|
|
||||||
result = ReadSPI(CalAddr::USER_RIGHT_MAGIC, sizeof(u16), buffer);
|
|
||||||
|
|
||||||
if (result == DriverResult::Success) {
|
if (result == DriverResult::Success) {
|
||||||
const bool has_user_calibration = buffer[0] == 0xB2 && buffer[1] == 0xA1;
|
result = HasUserCalibration(SpiAddress::USER_RIGHT_MAGIC, has_user_calibration);
|
||||||
if (has_user_calibration) {
|
}
|
||||||
result = ReadSPI(CalAddr::USER_RIGHT_DATA, 9, buffer);
|
|
||||||
} else {
|
// Read User defined calibration
|
||||||
result = ReadSPI(CalAddr::FACT_RIGHT_DATA, 9, buffer);
|
if (result == DriverResult::Success && has_user_calibration) {
|
||||||
}
|
result = ReadSPI(SpiAddress::USER_RIGHT_DATA, spi_calibration);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read Factory calibration
|
||||||
|
if (result == DriverResult::Success && !has_user_calibration) {
|
||||||
|
result = ReadSPI(SpiAddress::FACT_RIGHT_DATA, spi_calibration);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == DriverResult::Success) {
|
if (result == DriverResult::Success) {
|
||||||
calibration.x.center = static_cast<u16>(((buffer[1] & 0x0F) << 8) | buffer[0]);
|
calibration.x.center = GetXAxisCalibrationValue(spi_calibration.center);
|
||||||
calibration.y.center = static_cast<u16>((buffer[2] << 4) | (buffer[1] >> 4));
|
calibration.y.center = GetYAxisCalibrationValue(spi_calibration.center);
|
||||||
calibration.x.min = static_cast<u16>(((buffer[4] & 0x0F) << 8) | buffer[3]);
|
calibration.x.min = GetXAxisCalibrationValue(spi_calibration.min);
|
||||||
calibration.y.min = static_cast<u16>((buffer[5] << 4) | (buffer[4] >> 4));
|
calibration.y.min = GetYAxisCalibrationValue(spi_calibration.min);
|
||||||
calibration.x.max = static_cast<u16>(((buffer[7] & 0x0F) << 8) | buffer[6]);
|
calibration.x.max = GetXAxisCalibrationValue(spi_calibration.max);
|
||||||
calibration.y.max = static_cast<u16>((buffer[8] << 4) | (buffer[7] >> 4));
|
calibration.y.max = GetYAxisCalibrationValue(spi_calibration.max);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nintendo fix for drifting stick
|
|
||||||
// buffer = ReadSPI(0x60, 0x98 , 16);
|
|
||||||
// joystick.deadzone = (u16)((buffer[4] << 8) & 0xF00 | buffer[3]);
|
|
||||||
|
|
||||||
// Set a valid default calibration if data is missing
|
// Set a valid default calibration if data is missing
|
||||||
ValidateCalibration(calibration);
|
ValidateCalibration(calibration);
|
||||||
|
|
||||||
|
@ -85,39 +85,41 @@ DriverResult CalibrationProtocol::GetRightJoyStickCalibration(JoyStickCalibratio
|
||||||
|
|
||||||
DriverResult CalibrationProtocol::GetImuCalibration(MotionCalibration& calibration) {
|
DriverResult CalibrationProtocol::GetImuCalibration(MotionCalibration& calibration) {
|
||||||
ScopedSetBlocking sb(this);
|
ScopedSetBlocking sb(this);
|
||||||
std::vector<u8> buffer;
|
|
||||||
DriverResult result{DriverResult::Success};
|
DriverResult result{DriverResult::Success};
|
||||||
|
ImuSpiCalibration spi_calibration{};
|
||||||
|
bool has_user_calibration = false;
|
||||||
calibration = {};
|
calibration = {};
|
||||||
|
|
||||||
result = ReadSPI(CalAddr::USER_IMU_MAGIC, sizeof(u16), buffer);
|
|
||||||
|
|
||||||
if (result == DriverResult::Success) {
|
if (result == DriverResult::Success) {
|
||||||
const bool has_user_calibration = buffer[0] == 0xB2 && buffer[1] == 0xA1;
|
result = HasUserCalibration(SpiAddress::USER_IMU_MAGIC, has_user_calibration);
|
||||||
if (has_user_calibration) {
|
}
|
||||||
result = ReadSPI(CalAddr::USER_IMU_DATA, sizeof(IMUCalibration), buffer);
|
|
||||||
} else {
|
// Read User defined calibration
|
||||||
result = ReadSPI(CalAddr::FACT_IMU_DATA, sizeof(IMUCalibration), buffer);
|
if (result == DriverResult::Success && has_user_calibration) {
|
||||||
}
|
result = ReadSPI(SpiAddress::USER_IMU_DATA, spi_calibration);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read Factory calibration
|
||||||
|
if (result == DriverResult::Success && !has_user_calibration) {
|
||||||
|
result = ReadSPI(SpiAddress::FACT_IMU_DATA, spi_calibration);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == DriverResult::Success) {
|
if (result == DriverResult::Success) {
|
||||||
IMUCalibration device_calibration{};
|
calibration.accelerometer[0].offset = spi_calibration.accelerometer_offset[0];
|
||||||
memcpy(&device_calibration, buffer.data(), sizeof(IMUCalibration));
|
calibration.accelerometer[1].offset = spi_calibration.accelerometer_offset[1];
|
||||||
calibration.accelerometer[0].offset = device_calibration.accelerometer_offset[0];
|
calibration.accelerometer[2].offset = spi_calibration.accelerometer_offset[2];
|
||||||
calibration.accelerometer[1].offset = device_calibration.accelerometer_offset[1];
|
|
||||||
calibration.accelerometer[2].offset = device_calibration.accelerometer_offset[2];
|
|
||||||
|
|
||||||
calibration.accelerometer[0].scale = device_calibration.accelerometer_scale[0];
|
calibration.accelerometer[0].scale = spi_calibration.accelerometer_scale[0];
|
||||||
calibration.accelerometer[1].scale = device_calibration.accelerometer_scale[1];
|
calibration.accelerometer[1].scale = spi_calibration.accelerometer_scale[1];
|
||||||
calibration.accelerometer[2].scale = device_calibration.accelerometer_scale[2];
|
calibration.accelerometer[2].scale = spi_calibration.accelerometer_scale[2];
|
||||||
|
|
||||||
calibration.gyro[0].offset = device_calibration.gyroscope_offset[0];
|
calibration.gyro[0].offset = spi_calibration.gyroscope_offset[0];
|
||||||
calibration.gyro[1].offset = device_calibration.gyroscope_offset[1];
|
calibration.gyro[1].offset = spi_calibration.gyroscope_offset[1];
|
||||||
calibration.gyro[2].offset = device_calibration.gyroscope_offset[2];
|
calibration.gyro[2].offset = spi_calibration.gyroscope_offset[2];
|
||||||
|
|
||||||
calibration.gyro[0].scale = device_calibration.gyroscope_scale[0];
|
calibration.gyro[0].scale = spi_calibration.gyroscope_scale[0];
|
||||||
calibration.gyro[1].scale = device_calibration.gyroscope_scale[1];
|
calibration.gyro[1].scale = spi_calibration.gyroscope_scale[1];
|
||||||
calibration.gyro[2].scale = device_calibration.gyroscope_scale[2];
|
calibration.gyro[2].scale = spi_calibration.gyroscope_scale[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
ValidateCalibration(calibration);
|
ValidateCalibration(calibration);
|
||||||
|
@ -127,10 +129,12 @@ DriverResult CalibrationProtocol::GetImuCalibration(MotionCalibration& calibrati
|
||||||
|
|
||||||
DriverResult CalibrationProtocol::GetRingCalibration(RingCalibration& calibration,
|
DriverResult CalibrationProtocol::GetRingCalibration(RingCalibration& calibration,
|
||||||
s16 current_value) {
|
s16 current_value) {
|
||||||
|
constexpr s16 DefaultRingRange{800};
|
||||||
|
|
||||||
// TODO: Get default calibration form ring itself
|
// TODO: Get default calibration form ring itself
|
||||||
if (ring_data_max == 0 && ring_data_min == 0) {
|
if (ring_data_max == 0 && ring_data_min == 0) {
|
||||||
ring_data_max = current_value + 800;
|
ring_data_max = current_value + DefaultRingRange;
|
||||||
ring_data_min = current_value - 800;
|
ring_data_min = current_value - DefaultRingRange;
|
||||||
ring_data_default = current_value;
|
ring_data_default = current_value;
|
||||||
}
|
}
|
||||||
ring_data_max = std::max(ring_data_max, current_value);
|
ring_data_max = std::max(ring_data_max, current_value);
|
||||||
|
@ -143,42 +147,72 @@ DriverResult CalibrationProtocol::GetRingCalibration(RingCalibration& calibratio
|
||||||
return DriverResult::Success;
|
return DriverResult::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DriverResult CalibrationProtocol::HasUserCalibration(SpiAddress address,
|
||||||
|
bool& has_user_calibration) {
|
||||||
|
MagicSpiCalibration spi_magic{};
|
||||||
|
const DriverResult result{ReadSPI(address, spi_magic)};
|
||||||
|
has_user_calibration = false;
|
||||||
|
if (result == DriverResult::Success) {
|
||||||
|
has_user_calibration = spi_magic.first == CalibrationMagic::USR_MAGIC_0 &&
|
||||||
|
spi_magic.second == CalibrationMagic::USR_MAGIC_1;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 CalibrationProtocol::GetXAxisCalibrationValue(std::span<u8> block) const {
|
||||||
|
return static_cast<u16>(((block[1] & 0x0F) << 8) | block[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 CalibrationProtocol::GetYAxisCalibrationValue(std::span<u8> block) const {
|
||||||
|
return static_cast<u16>((block[2] << 4) | (block[1] >> 4));
|
||||||
|
}
|
||||||
|
|
||||||
void CalibrationProtocol::ValidateCalibration(JoyStickCalibration& calibration) {
|
void CalibrationProtocol::ValidateCalibration(JoyStickCalibration& calibration) {
|
||||||
constexpr u16 DefaultStickCenter{2048};
|
constexpr u16 DefaultStickCenter{0x800};
|
||||||
constexpr u16 DefaultStickRange{1740};
|
constexpr u16 DefaultStickRange{0x6cc};
|
||||||
|
|
||||||
if (calibration.x.center == 0xFFF || calibration.x.center == 0) {
|
calibration.x.center = ValidateValue(calibration.x.center, DefaultStickCenter);
|
||||||
calibration.x.center = DefaultStickCenter;
|
calibration.x.max = ValidateValue(calibration.x.max, DefaultStickRange);
|
||||||
}
|
calibration.x.min = ValidateValue(calibration.x.min, DefaultStickRange);
|
||||||
if (calibration.x.max == 0xFFF || calibration.x.max == 0) {
|
|
||||||
calibration.x.max = DefaultStickRange;
|
|
||||||
}
|
|
||||||
if (calibration.x.min == 0xFFF || calibration.x.min == 0) {
|
|
||||||
calibration.x.min = DefaultStickRange;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (calibration.y.center == 0xFFF || calibration.y.center == 0) {
|
calibration.y.center = ValidateValue(calibration.y.center, DefaultStickCenter);
|
||||||
calibration.y.center = DefaultStickCenter;
|
calibration.y.max = ValidateValue(calibration.y.max, DefaultStickRange);
|
||||||
}
|
calibration.y.min = ValidateValue(calibration.y.min, DefaultStickRange);
|
||||||
if (calibration.y.max == 0xFFF || calibration.y.max == 0) {
|
|
||||||
calibration.y.max = DefaultStickRange;
|
|
||||||
}
|
|
||||||
if (calibration.y.min == 0xFFF || calibration.y.min == 0) {
|
|
||||||
calibration.y.min = DefaultStickRange;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CalibrationProtocol::ValidateCalibration(MotionCalibration& calibration) {
|
void CalibrationProtocol::ValidateCalibration(MotionCalibration& calibration) {
|
||||||
|
constexpr s16 DefaultAccelerometerScale{0x4000};
|
||||||
|
constexpr s16 DefaultGyroScale{0x3be7};
|
||||||
|
constexpr s16 DefaultOffset{0};
|
||||||
|
|
||||||
for (auto& sensor : calibration.accelerometer) {
|
for (auto& sensor : calibration.accelerometer) {
|
||||||
if (sensor.scale == 0) {
|
sensor.scale = ValidateValue(sensor.scale, DefaultAccelerometerScale);
|
||||||
sensor.scale = 0x4000;
|
sensor.offset = ValidateValue(sensor.offset, DefaultOffset);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for (auto& sensor : calibration.gyro) {
|
for (auto& sensor : calibration.gyro) {
|
||||||
if (sensor.scale == 0) {
|
sensor.scale = ValidateValue(sensor.scale, DefaultGyroScale);
|
||||||
sensor.scale = 0x3be7;
|
sensor.offset = ValidateValue(sensor.offset, DefaultOffset);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u16 CalibrationProtocol::ValidateValue(u16 value, u16 default_value) const {
|
||||||
|
if (value == 0) {
|
||||||
|
return default_value;
|
||||||
|
}
|
||||||
|
if (value == 0xFFF) {
|
||||||
|
return default_value;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
s16 CalibrationProtocol::ValidateValue(s16 value, s16 default_value) const {
|
||||||
|
if (value == 0) {
|
||||||
|
return default_value;
|
||||||
|
}
|
||||||
|
if (value == 0xFFF) {
|
||||||
|
return default_value;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace InputCommon::Joycon
|
} // namespace InputCommon::Joycon
|
||||||
|
|
|
@ -53,9 +53,27 @@ public:
|
||||||
DriverResult GetRingCalibration(RingCalibration& calibration, s16 current_value);
|
DriverResult GetRingCalibration(RingCalibration& calibration, s16 current_value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/// Returns true if the specified address corresponds to the magic value of user calibration
|
||||||
|
DriverResult HasUserCalibration(SpiAddress address, bool& has_user_calibration);
|
||||||
|
|
||||||
|
/// Converts a raw calibration block to an u16 value containing the x axis value
|
||||||
|
u16 GetXAxisCalibrationValue(std::span<u8> block) const;
|
||||||
|
|
||||||
|
/// Converts a raw calibration block to an u16 value containing the y axis value
|
||||||
|
u16 GetYAxisCalibrationValue(std::span<u8> block) const;
|
||||||
|
|
||||||
|
/// Ensures that all joystick calibration values are set
|
||||||
void ValidateCalibration(JoyStickCalibration& calibration);
|
void ValidateCalibration(JoyStickCalibration& calibration);
|
||||||
|
|
||||||
|
/// Ensures that all motion calibration values are set
|
||||||
void ValidateCalibration(MotionCalibration& calibration);
|
void ValidateCalibration(MotionCalibration& calibration);
|
||||||
|
|
||||||
|
/// Returns the default value if the value is either zero or 0xFFF
|
||||||
|
u16 ValidateValue(u16 value, u16 default_value) const;
|
||||||
|
|
||||||
|
/// Returns the default value if the value is either zero or 0xFFF
|
||||||
|
s16 ValidateValue(s16 value, s16 default_value) const;
|
||||||
|
|
||||||
s16 ring_data_max = 0;
|
s16 ring_data_max = 0;
|
||||||
s16 ring_data_default = 0;
|
s16 ring_data_default = 0;
|
||||||
s16 ring_data_min = 0;
|
s16 ring_data_min = 0;
|
||||||
|
|
|
@ -22,8 +22,8 @@ void JoyconCommonProtocol::SetNonBlocking() {
|
||||||
}
|
}
|
||||||
|
|
||||||
DriverResult JoyconCommonProtocol::GetDeviceType(ControllerType& controller_type) {
|
DriverResult JoyconCommonProtocol::GetDeviceType(ControllerType& controller_type) {
|
||||||
std::vector<u8> buffer;
|
std::array<u8, 1> buffer{};
|
||||||
const auto result = ReadSPI(CalAddr::DEVICE_TYPE, 1, buffer);
|
const auto result = ReadRawSPI(SpiAddress::DEVICE_TYPE, buffer);
|
||||||
controller_type = ControllerType::None;
|
controller_type = ControllerType::None;
|
||||||
|
|
||||||
if (result == DriverResult::Success) {
|
if (result == DriverResult::Success) {
|
||||||
|
@ -148,11 +148,13 @@ DriverResult JoyconCommonProtocol::SendVibrationReport(std::span<const u8> buffe
|
||||||
return SendData(local_buffer);
|
return SendData(local_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
DriverResult JoyconCommonProtocol::ReadSPI(CalAddr addr, u8 size, std::vector<u8>& output) {
|
DriverResult JoyconCommonProtocol::ReadRawSPI(SpiAddress addr, std::span<u8> output) {
|
||||||
|
constexpr std::size_t HeaderSize = 20;
|
||||||
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, size};
|
std::array<u8, 5> buffer = {0x00, 0x00, 0x00, 0x00, static_cast<u8>(size)};
|
||||||
std::vector<u8> local_buffer(size + 20);
|
std::vector<u8> local_buffer{};
|
||||||
|
|
||||||
buffer[0] = static_cast<u8>(static_cast<u16>(addr) & 0x00FF);
|
buffer[0] = static_cast<u8>(static_cast<u16>(addr) & 0x00FF);
|
||||||
buffer[1] = static_cast<u8>((static_cast<u16>(addr) & 0xFF00) >> 8);
|
buffer[1] = static_cast<u8>((static_cast<u16>(addr) & 0xFF00) >> 8);
|
||||||
|
@ -167,8 +169,12 @@ DriverResult JoyconCommonProtocol::ReadSPI(CalAddr addr, u8 size, std::vector<u8
|
||||||
}
|
}
|
||||||
} while (local_buffer[15] != buffer[0] || local_buffer[16] != buffer[1]);
|
} while (local_buffer[15] != buffer[0] || local_buffer[16] != buffer[1]);
|
||||||
|
|
||||||
|
if (local_buffer.size() < size + HeaderSize) {
|
||||||
|
return DriverResult::WrongReply;
|
||||||
|
}
|
||||||
|
|
||||||
// Remove header from output
|
// Remove header from output
|
||||||
output = std::vector<u8>(local_buffer.begin() + 20, local_buffer.begin() + 20 + size);
|
memcpy(output.data(), local_buffer.data() + HeaderSize, size);
|
||||||
return DriverResult::Success;
|
return DriverResult::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,10 +97,29 @@ 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
|
||||||
* @param size in bytes to be read
|
|
||||||
* @returns output buffer containing the responce
|
* @returns output buffer containing the responce
|
||||||
*/
|
*/
|
||||||
DriverResult ReadSPI(CalAddr addr, u8 size, std::vector<u8>& output);
|
DriverResult ReadRawSPI(SpiAddress addr, std::span<u8> output);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the SPI memory stored on the joycon
|
||||||
|
* @param Initial address location
|
||||||
|
* @returns output object containing the responce
|
||||||
|
*/
|
||||||
|
template <typename Output>
|
||||||
|
requires std::is_trivially_copyable_v<Output> DriverResult ReadSPI(SpiAddress addr,
|
||||||
|
Output& output) {
|
||||||
|
std::array<u8, sizeof(Output)> buffer;
|
||||||
|
output = {};
|
||||||
|
|
||||||
|
const auto result = ReadRawSPI(addr, buffer);
|
||||||
|
if (result != DriverResult::Success) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::memcpy(&output, buffer.data(), sizeof(Output));
|
||||||
|
return DriverResult::Success;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables MCU chip on the joycon
|
* Enables MCU chip on the joycon
|
||||||
|
|
|
@ -71,8 +71,8 @@ DriverResult GenericProtocol::GetBattery(u32& battery_level) {
|
||||||
|
|
||||||
DriverResult GenericProtocol::GetColor(Color& color) {
|
DriverResult GenericProtocol::GetColor(Color& color) {
|
||||||
ScopedSetBlocking sb(this);
|
ScopedSetBlocking sb(this);
|
||||||
std::vector<u8> buffer;
|
std::array<u8, 12> buffer{};
|
||||||
const auto result = ReadSPI(CalAddr::COLOR_DATA, 12, buffer);
|
const auto result = ReadRawSPI(SpiAddress::COLOR_DATA, buffer);
|
||||||
|
|
||||||
color = {};
|
color = {};
|
||||||
if (result == DriverResult::Success) {
|
if (result == DriverResult::Success) {
|
||||||
|
@ -87,8 +87,8 @@ DriverResult GenericProtocol::GetColor(Color& color) {
|
||||||
|
|
||||||
DriverResult GenericProtocol::GetSerialNumber(SerialNumber& serial_number) {
|
DriverResult GenericProtocol::GetSerialNumber(SerialNumber& serial_number) {
|
||||||
ScopedSetBlocking sb(this);
|
ScopedSetBlocking sb(this);
|
||||||
std::vector<u8> buffer;
|
std::array<u8, 16> buffer{};
|
||||||
const auto result = ReadSPI(CalAddr::SERIAL_NUMBER, 16, buffer);
|
const auto result = ReadRawSPI(SpiAddress::SERIAL_NUMBER, buffer);
|
||||||
|
|
||||||
serial_number = {};
|
serial_number = {};
|
||||||
if (result == DriverResult::Success) {
|
if (result == DriverResult::Success) {
|
||||||
|
|
|
@ -159,13 +159,12 @@ enum class UsbSubCommand : u8 {
|
||||||
SEND_UART = 0x92,
|
SEND_UART = 0x92,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class CalMagic : u8 {
|
enum class CalibrationMagic : u8 {
|
||||||
USR_MAGIC_0 = 0xB2,
|
USR_MAGIC_0 = 0xB2,
|
||||||
USR_MAGIC_1 = 0xA1,
|
USR_MAGIC_1 = 0xA1,
|
||||||
USRR_MAGI_SIZE = 2,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class CalAddr {
|
enum class SpiAddress {
|
||||||
SERIAL_NUMBER = 0X6000,
|
SERIAL_NUMBER = 0X6000,
|
||||||
DEVICE_TYPE = 0X6012,
|
DEVICE_TYPE = 0X6012,
|
||||||
COLOR_EXIST = 0X601B,
|
COLOR_EXIST = 0X601B,
|
||||||
|
@ -396,10 +395,35 @@ struct MotionData {
|
||||||
u64 delta_timestamp{};
|
u64 delta_timestamp{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Output from SPI read command containing user calibration magic
|
||||||
|
struct MagicSpiCalibration {
|
||||||
|
CalibrationMagic first;
|
||||||
|
CalibrationMagic second;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(MagicSpiCalibration) == 0x2, "MagicSpiCalibration is an invalid size");
|
||||||
|
|
||||||
|
// Output from SPI read command containing left joystick calibration
|
||||||
|
struct JoystickLeftSpiCalibration {
|
||||||
|
std::array<u8, 3> max;
|
||||||
|
std::array<u8, 3> center;
|
||||||
|
std::array<u8, 3> min;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(JoystickLeftSpiCalibration) == 0x9,
|
||||||
|
"JoystickLeftSpiCalibration is an invalid size");
|
||||||
|
|
||||||
|
// Output from SPI read command containing right joystick calibration
|
||||||
|
struct JoystickRightSpiCalibration {
|
||||||
|
std::array<u8, 3> center;
|
||||||
|
std::array<u8, 3> min;
|
||||||
|
std::array<u8, 3> max;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(JoystickRightSpiCalibration) == 0x9,
|
||||||
|
"JoystickRightSpiCalibration is an invalid size");
|
||||||
|
|
||||||
struct JoyStickAxisCalibration {
|
struct JoyStickAxisCalibration {
|
||||||
u16 max{1};
|
u16 max;
|
||||||
u16 min{1};
|
u16 min;
|
||||||
u16 center{0};
|
u16 center;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct JoyStickCalibration {
|
struct JoyStickCalibration {
|
||||||
|
@ -407,6 +431,14 @@ struct JoyStickCalibration {
|
||||||
JoyStickAxisCalibration y;
|
JoyStickAxisCalibration y;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ImuSpiCalibration {
|
||||||
|
std::array<s16, 3> accelerometer_offset;
|
||||||
|
std::array<s16, 3> accelerometer_scale;
|
||||||
|
std::array<s16, 3> gyroscope_offset;
|
||||||
|
std::array<s16, 3> gyroscope_scale;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(ImuSpiCalibration) == 0x18, "ImuSpiCalibration is an invalid size");
|
||||||
|
|
||||||
struct RingCalibration {
|
struct RingCalibration {
|
||||||
s16 default_value;
|
s16 default_value;
|
||||||
s16 max_value;
|
s16 max_value;
|
||||||
|
@ -488,14 +520,6 @@ struct InputReportNfcIr {
|
||||||
static_assert(sizeof(InputReportNfcIr) == 0x29, "InputReportNfcIr is an invalid size");
|
static_assert(sizeof(InputReportNfcIr) == 0x29, "InputReportNfcIr is an invalid size");
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
struct IMUCalibration {
|
|
||||||
std::array<s16, 3> accelerometer_offset;
|
|
||||||
std::array<s16, 3> accelerometer_scale;
|
|
||||||
std::array<s16, 3> gyroscope_offset;
|
|
||||||
std::array<s16, 3> gyroscope_scale;
|
|
||||||
};
|
|
||||||
static_assert(sizeof(IMUCalibration) == 0x18, "IMUCalibration is an invalid size");
|
|
||||||
|
|
||||||
struct NFCReadBlock {
|
struct NFCReadBlock {
|
||||||
u8 start;
|
u8 start;
|
||||||
u8 end;
|
u8 end;
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -532,7 +532,7 @@ void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
|
void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
|
||||||
ScalarS32 lod) {
|
ScalarS32 lod, [[maybe_unused]] const IR::Value& skip_mips) {
|
||||||
const auto info{inst.Flags<IR::TextureInstInfo>()};
|
const auto info{inst.Flags<IR::TextureInstInfo>()};
|
||||||
const std::string texture{Texture(ctx, info, index)};
|
const std::string texture{Texture(ctx, info, index)};
|
||||||
const std::string_view type{TextureType(info)};
|
const std::string_view type{TextureType(info)};
|
||||||
|
|
|
@ -581,7 +581,7 @@ void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, const IR::Value& inde
|
||||||
void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
|
void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
|
||||||
const IR::Value& coord, const IR::Value& offset, ScalarS32 lod, ScalarS32 ms);
|
const IR::Value& coord, const IR::Value& offset, ScalarS32 lod, ScalarS32 ms);
|
||||||
void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
|
void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
|
||||||
ScalarS32 lod);
|
ScalarS32 lod, const IR::Value& skip_mips);
|
||||||
void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord);
|
void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord);
|
||||||
void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
|
void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
|
||||||
const IR::Value& coord, const IR::Value& derivatives,
|
const IR::Value& coord, const IR::Value& derivatives,
|
||||||
|
|
|
@ -460,27 +460,27 @@ void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
|
void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
|
||||||
std::string_view lod) {
|
std::string_view lod, const IR::Value& skip_mips_val) {
|
||||||
const auto info{inst.Flags<IR::TextureInstInfo>()};
|
const auto info{inst.Flags<IR::TextureInstInfo>()};
|
||||||
const auto texture{Texture(ctx, info, index)};
|
const auto texture{Texture(ctx, info, index)};
|
||||||
|
const bool skip_mips{skip_mips_val.U1()};
|
||||||
|
const auto mips{
|
||||||
|
[&] { return skip_mips ? "0u" : fmt::format("uint(textureQueryLevels({}))", texture); }};
|
||||||
switch (info.type) {
|
switch (info.type) {
|
||||||
case TextureType::Color1D:
|
case TextureType::Color1D:
|
||||||
return ctx.AddU32x4(
|
return ctx.AddU32x4("{}=uvec4(uint(textureSize({},int({}))),0u,0u,{});", inst, texture, lod,
|
||||||
"{}=uvec4(uint(textureSize({},int({}))),0u,0u,uint(textureQueryLevels({})));", inst,
|
mips());
|
||||||
texture, lod, texture);
|
|
||||||
case TextureType::ColorArray1D:
|
case TextureType::ColorArray1D:
|
||||||
case TextureType::Color2D:
|
case TextureType::Color2D:
|
||||||
case TextureType::ColorCube:
|
case TextureType::ColorCube:
|
||||||
case TextureType::Color2DRect:
|
case TextureType::Color2DRect:
|
||||||
return ctx.AddU32x4(
|
return ctx.AddU32x4("{}=uvec4(uvec2(textureSize({},int({}))),0u,{});", inst, texture, lod,
|
||||||
"{}=uvec4(uvec2(textureSize({},int({}))),0u,uint(textureQueryLevels({})));", inst,
|
mips());
|
||||||
texture, lod, texture);
|
|
||||||
case TextureType::ColorArray2D:
|
case TextureType::ColorArray2D:
|
||||||
case TextureType::Color3D:
|
case TextureType::Color3D:
|
||||||
case TextureType::ColorArrayCube:
|
case TextureType::ColorArrayCube:
|
||||||
return ctx.AddU32x4(
|
return ctx.AddU32x4("{}=uvec4(uvec3(textureSize({},int({}))),{});", inst, texture, lod,
|
||||||
"{}=uvec4(uvec3(textureSize({},int({}))),uint(textureQueryLevels({})));", inst, texture,
|
mips());
|
||||||
lod, texture);
|
|
||||||
case TextureType::Buffer:
|
case TextureType::Buffer:
|
||||||
throw NotImplementedException("EmitImageQueryDimensions Texture buffers");
|
throw NotImplementedException("EmitImageQueryDimensions Texture buffers");
|
||||||
}
|
}
|
||||||
|
|
|
@ -654,7 +654,7 @@ void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
|
||||||
std::string_view coords, std::string_view offset, std::string_view lod,
|
std::string_view coords, std::string_view offset, std::string_view lod,
|
||||||
std::string_view ms);
|
std::string_view ms);
|
||||||
void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
|
void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
|
||||||
std::string_view lod);
|
std::string_view lod, const IR::Value& skip_mips);
|
||||||
void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
|
void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
|
||||||
std::string_view coords);
|
std::string_view coords);
|
||||||
void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
|
void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
|
||||||
|
|
|
@ -445,11 +445,13 @@ Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id c
|
||||||
TextureImage(ctx, info, index), coords, operands.MaskOptional(), operands.Span());
|
TextureImage(ctx, info, index), coords, operands.MaskOptional(), operands.Span());
|
||||||
}
|
}
|
||||||
|
|
||||||
Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod) {
|
Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod,
|
||||||
|
const IR::Value& skip_mips_val) {
|
||||||
const auto info{inst->Flags<IR::TextureInstInfo>()};
|
const auto info{inst->Flags<IR::TextureInstInfo>()};
|
||||||
const Id image{TextureImage(ctx, info, index)};
|
const Id image{TextureImage(ctx, info, index)};
|
||||||
const Id zero{ctx.u32_zero_value};
|
const Id zero{ctx.u32_zero_value};
|
||||||
const auto mips{[&] { return ctx.OpImageQueryLevels(ctx.U32[1], image); }};
|
const bool skip_mips{skip_mips_val.U1()};
|
||||||
|
const auto mips{[&] { return skip_mips ? zero : ctx.OpImageQueryLevels(ctx.U32[1], image); }};
|
||||||
switch (info.type) {
|
switch (info.type) {
|
||||||
case TextureType::Color1D:
|
case TextureType::Color1D:
|
||||||
return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[1], image, lod),
|
return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[1], image, lod),
|
||||||
|
|
|
@ -539,7 +539,8 @@ Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index,
|
||||||
const IR::Value& offset, const IR::Value& offset2, Id dref);
|
const IR::Value& offset, const IR::Value& offset2, Id dref);
|
||||||
Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset,
|
Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset,
|
||||||
Id lod, Id ms);
|
Id lod, Id ms);
|
||||||
Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod);
|
Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod,
|
||||||
|
const IR::Value& skip_mips);
|
||||||
Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords);
|
Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords);
|
||||||
Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
|
Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
|
||||||
Id derivates, Id offset, Id lod_clamp);
|
Id derivates, Id offset, Id lod_clamp);
|
||||||
|
|
|
@ -1846,15 +1846,16 @@ Value IREmitter::ImageFetch(const Value& handle, const Value& coords, const Valu
|
||||||
return Inst(op, Flags{info}, handle, coords, offset, lod, multisampling);
|
return Inst(op, Flags{info}, handle, coords, offset, lod, multisampling);
|
||||||
}
|
}
|
||||||
|
|
||||||
Value IREmitter::ImageQueryDimension(const Value& handle, const IR::U32& lod) {
|
Value IREmitter::ImageQueryDimension(const Value& handle, const IR::U32& lod,
|
||||||
|
const IR::U1& skip_mips) {
|
||||||
const Opcode op{handle.IsImmediate() ? Opcode::BoundImageQueryDimensions
|
const Opcode op{handle.IsImmediate() ? Opcode::BoundImageQueryDimensions
|
||||||
: Opcode::BindlessImageQueryDimensions};
|
: Opcode::BindlessImageQueryDimensions};
|
||||||
return Inst(op, handle, lod);
|
return Inst(op, handle, lod, skip_mips);
|
||||||
}
|
}
|
||||||
|
|
||||||
Value IREmitter::ImageQueryDimension(const Value& handle, const IR::U32& lod,
|
Value IREmitter::ImageQueryDimension(const Value& handle, const IR::U32& lod,
|
||||||
TextureInstInfo info) {
|
const IR::U1& skip_mips, TextureInstInfo info) {
|
||||||
return Inst(Opcode::ImageQueryDimensions, Flags{info}, handle, lod);
|
return Inst(Opcode::ImageQueryDimensions, Flags{info}, handle, lod, skip_mips);
|
||||||
}
|
}
|
||||||
|
|
||||||
Value IREmitter::ImageQueryLod(const Value& handle, const Value& coords, TextureInstInfo info) {
|
Value IREmitter::ImageQueryLod(const Value& handle, const Value& coords, TextureInstInfo info) {
|
||||||
|
|
|
@ -320,9 +320,10 @@ public:
|
||||||
[[nodiscard]] F32 ImageSampleDrefExplicitLod(const Value& handle, const Value& coords,
|
[[nodiscard]] F32 ImageSampleDrefExplicitLod(const Value& handle, const Value& coords,
|
||||||
const F32& dref, const F32& lod,
|
const F32& dref, const F32& lod,
|
||||||
const Value& offset, TextureInstInfo info);
|
const Value& offset, TextureInstInfo info);
|
||||||
[[nodiscard]] Value ImageQueryDimension(const Value& handle, const IR::U32& lod);
|
|
||||||
[[nodiscard]] Value ImageQueryDimension(const Value& handle, const IR::U32& lod,
|
[[nodiscard]] Value ImageQueryDimension(const Value& handle, const IR::U32& lod,
|
||||||
TextureInstInfo info);
|
const IR::U1& skip_mips);
|
||||||
|
[[nodiscard]] Value ImageQueryDimension(const Value& handle, const IR::U32& lod,
|
||||||
|
const IR::U1& skip_mips, TextureInstInfo info);
|
||||||
|
|
||||||
[[nodiscard]] Value ImageQueryLod(const Value& handle, const Value& coords,
|
[[nodiscard]] Value ImageQueryLod(const Value& handle, const Value& coords,
|
||||||
TextureInstInfo info);
|
TextureInstInfo info);
|
||||||
|
|
|
@ -482,7 +482,7 @@ OPCODE(BindlessImageSampleDrefExplicitLod, F32, U32,
|
||||||
OPCODE(BindlessImageGather, F32x4, U32, Opaque, Opaque, Opaque, )
|
OPCODE(BindlessImageGather, F32x4, U32, Opaque, Opaque, Opaque, )
|
||||||
OPCODE(BindlessImageGatherDref, F32x4, U32, Opaque, Opaque, Opaque, F32, )
|
OPCODE(BindlessImageGatherDref, F32x4, U32, Opaque, Opaque, Opaque, F32, )
|
||||||
OPCODE(BindlessImageFetch, F32x4, U32, Opaque, Opaque, U32, Opaque, )
|
OPCODE(BindlessImageFetch, F32x4, U32, Opaque, Opaque, U32, Opaque, )
|
||||||
OPCODE(BindlessImageQueryDimensions, U32x4, U32, U32, )
|
OPCODE(BindlessImageQueryDimensions, U32x4, U32, U32, U1, )
|
||||||
OPCODE(BindlessImageQueryLod, F32x4, U32, Opaque, )
|
OPCODE(BindlessImageQueryLod, F32x4, U32, Opaque, )
|
||||||
OPCODE(BindlessImageGradient, F32x4, U32, Opaque, Opaque, Opaque, Opaque, )
|
OPCODE(BindlessImageGradient, F32x4, U32, Opaque, Opaque, Opaque, Opaque, )
|
||||||
OPCODE(BindlessImageRead, U32x4, U32, Opaque, )
|
OPCODE(BindlessImageRead, U32x4, U32, Opaque, )
|
||||||
|
@ -495,7 +495,7 @@ OPCODE(BoundImageSampleDrefExplicitLod, F32, U32,
|
||||||
OPCODE(BoundImageGather, F32x4, U32, Opaque, Opaque, Opaque, )
|
OPCODE(BoundImageGather, F32x4, U32, Opaque, Opaque, Opaque, )
|
||||||
OPCODE(BoundImageGatherDref, F32x4, U32, Opaque, Opaque, Opaque, F32, )
|
OPCODE(BoundImageGatherDref, F32x4, U32, Opaque, Opaque, Opaque, F32, )
|
||||||
OPCODE(BoundImageFetch, F32x4, U32, Opaque, Opaque, U32, Opaque, )
|
OPCODE(BoundImageFetch, F32x4, U32, Opaque, Opaque, U32, Opaque, )
|
||||||
OPCODE(BoundImageQueryDimensions, U32x4, U32, U32, )
|
OPCODE(BoundImageQueryDimensions, U32x4, U32, U32, U1, )
|
||||||
OPCODE(BoundImageQueryLod, F32x4, U32, Opaque, )
|
OPCODE(BoundImageQueryLod, F32x4, U32, Opaque, )
|
||||||
OPCODE(BoundImageGradient, F32x4, U32, Opaque, Opaque, Opaque, Opaque, )
|
OPCODE(BoundImageGradient, F32x4, U32, Opaque, Opaque, Opaque, Opaque, )
|
||||||
OPCODE(BoundImageRead, U32x4, U32, Opaque, )
|
OPCODE(BoundImageRead, U32x4, U32, Opaque, )
|
||||||
|
@ -508,7 +508,7 @@ OPCODE(ImageSampleDrefExplicitLod, F32, Opaq
|
||||||
OPCODE(ImageGather, F32x4, Opaque, Opaque, Opaque, Opaque, )
|
OPCODE(ImageGather, F32x4, Opaque, Opaque, Opaque, Opaque, )
|
||||||
OPCODE(ImageGatherDref, F32x4, Opaque, Opaque, Opaque, Opaque, F32, )
|
OPCODE(ImageGatherDref, F32x4, Opaque, Opaque, Opaque, Opaque, F32, )
|
||||||
OPCODE(ImageFetch, F32x4, Opaque, Opaque, Opaque, U32, Opaque, )
|
OPCODE(ImageFetch, F32x4, Opaque, Opaque, Opaque, U32, Opaque, )
|
||||||
OPCODE(ImageQueryDimensions, U32x4, Opaque, U32, )
|
OPCODE(ImageQueryDimensions, U32x4, Opaque, U32, U1, )
|
||||||
OPCODE(ImageQueryLod, F32x4, Opaque, Opaque, )
|
OPCODE(ImageQueryLod, F32x4, Opaque, Opaque, )
|
||||||
OPCODE(ImageGradient, F32x4, Opaque, Opaque, Opaque, Opaque, Opaque, )
|
OPCODE(ImageGradient, F32x4, Opaque, Opaque, Opaque, Opaque, Opaque, )
|
||||||
OPCODE(ImageRead, U32x4, Opaque, Opaque, )
|
OPCODE(ImageRead, U32x4, Opaque, Opaque, )
|
||||||
|
|
|
@ -15,11 +15,13 @@ enum class Mode : u64 {
|
||||||
SamplePos = 5,
|
SamplePos = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
IR::Value Query(TranslatorVisitor& v, const IR::U32& handle, Mode mode, IR::Reg src_reg) {
|
IR::Value Query(TranslatorVisitor& v, const IR::U32& handle, Mode mode, IR::Reg src_reg, u64 mask) {
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case Mode::Dimension: {
|
case Mode::Dimension: {
|
||||||
|
const bool needs_num_mips{((mask >> 3) & 1) != 0};
|
||||||
|
const IR::U1 skip_mips{v.ir.Imm1(!needs_num_mips)};
|
||||||
const IR::U32 lod{v.X(src_reg)};
|
const IR::U32 lod{v.X(src_reg)};
|
||||||
return v.ir.ImageQueryDimension(handle, lod);
|
return v.ir.ImageQueryDimension(handle, lod, skip_mips);
|
||||||
}
|
}
|
||||||
case Mode::TextureType:
|
case Mode::TextureType:
|
||||||
case Mode::SamplePos:
|
case Mode::SamplePos:
|
||||||
|
@ -46,7 +48,7 @@ void Impl(TranslatorVisitor& v, u64 insn, std::optional<u32> cbuf_offset) {
|
||||||
handle = v.X(src_reg);
|
handle = v.X(src_reg);
|
||||||
++src_reg;
|
++src_reg;
|
||||||
}
|
}
|
||||||
const IR::Value query{Query(v, handle, txq.mode, src_reg)};
|
const IR::Value query{Query(v, handle, txq.mode, src_reg, txq.mask)};
|
||||||
IR::Reg dest_reg{txq.dest_reg};
|
IR::Reg dest_reg{txq.dest_reg};
|
||||||
for (int element = 0; element < 4; ++element) {
|
for (int element = 0; element < 4; ++element) {
|
||||||
if (((txq.mask >> element) & 1) == 0) {
|
if (((txq.mask >> element) & 1) == 0) {
|
||||||
|
|
|
@ -355,21 +355,21 @@ TextureInst MakeInst(Environment& env, IR::Block* block, IR::Inst& inst) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureType ReadTextureType(Environment& env, const ConstBufferAddr& cbuf) {
|
u32 GetTextureHandle(Environment& env, const ConstBufferAddr& cbuf) {
|
||||||
const u32 secondary_index{cbuf.has_secondary ? cbuf.secondary_index : cbuf.index};
|
const u32 secondary_index{cbuf.has_secondary ? cbuf.secondary_index : cbuf.index};
|
||||||
const u32 secondary_offset{cbuf.has_secondary ? cbuf.secondary_offset : cbuf.offset};
|
const u32 secondary_offset{cbuf.has_secondary ? cbuf.secondary_offset : cbuf.offset};
|
||||||
const u32 lhs_raw{env.ReadCbufValue(cbuf.index, cbuf.offset) << cbuf.shift_left};
|
const u32 lhs_raw{env.ReadCbufValue(cbuf.index, cbuf.offset) << cbuf.shift_left};
|
||||||
const u32 rhs_raw{env.ReadCbufValue(secondary_index, secondary_offset)
|
const u32 rhs_raw{env.ReadCbufValue(secondary_index, secondary_offset)
|
||||||
<< cbuf.secondary_shift_left};
|
<< cbuf.secondary_shift_left};
|
||||||
return env.ReadTextureType(lhs_raw | rhs_raw);
|
return lhs_raw | rhs_raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureType ReadTextureType(Environment& env, const ConstBufferAddr& cbuf) {
|
||||||
|
return env.ReadTextureType(GetTextureHandle(env, cbuf));
|
||||||
}
|
}
|
||||||
|
|
||||||
TexturePixelFormat ReadTexturePixelFormat(Environment& env, const ConstBufferAddr& cbuf) {
|
TexturePixelFormat ReadTexturePixelFormat(Environment& env, const ConstBufferAddr& cbuf) {
|
||||||
const u32 secondary_index{cbuf.has_secondary ? cbuf.secondary_index : cbuf.index};
|
return env.ReadTexturePixelFormat(GetTextureHandle(env, cbuf));
|
||||||
const u32 secondary_offset{cbuf.has_secondary ? cbuf.secondary_offset : cbuf.offset};
|
|
||||||
const u32 lhs_raw{env.ReadCbufValue(cbuf.index, cbuf.offset)};
|
|
||||||
const u32 rhs_raw{env.ReadCbufValue(secondary_index, secondary_offset)};
|
|
||||||
return env.ReadTexturePixelFormat(lhs_raw | rhs_raw);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Descriptors {
|
class Descriptors {
|
||||||
|
@ -386,8 +386,10 @@ public:
|
||||||
return Add(texture_buffer_descriptors, desc, [&desc](const auto& existing) {
|
return Add(texture_buffer_descriptors, desc, [&desc](const auto& existing) {
|
||||||
return desc.cbuf_index == existing.cbuf_index &&
|
return desc.cbuf_index == existing.cbuf_index &&
|
||||||
desc.cbuf_offset == existing.cbuf_offset &&
|
desc.cbuf_offset == existing.cbuf_offset &&
|
||||||
|
desc.shift_left == existing.shift_left &&
|
||||||
desc.secondary_cbuf_index == existing.secondary_cbuf_index &&
|
desc.secondary_cbuf_index == existing.secondary_cbuf_index &&
|
||||||
desc.secondary_cbuf_offset == existing.secondary_cbuf_offset &&
|
desc.secondary_cbuf_offset == existing.secondary_cbuf_offset &&
|
||||||
|
desc.secondary_shift_left == existing.secondary_shift_left &&
|
||||||
desc.count == existing.count && desc.size_shift == existing.size_shift &&
|
desc.count == existing.count && desc.size_shift == existing.size_shift &&
|
||||||
desc.has_secondary == existing.has_secondary;
|
desc.has_secondary == existing.has_secondary;
|
||||||
});
|
});
|
||||||
|
@ -405,15 +407,20 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 Add(const TextureDescriptor& desc) {
|
u32 Add(const TextureDescriptor& desc) {
|
||||||
return Add(texture_descriptors, desc, [&desc](const auto& existing) {
|
const u32 index{Add(texture_descriptors, desc, [&desc](const auto& existing) {
|
||||||
return desc.type == existing.type && desc.is_depth == existing.is_depth &&
|
return desc.type == existing.type && desc.is_depth == existing.is_depth &&
|
||||||
desc.has_secondary == existing.has_secondary &&
|
desc.has_secondary == existing.has_secondary &&
|
||||||
desc.cbuf_index == existing.cbuf_index &&
|
desc.cbuf_index == existing.cbuf_index &&
|
||||||
desc.cbuf_offset == existing.cbuf_offset &&
|
desc.cbuf_offset == existing.cbuf_offset &&
|
||||||
|
desc.shift_left == existing.shift_left &&
|
||||||
desc.secondary_cbuf_index == existing.secondary_cbuf_index &&
|
desc.secondary_cbuf_index == existing.secondary_cbuf_index &&
|
||||||
desc.secondary_cbuf_offset == existing.secondary_cbuf_offset &&
|
desc.secondary_cbuf_offset == existing.secondary_cbuf_offset &&
|
||||||
|
desc.secondary_shift_left == existing.secondary_shift_left &&
|
||||||
desc.count == existing.count && desc.size_shift == existing.size_shift;
|
desc.count == existing.count && desc.size_shift == existing.size_shift;
|
||||||
});
|
})};
|
||||||
|
// TODO: Read this from TIC
|
||||||
|
texture_descriptors[index].is_multisample |= desc.is_multisample;
|
||||||
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 Add(const ImageDescriptor& desc) {
|
u32 Add(const ImageDescriptor& desc) {
|
||||||
|
@ -452,7 +459,8 @@ void PatchImageSampleImplicitLod(IR::Block& block, IR::Inst& inst) {
|
||||||
const IR::Value coord(inst.Arg(1));
|
const IR::Value coord(inst.Arg(1));
|
||||||
const IR::Value handle(ir.Imm32(0));
|
const IR::Value handle(ir.Imm32(0));
|
||||||
const IR::U32 lod{ir.Imm32(0)};
|
const IR::U32 lod{ir.Imm32(0)};
|
||||||
const IR::Value texture_size = ir.ImageQueryDimension(handle, lod, info);
|
const IR::U1 skip_mips{ir.Imm1(true)};
|
||||||
|
const IR::Value texture_size = ir.ImageQueryDimension(handle, lod, skip_mips, info);
|
||||||
inst.SetArg(
|
inst.SetArg(
|
||||||
1, ir.CompositeConstruct(
|
1, ir.CompositeConstruct(
|
||||||
ir.FPMul(IR::F32(ir.CompositeExtract(coord, 0)),
|
ir.FPMul(IR::F32(ir.CompositeExtract(coord, 0)),
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"), [&] {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue