mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-26 21:11:49 +01:00
Introduce Custom Span Class + IPC Buffer -> Span
This commit is contained in:
parent
4d6ae9aa26
commit
20559c5dca
@ -139,9 +139,8 @@ extern "C" JNIEXPORT void JNICALL Java_emu_skyline_EmulationActivity_setTouchSta
|
||||
auto input = inputWeak.lock();
|
||||
jboolean isCopy{false};
|
||||
|
||||
std::span<Point> points(reinterpret_cast<Point *>(env->GetIntArrayElements(pointsJni, &isCopy)), env->GetArrayLength(pointsJni) / (sizeof(Point) / sizeof(jint)));
|
||||
skyline::span<Point> points(reinterpret_cast<Point *>(env->GetIntArrayElements(pointsJni, &isCopy)), env->GetArrayLength(pointsJni) / (sizeof(Point) / sizeof(jint)));
|
||||
input->touch.SetState(points);
|
||||
|
||||
env->ReleaseIntArrayElements(pointsJni, reinterpret_cast<jint *>(points.data()), JNI_ABORT);
|
||||
} catch (const std::bad_weak_ptr &) {
|
||||
// We don't mind if we miss axis updates while input hasn't been initialized
|
||||
|
@ -9,7 +9,7 @@
|
||||
namespace skyline::audio {
|
||||
AdpcmDecoder::AdpcmDecoder(const std::vector<std::array<i16, 2>> &coefficients) : coefficients(coefficients) {}
|
||||
|
||||
std::vector<i16> AdpcmDecoder::Decode(std::span<u8> adpcmData) {
|
||||
std::vector<i16> AdpcmDecoder::Decode(span<u8> adpcmData) {
|
||||
constexpr size_t BytesPerFrame{0x8};
|
||||
constexpr size_t SamplesPerFrame{0xE};
|
||||
|
||||
|
@ -37,6 +37,6 @@ namespace skyline::audio {
|
||||
* @param adpcmData A buffer containing the raw ADPCM data
|
||||
* @return A buffer containing decoded single channel I16 PCM data
|
||||
*/
|
||||
std::vector<i16> Decode(std::span<u8> adpcmData);
|
||||
std::vector<i16> Decode(span<u8> adpcmData);
|
||||
};
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ namespace skyline::audio {
|
||||
* @brief This appends data from a span to the buffer
|
||||
* @param data A span containing the data to be appended
|
||||
*/
|
||||
inline void Append(std::span<Type> data) {
|
||||
inline void Append(span<Type> data) {
|
||||
Append(data.data(), data.size());
|
||||
}
|
||||
};
|
||||
|
@ -121,7 +121,7 @@ namespace skyline::audio {
|
||||
{-42, 3751, 26253, 2811}, {-38, 3608, 26270, 2936}, {-34, 3467, 26281, 3064}, {-32, 3329, 26287, 3195}}};
|
||||
// @fmt:on
|
||||
|
||||
std::vector<i16> Resampler::ResampleBuffer(std::span<i16> inputBuffer, double ratio, u8 channelCount) {
|
||||
std::vector<i16> Resampler::ResampleBuffer(span<i16> inputBuffer, double ratio, u8 channelCount) {
|
||||
auto step{static_cast<u32>(ratio * 0x8000)};
|
||||
auto outputSize{static_cast<size_t>(inputBuffer.size() / ratio)};
|
||||
std::vector<i16> outputBuffer(outputSize);
|
||||
|
@ -21,6 +21,6 @@ namespace skyline::audio {
|
||||
* @param ratio The conversion ratio needed
|
||||
* @param channelCount The amount of channels the buffer contains
|
||||
*/
|
||||
std::vector<i16> ResampleBuffer(std::span<i16> inputBuffer, double ratio, u8 channelCount);
|
||||
std::vector<i16> ResampleBuffer(span<i16> inputBuffer, double ratio, u8 channelCount);
|
||||
};
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ namespace skyline::audio {
|
||||
return bufferIds;
|
||||
}
|
||||
|
||||
void AudioTrack::AppendBuffer(u64 tag, std::span<i16> buffer) {
|
||||
void AudioTrack::AppendBuffer(u64 tag, span<i16> buffer) {
|
||||
BufferIdentifier identifier{
|
||||
.released = false,
|
||||
.tag = tag,
|
||||
|
@ -66,7 +66,7 @@ namespace skyline::audio {
|
||||
* @param tag The tag of the buffer
|
||||
* @param buffer A span containing the source sample buffer
|
||||
*/
|
||||
void AppendBuffer(u64 tag, std::span<i16> buffer = {});
|
||||
void AppendBuffer(u64 tag, span<i16> buffer = {});
|
||||
|
||||
/**
|
||||
* @brief Checks if any buffers have been released and calls the appropriate callback for them
|
||||
|
@ -105,13 +105,7 @@ namespace skyline {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Aligns up a value to a multiple of two
|
||||
* @tparam Type The type of the values
|
||||
* @param value The value to round up
|
||||
* @param multiple The multiple to round up to (Should be a multiple of 2)
|
||||
* @tparam TypeVal The type of the value
|
||||
* @tparam TypeMul The type of the multiple
|
||||
* @return The aligned value
|
||||
* @return The value aligned up to the next multiple
|
||||
*/
|
||||
template<typename TypeVal, typename TypeMul>
|
||||
constexpr inline TypeVal AlignUp(TypeVal value, TypeMul multiple) {
|
||||
@ -120,12 +114,7 @@ namespace skyline {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Aligns down a value to a multiple of two
|
||||
* @param value The value to round down
|
||||
* @param multiple The multiple to round down to (Should be a multiple of 2)
|
||||
* @tparam TypeVal The type of the value
|
||||
* @tparam TypeMul The type of the multiple
|
||||
* @return The aligned value
|
||||
* @return The value aligned down to the previous multiple
|
||||
*/
|
||||
template<typename TypeVal, typename TypeMul>
|
||||
constexpr inline TypeVal AlignDown(TypeVal value, TypeMul multiple) {
|
||||
@ -133,10 +122,7 @@ namespace skyline {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param value The value to check for alignment
|
||||
* @param multiple The multiple to check alignment with
|
||||
* @return If the address is aligned with the multiple
|
||||
* @note The multiple must be divisible by 2
|
||||
*/
|
||||
template<typename TypeVal, typename TypeMul>
|
||||
constexpr inline bool IsAligned(TypeVal value, TypeMul multiple) {
|
||||
@ -147,7 +133,6 @@ namespace skyline {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param value The value to check for alignment
|
||||
* @return If the value is page aligned
|
||||
*/
|
||||
constexpr inline bool PageAligned(u64 value) {
|
||||
@ -155,7 +140,6 @@ namespace skyline {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param value The value to check for alignment
|
||||
* @return If the value is word aligned
|
||||
*/
|
||||
constexpr inline bool WordAligned(u64 value) {
|
||||
@ -201,25 +185,118 @@ namespace skyline {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A compile-time hash function as std::hash isn't constexpr
|
||||
*/
|
||||
constexpr std::size_t Hash(std::string_view view) {
|
||||
return frz::elsa<frz::string>{}(frz::string(view.data(), view.size()), 0);
|
||||
}
|
||||
|
||||
template<typename Out, typename In>
|
||||
constexpr Out &As(std::span<In> span) {
|
||||
if (IsAligned(span.size_bytes(), sizeof(Out)))
|
||||
return *reinterpret_cast<Out *>(span.data());
|
||||
throw exception("Span size not aligned with Out type size (0x{:X}/0x{:X})", span.size_bytes(), sizeof(Out));
|
||||
}
|
||||
|
||||
template<typename Out, typename In>
|
||||
constexpr std::span<Out> AsSpan(std::span<In> span) {
|
||||
if (IsAligned(span.size_bytes(), sizeof(Out)))
|
||||
return std::span(reinterpret_cast<Out *>(span.data()), span.size_bytes() / sizeof(Out));
|
||||
throw exception("Span size not aligned with Out type size (0x{:X}/0x{:X})", span.size_bytes(), sizeof(Out));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A custom wrapper over span that adds several useful methods to it
|
||||
* @note This class is completely transparent, it implicitly converts from and to span
|
||||
*/
|
||||
template<typename T, size_t Extent = std::dynamic_extent>
|
||||
class span : public std::span<T, Extent> {
|
||||
public:
|
||||
using std::span<T, Extent>::span;
|
||||
using std::span<T, Extent>::operator=;
|
||||
|
||||
typedef typename std::span<T, Extent>::element_type elementType;
|
||||
typedef typename std::span<T, Extent>::index_type indexType;
|
||||
|
||||
constexpr span(const std::span<T, Extent> &spn) : std::span<T, Extent>(spn) {}
|
||||
|
||||
/**
|
||||
* @brief We want to support implicitly casting from std::string_view -> span as it is just a specialization of a data view which span is a generic form of, the opposite doesn't hold true as not all data held by a span is string data therefore the conversion isn't implicit there
|
||||
*/
|
||||
template<class Traits>
|
||||
constexpr span(const std::basic_string_view<T, Traits> &string) : std::span<T, Extent>(const_cast<T *>(string.data()), string.size()) {}
|
||||
|
||||
template<typename Out>
|
||||
constexpr Out &as() {
|
||||
if (span::size_bytes() >= sizeof(Out))
|
||||
return *reinterpret_cast<Out *>(span::data());
|
||||
throw exception("Span size is less than Out type size (0x{:X}/0x{:X})", span::size_bytes(), sizeof(Out));
|
||||
}
|
||||
|
||||
constexpr std::string_view as_string(indexType length = 0) {
|
||||
return std::string_view(reinterpret_cast<char *>(span::data()), length ? length : span::size_bytes());
|
||||
}
|
||||
|
||||
template<typename Out, size_t OutExtent = std::dynamic_extent>
|
||||
constexpr span<Out> cast() {
|
||||
if (util::IsAligned(span::size_bytes(), sizeof(Out)))
|
||||
return span<Out, OutExtent>(reinterpret_cast<Out *>(span::data()), span::size_bytes() / sizeof(Out));
|
||||
throw exception("Span size not aligned with Out type size (0x{:X}/0x{:X})", span::size_bytes(), sizeof(Out));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copies data from the supplied span into this one
|
||||
* @param amount The amount of elements that need to be copied (in terms of the supplied span), 0 will try to copy the entirety of the other span
|
||||
*/
|
||||
template<typename In, size_t InExtent>
|
||||
constexpr void copy_from(const span<In, InExtent> spn, indexType amount = 0) {
|
||||
auto size{amount ? amount * sizeof(In) : spn.size_bytes()};
|
||||
if (span::size_bytes() < size)
|
||||
throw exception("Data being copied is larger than this span");
|
||||
std::memmove(span::data(), spn.data(), size);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Implicit type conversion for copy_from, this allows passing in std::vector/std::array in directly is automatically passed by reference which is important for any containers
|
||||
*/
|
||||
template<typename In>
|
||||
constexpr void copy_from(const In &in, indexType amount = 0) {
|
||||
copy_from(span<typename std::add_const<typename In::value_type>::type>(in), amount);
|
||||
}
|
||||
|
||||
/** Base Class Functions that return an instance of it, we upcast them **/
|
||||
template<size_t Count>
|
||||
constexpr span<T, Count> first() const noexcept {
|
||||
return std::span<T, Extent>::template first<Count>();
|
||||
}
|
||||
|
||||
template<size_t Count>
|
||||
constexpr span<T, Count> last() const noexcept {
|
||||
return std::span<T, Extent>::template last<Count>();
|
||||
}
|
||||
|
||||
constexpr span<elementType, std::dynamic_extent> first(indexType count) const noexcept {
|
||||
return std::span<T, Extent>::first(count);
|
||||
}
|
||||
|
||||
constexpr span<elementType, std::dynamic_extent> last(indexType count) const noexcept {
|
||||
return std::span<T, Extent>::last(count);
|
||||
}
|
||||
|
||||
template<size_t Offset, size_t Count = std::dynamic_extent>
|
||||
constexpr auto subspan() const noexcept -> span<T, Count != std::dynamic_extent ? Count : Extent - Offset> {
|
||||
return std::span<T, Extent>::template subspan<Offset, Count>();
|
||||
}
|
||||
|
||||
constexpr span<T, std::dynamic_extent> subspan(indexType offset, indexType count = std::dynamic_extent) const noexcept {
|
||||
return std::span<T, Extent>::subspan(offset, count);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Deduction guides required for arguments to span, CTAD will fail for iterators, arrays and containers without this
|
||||
*/
|
||||
template<class It, class End, size_t Extent = std::dynamic_extent>
|
||||
span(It, End) -> span<typename std::iterator_traits<It>::value_type, Extent>;
|
||||
template<class T, size_t Size>
|
||||
span(T (&)[Size]) -> span<T, Size>;
|
||||
template<class T, size_t Size>
|
||||
span(std::array<T, Size> &) -> span<T, Size>;
|
||||
template<class T, size_t Size>
|
||||
span(const std::array<T, Size> &) -> span<const T, Size>;
|
||||
template<class Container>
|
||||
span(Container &) -> span<typename Container::value_type>;
|
||||
template<class Container>
|
||||
span(const Container &) -> span<const typename Container::value_type>;
|
||||
|
||||
/**
|
||||
* @brief The Mutex class is a wrapper around an atomic bool used for synchronization
|
||||
*/
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include "aes_cipher.h"
|
||||
|
||||
namespace skyline::crypto {
|
||||
AesCipher::AesCipher(std::span<u8> key, mbedtls_cipher_type_t type) {
|
||||
AesCipher::AesCipher(span<u8> key, mbedtls_cipher_type_t type) {
|
||||
mbedtls_cipher_init(&decryptContext);
|
||||
if (mbedtls_cipher_setup(&decryptContext, mbedtls_cipher_info_from_type(type)) != 0)
|
||||
throw exception("Failed to setup decryption context");
|
||||
|
@ -37,7 +37,7 @@ namespace skyline::crypto {
|
||||
}
|
||||
|
||||
public:
|
||||
AesCipher(std::span<u8> key, mbedtls_cipher_type_t type);
|
||||
AesCipher(span<u8> key, mbedtls_cipher_type_t type);
|
||||
|
||||
~AesCipher();
|
||||
|
||||
@ -54,7 +54,7 @@ namespace skyline::crypto {
|
||||
/**
|
||||
* @brief Decrypts data and writes back to it
|
||||
*/
|
||||
inline void Decrypt(std::span<u8> data) {
|
||||
inline void Decrypt(span<u8> data) {
|
||||
Decrypt(data.data(), data.data(), data.size());
|
||||
}
|
||||
|
||||
@ -66,7 +66,7 @@ namespace skyline::crypto {
|
||||
/**
|
||||
* @brief Decrypts data with XTS and writes back to it
|
||||
*/
|
||||
inline void XtsDecrypt(std::span<u8> data, size_t sector, size_t sectorSize) {
|
||||
inline void XtsDecrypt(span<u8> data, size_t sector, size_t sectorSize) {
|
||||
XtsDecrypt(data.data(), data.data(), data.size(), sector, sectorSize);
|
||||
}
|
||||
};
|
||||
|
@ -89,7 +89,7 @@ namespace skyline::gpu::gpfifo {
|
||||
}
|
||||
}
|
||||
|
||||
void GPFIFO::Push(std::span<GpEntry> entries) {
|
||||
void GPFIFO::Push(span<GpEntry> entries) {
|
||||
std::lock_guard lock(pushBufferQueueLock);
|
||||
bool beforeBarrier{false};
|
||||
|
||||
|
@ -173,7 +173,7 @@ namespace skyline::gpu {
|
||||
/**
|
||||
* @brief Pushes a list of entries to the FIFO, these commands will be executed on calls to 'Step'
|
||||
*/
|
||||
void Push(std::span<GpEntry> entries);
|
||||
void Push(span<GpEntry> entries);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ namespace skyline {
|
||||
* @tparam T The type of span to read into
|
||||
*/
|
||||
template<typename T>
|
||||
void Read(std::span<T> destination, u64 address) const {
|
||||
void Read(span<T> destination, u64 address) const {
|
||||
Read(reinterpret_cast<u8 *>(destination.data()), address, destination.size_bytes());
|
||||
}
|
||||
|
||||
@ -132,7 +132,7 @@ namespace skyline {
|
||||
* @brief Writes out a span to a region of the GPU virtual address space
|
||||
*/
|
||||
template<typename T>
|
||||
void Write(std::span<T> source, u64 address) const {
|
||||
void Write(span<T> source, u64 address) const {
|
||||
Write(reinterpret_cast<u8 *>(source.data()), address, source.size_bytes());
|
||||
}
|
||||
|
||||
|
@ -412,7 +412,7 @@ namespace skyline::input {
|
||||
amplitudes[i] = std::min(totalAmplitude, constant::AmplitudeMax);
|
||||
}
|
||||
|
||||
jvm->VibrateDevice(index, std::span(timings.begin(), timings.begin() + i), std::span(amplitudes.begin(), amplitudes.begin() + i));
|
||||
jvm->VibrateDevice(index, span(timings.begin(), timings.begin() + i), span(amplitudes.begin(), amplitudes.begin() + i));
|
||||
}
|
||||
|
||||
void VibrateDevice(const std::shared_ptr<JvmManager> &jvm, i8 index, const NpadVibrationValue &value) {
|
||||
|
@ -14,7 +14,7 @@ namespace skyline::input {
|
||||
SetState({});
|
||||
}
|
||||
|
||||
void TouchManager::SetState(const std::span<TouchScreenPoint> &points) {
|
||||
void TouchManager::SetState(const span<TouchScreenPoint> &points) {
|
||||
if (!activated)
|
||||
return;
|
||||
|
||||
|
@ -37,6 +37,6 @@ namespace skyline::input {
|
||||
|
||||
void Activate();
|
||||
|
||||
void SetState(const std::span<TouchScreenPoint> &points);
|
||||
void SetState(const span<TouchScreenPoint> &points);
|
||||
};
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ namespace skyline {
|
||||
env->CallVoidMethod(instance, initializeControllersId);
|
||||
}
|
||||
|
||||
void JvmManager::VibrateDevice(jint index, const std::span<jlong> &timings, const std::span<jint> &litudes) {
|
||||
void JvmManager::VibrateDevice(jint index, const span<jlong> &timings, const span<jint> &litudes) {
|
||||
auto jTimings = env->NewLongArray(timings.size());
|
||||
env->SetLongArrayRegion(jTimings, 0, timings.size(), timings.data());
|
||||
auto jAmplitudes = env->NewIntArray(amplitudes.size());
|
||||
|
@ -97,7 +97,7 @@ namespace skyline {
|
||||
/**
|
||||
* @brief A call to EmulationActivity.vibrateDevice in Kotlin
|
||||
*/
|
||||
void VibrateDevice(jint index, const std::span<jlong> &timings, const std::span<jint> &litudes);
|
||||
void VibrateDevice(jint index, const span<jlong> &timings, const span<jint> &litudes);
|
||||
|
||||
/**
|
||||
* @brief A call to EmulationActivity.clearVibrationDevice in Kotlin
|
||||
|
@ -5,16 +5,6 @@
|
||||
#include "types/KProcess.h"
|
||||
|
||||
namespace skyline::kernel::ipc {
|
||||
IpcBuffer::IpcBuffer(u64 address, size_t size, IpcBufferType type) : address(address), size(size), type(type) {}
|
||||
|
||||
InputBuffer::InputBuffer(kernel::ipc::BufferDescriptorX *xBuf) : IpcBuffer(xBuf->Address(), xBuf->size, IpcBufferType::X) {}
|
||||
|
||||
InputBuffer::InputBuffer(kernel::ipc::BufferDescriptorABW *aBuf, IpcBufferType type) : IpcBuffer(aBuf->Address(), aBuf->Size(), type) {}
|
||||
|
||||
OutputBuffer::OutputBuffer(kernel::ipc::BufferDescriptorABW *bBuf, IpcBufferType type) : IpcBuffer(bBuf->Address(), bBuf->Size(), type) {}
|
||||
|
||||
OutputBuffer::OutputBuffer(kernel::ipc::BufferDescriptorC *cBuf) : IpcBuffer(cBuf->address, cBuf->size, IpcBufferType::C) {}
|
||||
|
||||
IpcRequest::IpcRequest(bool isDomain, const DeviceState &state) : isDomain(isDomain) {
|
||||
u8 *tls = state.process->GetPointer<u8>(state.thread->tls);
|
||||
u8 *pointer = tls;
|
||||
@ -40,7 +30,7 @@ namespace skyline::kernel::ipc {
|
||||
for (u8 index = 0; header->xNo > index; index++) {
|
||||
auto bufX = reinterpret_cast<BufferDescriptorX *>(pointer);
|
||||
if (bufX->Address()) {
|
||||
inputBuf.emplace_back(bufX);
|
||||
inputBuf.emplace_back(state.process->GetPointer<u8>(bufX->Address()), u16(bufX->size));
|
||||
state.logger->Debug("Buf X #{} AD: 0x{:X} SZ: 0x{:X} CTR: {}", index, u64(bufX->Address()), u16(bufX->size), u16(bufX->Counter()));
|
||||
}
|
||||
pointer += sizeof(BufferDescriptorX);
|
||||
@ -49,7 +39,7 @@ namespace skyline::kernel::ipc {
|
||||
for (u8 index = 0; header->aNo > index; index++) {
|
||||
auto bufA = reinterpret_cast<BufferDescriptorABW *>(pointer);
|
||||
if (bufA->Address()) {
|
||||
inputBuf.emplace_back(bufA);
|
||||
inputBuf.emplace_back(state.process->GetPointer<u8>(bufA->Address()), bufA->Size());
|
||||
state.logger->Debug("Buf A #{} AD: 0x{:X} SZ: 0x{:X}", index, u64(bufA->Address()), u64(bufA->Size()));
|
||||
}
|
||||
pointer += sizeof(BufferDescriptorABW);
|
||||
@ -58,7 +48,7 @@ namespace skyline::kernel::ipc {
|
||||
for (u8 index = 0; header->bNo > index; index++) {
|
||||
auto bufB = reinterpret_cast<BufferDescriptorABW *>(pointer);
|
||||
if (bufB->Address()) {
|
||||
outputBuf.emplace_back(bufB);
|
||||
outputBuf.emplace_back(state.process->GetPointer<u8>(bufB->Address()), bufB->Size());
|
||||
state.logger->Debug("Buf B #{} AD: 0x{:X} SZ: 0x{:X}", index, u64(bufB->Address()), u64(bufB->Size()));
|
||||
}
|
||||
pointer += sizeof(BufferDescriptorABW);
|
||||
@ -67,8 +57,8 @@ namespace skyline::kernel::ipc {
|
||||
for (u8 index = 0; header->wNo > index; index++) {
|
||||
auto bufW = reinterpret_cast<BufferDescriptorABW *>(pointer);
|
||||
if (bufW->Address()) {
|
||||
inputBuf.emplace_back(bufW, IpcBufferType::W);
|
||||
outputBuf.emplace_back(bufW, IpcBufferType::W);
|
||||
outputBuf.emplace_back(state.process->GetPointer<u8>(bufW->Address()), bufW->Size());
|
||||
outputBuf.emplace_back(state.process->GetPointer<u8>(bufW->Address()), bufW->Size());
|
||||
state.logger->Debug("Buf W #{} AD: 0x{:X} SZ: 0x{:X}", index, u64(bufW->Address()), u16(bufW->Size()));
|
||||
}
|
||||
pointer += sizeof(BufferDescriptorABW);
|
||||
@ -112,14 +102,14 @@ namespace skyline::kernel::ipc {
|
||||
if (header->cFlag == BufferCFlag::SingleDescriptor) {
|
||||
auto bufC = reinterpret_cast<BufferDescriptorC *>(pointer);
|
||||
if (bufC->address) {
|
||||
outputBuf.emplace_back(bufC);
|
||||
outputBuf.emplace_back(state.process->GetPointer<u8>(bufC->address), u16(bufC->size));
|
||||
state.logger->Debug("Buf C: AD: 0x{:X} SZ: 0x{:X}", u64(bufC->address), u16(bufC->size));
|
||||
}
|
||||
} else if (header->cFlag > BufferCFlag::SingleDescriptor) {
|
||||
for (u8 index = 0; (static_cast<u8>(header->cFlag) - 2) > index; index++) { // (cFlag - 2) C descriptors are present
|
||||
auto bufC = reinterpret_cast<BufferDescriptorC *>(pointer);
|
||||
if (bufC->address) {
|
||||
outputBuf.emplace_back(bufC);
|
||||
outputBuf.emplace_back(state.process->GetPointer<u8>(bufC->address), u16(bufC->size));
|
||||
state.logger->Debug("Buf C #{} AD: 0x{:X} SZ: 0x{:X}", index, u64(bufC->address), u16(bufC->size));
|
||||
}
|
||||
pointer += sizeof(BufferDescriptorC);
|
||||
|
@ -196,52 +196,6 @@ namespace skyline {
|
||||
C //!< This is a type-C buffer
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Describes a buffer by holding the address and size
|
||||
*/
|
||||
struct IpcBuffer {
|
||||
u64 address; //!< The address of the buffer
|
||||
size_t size; //!< The size of the buffer
|
||||
IpcBufferType type; //!< The type of the buffer
|
||||
|
||||
/**
|
||||
* @param address The address of the buffer
|
||||
* @param size The size of the buffer
|
||||
* @param type The type of the buffer
|
||||
*/
|
||||
IpcBuffer(u64 address, size_t size, IpcBufferType type);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This holds an input IPC buffer
|
||||
*/
|
||||
struct InputBuffer : public IpcBuffer {
|
||||
/**
|
||||
* @param aBuf The X Buffer Descriptor that has contains the input data
|
||||
*/
|
||||
InputBuffer(kernel::ipc::BufferDescriptorX *xBuf);
|
||||
|
||||
/**
|
||||
* @param aBuf The A or W Buffer Descriptor that has contains the input data
|
||||
*/
|
||||
InputBuffer(kernel::ipc::BufferDescriptorABW *aBuf, IpcBufferType type = IpcBufferType::A);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This holds an output IPC buffer
|
||||
*/
|
||||
struct OutputBuffer : public IpcBuffer {
|
||||
/**
|
||||
* @param bBuf The B or W Buffer Descriptor that has to be outputted to
|
||||
*/
|
||||
OutputBuffer(kernel::ipc::BufferDescriptorABW *bBuf, IpcBufferType type = IpcBufferType::B);
|
||||
|
||||
/**
|
||||
* @param cBuf The C Buffer Descriptor that has to be outputted to
|
||||
*/
|
||||
OutputBuffer(kernel::ipc::BufferDescriptorC *cBuf);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This class encapsulates an IPC Request (https://switchbrew.org/wiki/IPC_Marshalling)
|
||||
*/
|
||||
@ -260,8 +214,8 @@ namespace skyline {
|
||||
std::vector<KHandle> copyHandles; //!< A vector of handles that should be copied from the server to the client process (The difference is just to match application expectations, there is no real difference b/w copying and moving handles)
|
||||
std::vector<KHandle> moveHandles; //!< A vector of handles that should be moved from the server to the client process rather than copied
|
||||
std::vector<KHandle> domainObjects; //!< A vector of all input domain objects
|
||||
std::vector<InputBuffer> inputBuf; //!< This is a vector of input buffers
|
||||
std::vector<OutputBuffer> outputBuf; //!< This is a vector of output buffers
|
||||
std::vector<span<u8>> inputBuf; //!< This is a vector of input buffers
|
||||
std::vector<span<u8>> outputBuf; //!< This is a vector of output buffers
|
||||
|
||||
/**
|
||||
* @param isDomain If the following request is a domain request
|
||||
|
@ -24,7 +24,7 @@ namespace skyline::service::account {
|
||||
try {
|
||||
// We only support one active user currently so hardcode this and ListOpenUsers
|
||||
return WriteUserList(request.outputBuf.at(0), {constant::DefaultUserId});
|
||||
} catch (const std::out_of_range &e) {
|
||||
} catch (const std::out_of_range &) {
|
||||
return result::InvalidInputBuffer;
|
||||
}
|
||||
}
|
||||
@ -32,14 +32,13 @@ namespace skyline::service::account {
|
||||
Result IAccountServiceForApplication::ListOpenUsers(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
try {
|
||||
return WriteUserList(request.outputBuf.at(0), {constant::DefaultUserId});
|
||||
} catch (const std::out_of_range &e) {
|
||||
} catch (const std::out_of_range &) {
|
||||
return result::InvalidInputBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
Result IAccountServiceForApplication::WriteUserList(ipc::OutputBuffer buffer, std::vector<UserId> userIds) {
|
||||
std::span outputUserIds(state.process->GetPointer<UserId>(buffer.address), buffer.size / sizeof(UserId));
|
||||
|
||||
Result IAccountServiceForApplication::WriteUserList(span<u8> buffer, std::vector<UserId> userIds) {
|
||||
span outputUserIds{buffer.cast<UserId>()};
|
||||
for (auto &userId : outputUserIds) {
|
||||
if (userIds.empty()) {
|
||||
userId = UserId{};
|
||||
|
@ -39,7 +39,7 @@ namespace skyline {
|
||||
/**
|
||||
* @brief Writes a vector of 128-bit user IDs to an output buffer
|
||||
*/
|
||||
Result WriteUserList(ipc::OutputBuffer buffer, std::vector<UserId> userIds);
|
||||
Result WriteUserList(span<u8> buffer, std::vector<UserId> userIds);
|
||||
|
||||
public:
|
||||
IAccountServiceForApplication(const DeviceState &state, ServiceManager &manager);
|
||||
|
@ -17,8 +17,7 @@ namespace skyline::service::account {
|
||||
u8 _unk2_[0x60];
|
||||
};
|
||||
|
||||
auto userData = state.process->GetPointer<AccountUserData>(request.outputBuf.at(0).address);
|
||||
userData->iconBackgroundColorID = 0x1; // Color indexing starts at 0x1
|
||||
request.outputBuf.at(0).as<AccountUserData>().iconBackgroundColorID = 0x1; // Color indexing starts at 0x1
|
||||
|
||||
return GetBase(session, request, response);
|
||||
}
|
||||
|
@ -15,26 +15,26 @@ namespace skyline::service::am {
|
||||
|
||||
Result IStorageAccessor::Write(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
auto offset = request.Pop<i64>();
|
||||
auto size = std::min(static_cast<i64>(request.inputBuf.at(0).size), static_cast<i64>(parent->content.size()) - offset);
|
||||
auto size = std::min(static_cast<i64>(request.inputBuf.at(0).size()), static_cast<i64>(parent->content.size()) - offset);
|
||||
|
||||
if (offset > parent->content.size())
|
||||
return result::OutOfBounds;
|
||||
|
||||
if (size > 0)
|
||||
state.process->ReadMemory(parent->content.data() + offset, request.inputBuf.at(0).address, size);
|
||||
if (size)
|
||||
request.outputBuf.at(0).copy_from(span(parent->content.data() + offset, size));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
Result IStorageAccessor::Read(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
auto offset = request.Pop<i64>();
|
||||
auto size = std::min(static_cast<i64>(request.inputBuf.at(0).size), static_cast<i64>(parent->content.size()) - offset);
|
||||
auto size = std::min(static_cast<i64>(request.inputBuf.at(0).size()), static_cast<i64>(parent->content.size()) - offset);
|
||||
|
||||
if (offset > parent->content.size())
|
||||
return result::OutOfBounds;
|
||||
|
||||
if (size > 0)
|
||||
state.process->WriteMemory(parent->content.data() + offset, request.outputBuf.at(0).address, size);
|
||||
request.outputBuf.at(0).copy_from(span(parent->content.data() + offset, size));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
@ -9,13 +9,12 @@ namespace skyline::service::audio {
|
||||
IAudioDevice::IAudioDevice(const DeviceState &state, ServiceManager &manager) : systemEvent(std::make_shared<type::KEvent>(state)), BaseService(state, manager) {}
|
||||
|
||||
Result IAudioDevice::ListAudioDeviceName(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
u64 offset{};
|
||||
for (std::string deviceName : {"AudioTvOutput", "AudioStereoJackOutput", "AudioBuiltInSpeakerOutput"}) {
|
||||
if (offset + deviceName.size() + 1 > request.outputBuf.at(0).size)
|
||||
throw exception("Too small a buffer supplied to ListAudioDeviceName");
|
||||
|
||||
state.process->WriteMemory(deviceName.c_str(), request.outputBuf.at(0).address + offset, deviceName.size() + 1);
|
||||
offset += deviceName.size() + 1;
|
||||
span buffer{request.outputBuf.at(0)};
|
||||
for (std::string_view deviceName : {"AudioTvOutput\0", "AudioStereoJackOutput\0", "AudioBuiltInSpeakerOutput\0"}) {
|
||||
if (deviceName.size() > buffer.size())
|
||||
throw exception("The buffer supplied to ListAudioDeviceName is too small");
|
||||
buffer.copy_from(deviceName);
|
||||
buffer = buffer.subspan(deviceName.size());
|
||||
}
|
||||
return {};
|
||||
}
|
||||
@ -25,12 +24,10 @@ namespace skyline::service::audio {
|
||||
}
|
||||
|
||||
Result IAudioDevice::GetActiveAudioDeviceName(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
std::string deviceName("AudioStereoJackOutput");
|
||||
|
||||
if (deviceName.size() > request.outputBuf.at(0).size)
|
||||
throw exception("Too small a buffer supplied to GetActiveAudioDeviceName");
|
||||
|
||||
state.process->WriteMemory(deviceName.c_str(), request.outputBuf.at(0).address, deviceName.size() + 1);
|
||||
std::string_view deviceName{"AudioStereoJackOutput\0"};
|
||||
if (deviceName.size() > request.outputBuf.at(0).size())
|
||||
throw exception("The buffer supplied to GetActiveAudioDeviceName is too small");
|
||||
request.outputBuf.at(0).copy_from(deviceName);
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -37,16 +37,16 @@ namespace skyline::service::audio {
|
||||
u64 sampleCapacity;
|
||||
u64 sampleSize;
|
||||
u64 sampleOffset;
|
||||
} &data{state.process->GetReference<Data>(request.inputBuf.at(0).address)};
|
||||
} &data{request.inputBuf.at(0).as<Data>()};
|
||||
auto tag = request.Pop<u64>();
|
||||
|
||||
state.logger->Debug("IAudioOut: Appending buffer with address: 0x{:X}, size: 0x{:X}", data.sampleBufferPtr, data.sampleSize);
|
||||
|
||||
if (sampleRate != constant::SampleRate) {
|
||||
auto resampledBuffer = resampler.ResampleBuffer(std::span(state.process->GetPointer<i16>(data.sampleBufferPtr), data.sampleSize / sizeof(i16)), static_cast<double>(sampleRate) / constant::SampleRate, channelCount);
|
||||
auto resampledBuffer = resampler.ResampleBuffer(span(state.process->GetPointer<i16>(data.sampleBufferPtr), data.sampleSize / sizeof(i16)), static_cast<double>(sampleRate) / constant::SampleRate, channelCount);
|
||||
track->AppendBuffer(tag, resampledBuffer);
|
||||
} else {
|
||||
track->AppendBuffer(tag, std::span(state.process->GetPointer<i16>(data.sampleBufferPtr), data.sampleSize / sizeof(i16)));
|
||||
track->AppendBuffer(tag, span(state.process->GetPointer<i16>(data.sampleBufferPtr), data.sampleSize / sizeof(i16)));
|
||||
}
|
||||
|
||||
return {};
|
||||
@ -60,13 +60,13 @@ namespace skyline::service::audio {
|
||||
}
|
||||
|
||||
Result IAudioOut::GetReleasedAudioOutBuffer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
auto maxCount{static_cast<u32>(request.outputBuf.at(0).size >> 3)};
|
||||
auto maxCount{static_cast<u32>(request.outputBuf.at(0).size() >> 3)};
|
||||
std::vector<u64> releasedBuffers{track->GetReleasedBuffers(maxCount)};
|
||||
auto count{static_cast<u32>(releasedBuffers.size())};
|
||||
|
||||
// Fill rest of output buffer with zeros
|
||||
releasedBuffers.resize(maxCount, 0);
|
||||
state.process->WriteMemory(releasedBuffers.data(), request.outputBuf.at(0).address, request.outputBuf.at(0).size);
|
||||
request.outputBuf.at(0).copy_from(releasedBuffers);
|
||||
|
||||
response.Push<u32>(count);
|
||||
return {};
|
||||
|
@ -9,7 +9,7 @@ namespace skyline::service::audio {
|
||||
IAudioOutManager::IAudioOutManager(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager) {}
|
||||
|
||||
Result IAudioOutManager::ListAudioOuts(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
state.process->WriteMemory(reinterpret_cast<void *>(const_cast<char *>(constant::DefaultAudioOutName.data())), request.outputBuf.at(0).address, constant::DefaultAudioOutName.size());
|
||||
request.outputBuf.at(0).copy_from(constant::DefaultAudioOutName);
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -45,32 +45,26 @@ namespace skyline::service::audio::IAudioRenderer {
|
||||
}
|
||||
|
||||
Result IAudioRenderer::RequestUpdate(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
auto inputAddress{request.inputBuf.at(0).address};
|
||||
auto input{request.inputBuf.at(0).data()};
|
||||
|
||||
auto inputHeader{state.process->GetObject<UpdateDataHeader>(inputAddress)};
|
||||
auto inputHeader{*reinterpret_cast<UpdateDataHeader *>(input)};
|
||||
revisionInfo.SetUserRevision(inputHeader.revision);
|
||||
inputAddress += sizeof(UpdateDataHeader);
|
||||
inputAddress += inputHeader.behaviorSize; // Unused
|
||||
input += sizeof(UpdateDataHeader);
|
||||
input += inputHeader.behaviorSize; // Unused
|
||||
|
||||
auto memoryPoolCount{memoryPools.size()};
|
||||
std::vector<MemoryPoolIn> memoryPoolsIn(memoryPoolCount);
|
||||
state.process->ReadMemory(memoryPoolsIn.data(), inputAddress, memoryPoolCount * sizeof(MemoryPoolIn));
|
||||
inputAddress += inputHeader.memoryPoolSize;
|
||||
|
||||
for (auto i = 0; i < memoryPoolsIn.size(); i++)
|
||||
span memoryPoolsIn(reinterpret_cast<MemoryPoolIn*>(input), memoryPools.size());
|
||||
input += inputHeader.memoryPoolSize;
|
||||
for (auto i = 0; i < memoryPools.size(); i++)
|
||||
memoryPools[i].ProcessInput(memoryPoolsIn[i]);
|
||||
|
||||
inputAddress += inputHeader.voiceResourceSize;
|
||||
std::vector<VoiceIn> voicesIn(parameters.voiceCount);
|
||||
state.process->ReadMemory(voicesIn.data(), inputAddress, parameters.voiceCount * sizeof(VoiceIn));
|
||||
inputAddress += inputHeader.voiceSize;
|
||||
input += inputHeader.voiceResourceSize;
|
||||
|
||||
span voicesIn(reinterpret_cast<VoiceIn*>(input), parameters.voiceCount);
|
||||
input += inputHeader.voiceSize;
|
||||
for (auto i = 0; i < voicesIn.size(); i++)
|
||||
voices[i].ProcessInput(voicesIn[i]);
|
||||
|
||||
std::vector<EffectIn> effectsIn(parameters.effectCount);
|
||||
state.process->ReadMemory(effectsIn.data(), inputAddress, parameters.effectCount * sizeof(EffectIn));
|
||||
|
||||
span effectsIn(reinterpret_cast<EffectIn*>(input), parameters.effectCount);
|
||||
for (auto i = 0; i < effectsIn.size(); i++)
|
||||
effects[i].ProcessInput(effectsIn[i]);
|
||||
|
||||
@ -100,24 +94,24 @@ namespace skyline::service::audio::IAudioRenderer {
|
||||
outputHeader.performanceManagerSize +
|
||||
outputHeader.elapsedFrameCountInfoSize;
|
||||
|
||||
u64 outputAddress = request.outputBuf.at(0).address;
|
||||
auto output{request.outputBuf.at(0).data()};
|
||||
|
||||
state.process->WriteMemory(outputHeader, outputAddress);
|
||||
outputAddress += sizeof(UpdateDataHeader);
|
||||
*reinterpret_cast<UpdateDataHeader*>(output) = outputHeader;
|
||||
output += sizeof(UpdateDataHeader);
|
||||
|
||||
for (const auto &memoryPool : memoryPools) {
|
||||
state.process->WriteMemory(memoryPool.output, outputAddress);
|
||||
outputAddress += sizeof(MemoryPoolOut);
|
||||
*reinterpret_cast<MemoryPoolOut*>(output) = memoryPool.output;
|
||||
output += sizeof(MemoryPoolOut);
|
||||
}
|
||||
|
||||
for (const auto &voice : voices) {
|
||||
state.process->WriteMemory(voice.output, outputAddress);
|
||||
outputAddress += sizeof(VoiceOut);
|
||||
*reinterpret_cast<VoiceOut*>(output) = voice.output;
|
||||
output += sizeof(VoiceOut);
|
||||
}
|
||||
|
||||
for (const auto &effect : effects) {
|
||||
state.process->WriteMemory(effect.output, outputAddress);
|
||||
outputAddress += sizeof(EffectOut);
|
||||
*reinterpret_cast<EffectOut*>(output) = effect.output;
|
||||
output += sizeof(EffectOut);
|
||||
}
|
||||
|
||||
return {};
|
||||
|
@ -68,7 +68,7 @@ namespace skyline::service::audio::IAudioRenderer {
|
||||
state.process->ReadMemory(samples.data(), currentBuffer.address, currentBuffer.size);
|
||||
break;
|
||||
case skyline::audio::AudioFormat::ADPCM: {
|
||||
samples = adpcmDecoder->Decode(std::span(state.process->GetPointer<u8>(currentBuffer.address), currentBuffer.size));
|
||||
samples = adpcmDecoder->Decode(span(state.process->GetPointer<u8>(currentBuffer.address), currentBuffer.size));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -6,30 +6,24 @@
|
||||
#include "parcel.h"
|
||||
|
||||
namespace skyline::service {
|
||||
Parcel::Parcel(kernel::ipc::InputBuffer &buffer, const DeviceState &state, bool hasToken) : Parcel(buffer.address, buffer.size, state, hasToken) {}
|
||||
Parcel::Parcel(span<u8> buffer, const DeviceState &state, bool hasToken) : state(state) {
|
||||
header = buffer.as<ParcelHeader>();
|
||||
|
||||
Parcel::Parcel(u64 address, u64 size, const DeviceState &state, bool hasToken) : state(state) {
|
||||
state.process->ReadMemory(&header, address, sizeof(ParcelHeader));
|
||||
|
||||
if (size < (sizeof(ParcelHeader) + header.dataSize + header.objectsSize))
|
||||
if (buffer.size() < (sizeof(ParcelHeader) + header.dataSize + header.objectsSize))
|
||||
throw exception("The size of the parcel according to the header exceeds the specified size");
|
||||
|
||||
constexpr auto tokenLength = 0x50; // The length of the token on BufferQueue parcels
|
||||
|
||||
data.resize(header.dataSize - (hasToken ? tokenLength : 0));
|
||||
state.process->ReadMemory(data.data(), address + header.dataOffset + (hasToken ? tokenLength : 0), header.dataSize - (hasToken ? tokenLength : 0));
|
||||
memcpy(data.data(), buffer.data() + header.dataOffset + (hasToken ? tokenLength : 0), header.dataSize - (hasToken ? tokenLength : 0));
|
||||
|
||||
objects.resize(header.objectsSize);
|
||||
state.process->ReadMemory(objects.data(), address + header.objectsOffset, header.objectsSize);
|
||||
memcpy(objects.data(), buffer.data() + header.objectsOffset, header.objectsSize);
|
||||
}
|
||||
|
||||
Parcel::Parcel(const DeviceState &state) : state(state) {}
|
||||
|
||||
u64 Parcel::WriteParcel(kernel::ipc::OutputBuffer &buffer) {
|
||||
return WriteParcel(buffer.address, buffer.size);
|
||||
}
|
||||
|
||||
u64 Parcel::WriteParcel(u64 address, u64 maxSize) {
|
||||
u64 Parcel::WriteParcel(span<u8> buffer) {
|
||||
header.dataSize = static_cast<u32>(data.size());
|
||||
header.dataOffset = sizeof(ParcelHeader);
|
||||
|
||||
@ -38,12 +32,12 @@ namespace skyline::service {
|
||||
|
||||
auto totalSize = sizeof(ParcelHeader) + header.dataSize + header.objectsSize;
|
||||
|
||||
if (maxSize < totalSize)
|
||||
if (buffer.size() < totalSize)
|
||||
throw exception("The size of the parcel exceeds maxSize");
|
||||
|
||||
state.process->WriteMemory(header, address);
|
||||
state.process->WriteMemory(data.data(), address + header.dataOffset, data.size());
|
||||
state.process->WriteMemory(objects.data(), address + header.objectsOffset, objects.size());
|
||||
buffer.as<ParcelHeader>() = header;
|
||||
memcpy(buffer.data() + header.dataOffset, data.data(), data.size());
|
||||
memcpy(buffer.data() + header.objectsOffset, objects.data(), objects.size());
|
||||
|
||||
return totalSize;
|
||||
}
|
||||
|
@ -36,16 +36,7 @@ namespace skyline::service {
|
||||
* @param state The state of the device
|
||||
* @param hasToken If the parcel starts with a token, it is skipped if this flag is true
|
||||
*/
|
||||
Parcel(kernel::ipc::InputBuffer &buffer, const DeviceState &state, bool hasToken = false);
|
||||
|
||||
/**
|
||||
* @brief This constructor fills in the Parcel object with data from a Parcel on a remote process
|
||||
* @param address The remote address of the parcel
|
||||
* @param size The size of the parcel
|
||||
* @param state The state of the device
|
||||
* @param hasToken If the parcel starts with a token, it is skipped if this flag is true
|
||||
*/
|
||||
Parcel(u64 address, u64 size, const DeviceState &state, bool hasToken = false);
|
||||
Parcel(span<u8> buffer, const DeviceState &state, bool hasToken = false);
|
||||
|
||||
/**
|
||||
* @brief This constructor is used to create an empty parcel then write to a process
|
||||
@ -94,18 +85,10 @@ namespace skyline::service {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes the Parcel object into a particular output buffer on a process
|
||||
* @param buffer The buffer to write into
|
||||
* @brief Writes the Parcel object out
|
||||
* @param buffer The buffer to write the Parcel object to
|
||||
* @return The total size of the message
|
||||
*/
|
||||
u64 WriteParcel(kernel::ipc::OutputBuffer &buffer);
|
||||
|
||||
/**
|
||||
* @brief Writes the Parcel object into the process's memory
|
||||
* @param address The address to write the Parcel object to
|
||||
* @param maxSize The maximum size of the Parcel
|
||||
* @return The total size of the message
|
||||
*/
|
||||
u64 WriteParcel(u64 address, u64 maxSize);
|
||||
u64 WriteParcel(span<u8> buffer);
|
||||
};
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ namespace skyline::service::fssrv {
|
||||
return result::InvalidSize;
|
||||
}
|
||||
|
||||
response.Push<u32>(static_cast<u32>(backing->Read(state.process->GetPointer<u8>(request.outputBuf.at(0).address), offset, size)));
|
||||
response.Push<u32>(static_cast<u32>(backing->Read(request.outputBuf.at(0).data(), offset, size)));
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -44,12 +44,12 @@ namespace skyline::service::fssrv {
|
||||
return result::InvalidSize;
|
||||
}
|
||||
|
||||
if (request.inputBuf.at(0).size < size) {
|
||||
if (request.inputBuf.at(0).size() < size) {
|
||||
state.logger->Warn("The input buffer is not large enough to fit the requested size");
|
||||
return result::InvalidSize;
|
||||
}
|
||||
|
||||
if (backing->Write(state.process->GetPointer<u8>(request.inputBuf.at(0).address), offset, request.inputBuf.at(0).size) != size) {
|
||||
if (backing->Write(request.inputBuf.at(0).data(), offset, request.inputBuf.at(0).size()) != size) {
|
||||
state.logger->Warn("Failed to write all data to the backing");
|
||||
return result::UnexpectedFailure;
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ namespace skyline::service::fssrv {
|
||||
IFileSystem::IFileSystem(std::shared_ptr<vfs::FileSystem> backing, const DeviceState &state, ServiceManager &manager) : backing(backing), BaseService(state, manager) {}
|
||||
|
||||
Result IFileSystem::CreateFile(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
std::string path = std::string(state.process->GetPointer<char>(request.inputBuf.at(0).address));
|
||||
std::string path{request.inputBuf.at(0).as<char>()};
|
||||
auto mode = request.Pop<u64>();
|
||||
auto size = request.Pop<u32>();
|
||||
|
||||
@ -19,7 +19,7 @@ namespace skyline::service::fssrv {
|
||||
}
|
||||
|
||||
Result IFileSystem::GetEntryType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
std::string path = std::string(state.process->GetPointer<char>(request.inputBuf.at(0).address));
|
||||
std::string path{request.inputBuf.at(0).as<char>()};
|
||||
|
||||
auto type = backing->GetEntryType(path);
|
||||
|
||||
@ -33,7 +33,7 @@ namespace skyline::service::fssrv {
|
||||
}
|
||||
|
||||
Result IFileSystem::OpenFile(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
std::string path(state.process->GetPointer<char>(request.inputBuf.at(0).address));
|
||||
std::string path{request.inputBuf.at(0).as<char>()};
|
||||
auto mode = request.Pop<vfs::Backing::Mode>();
|
||||
|
||||
if (!backing->FileExists(path))
|
||||
|
@ -22,7 +22,7 @@ namespace skyline::service::fssrv {
|
||||
return result::InvalidSize;
|
||||
}
|
||||
|
||||
backing->Read(state.process->GetPointer<u8>(request.outputBuf.at(0).address), offset, size);
|
||||
backing->Read(request.outputBuf.at(0).data(), offset, size);
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -41,18 +41,9 @@ namespace skyline::service::hid {
|
||||
}
|
||||
|
||||
Result IHidServer::SetSupportedNpadIdType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
const auto &buffer = request.inputBuf.at(0);
|
||||
u64 address = buffer.address;
|
||||
size_t size = buffer.size / sizeof(NpadId);
|
||||
|
||||
std::vector<NpadId> supportedIds(size);
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
supportedIds[i] = state.process->GetObject<NpadId>(address);
|
||||
address += sizeof(NpadId);
|
||||
}
|
||||
|
||||
auto supportedIds{request.inputBuf.at(0).cast<NpadId>()};
|
||||
std::lock_guard lock(state.input->npad.mutex);
|
||||
state.input->npad.supportedIds = supportedIds;
|
||||
state.input->npad.supportedIds.assign(supportedIds.begin(), supportedIds.end());
|
||||
state.input->npad.Update();
|
||||
return {};
|
||||
}
|
||||
@ -150,10 +141,8 @@ namespace skyline::service::hid {
|
||||
Result IHidServer::SendVibrationValues(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
request.Skip<u64>(); // appletResourceUserId
|
||||
|
||||
auto &handleBuf = request.inputBuf.at(0);
|
||||
std::span handles(reinterpret_cast<NpadDeviceHandle *>(handleBuf.address), handleBuf.size / sizeof(NpadDeviceHandle));
|
||||
auto &valueBuf = request.inputBuf.at(1);
|
||||
std::span values(reinterpret_cast<NpadVibrationValue *>(valueBuf.address), valueBuf.size / sizeof(NpadVibrationValue));
|
||||
auto handles{request.inputBuf.at(0).cast<NpadDeviceHandle>()};
|
||||
auto values{request.inputBuf.at(1).cast<NpadVibrationValue>()};
|
||||
|
||||
for (size_t i{}; i < handles.size(); ++i) {
|
||||
const auto &handle = handles[i];
|
||||
|
@ -40,16 +40,16 @@ namespace skyline::service::lm {
|
||||
LogLevel level;
|
||||
u8 verbosity;
|
||||
u32 payloadLength;
|
||||
} &data = state.process->GetReference<Data>(request.inputBuf.at(0).address);
|
||||
} &data = request.inputBuf.at(0).as<Data>();
|
||||
|
||||
std::ostringstream logMessage;
|
||||
logMessage << "Guest log:";
|
||||
|
||||
u64 offset = sizeof(Data);
|
||||
while (offset < request.inputBuf.at(0).size) {
|
||||
auto fieldType = state.process->GetObject<LogFieldType>(request.inputBuf.at(0).address + offset++);
|
||||
auto length = state.process->GetObject<u8>(request.inputBuf.at(0).address + offset++);
|
||||
auto address = request.inputBuf.at(0).address + offset;
|
||||
while (offset < request.inputBuf[0].size()) {
|
||||
auto fieldType = request.inputBuf[0].subspan(offset++).as<LogFieldType>();
|
||||
auto length = request.inputBuf[0].subspan(offset++).as<u8>();
|
||||
auto object = request.inputBuf[0].subspan(offset, length);
|
||||
|
||||
logMessage << " ";
|
||||
|
||||
@ -58,24 +58,25 @@ namespace skyline::service::lm {
|
||||
offset += length;
|
||||
continue;
|
||||
case LogFieldType::Line:
|
||||
logMessage << GetFieldName(fieldType) << ": " << state.process->GetObject<u32>(address);
|
||||
logMessage << GetFieldName(fieldType) << ": " << object.as<u32>();
|
||||
offset += sizeof(u32);
|
||||
continue;
|
||||
case LogFieldType::DropCount:
|
||||
logMessage << GetFieldName(fieldType) << ": " << state.process->GetObject<u64>(address);
|
||||
logMessage << GetFieldName(fieldType) << ": " << object.as<u64>();
|
||||
offset += sizeof(u64);
|
||||
continue;
|
||||
case LogFieldType::Time:
|
||||
logMessage << GetFieldName(fieldType) << ": " << state.process->GetObject<u64>(address) << "s";
|
||||
logMessage << GetFieldName(fieldType) << ": " << object.as<u64>() << "s";
|
||||
offset += sizeof(u64);
|
||||
continue;
|
||||
case LogFieldType::Stop:
|
||||
break;
|
||||
default:
|
||||
logMessage << GetFieldName(fieldType) << ": " << state.process->GetString(address, length);
|
||||
logMessage << GetFieldName(fieldType) << ": " << object.as_string();
|
||||
offset += length;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -13,8 +13,7 @@ namespace skyline::service::nvdrv {
|
||||
}
|
||||
|
||||
Result INvDrvServices::Open(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
auto buffer = request.inputBuf.at(0);
|
||||
auto path = state.process->GetString(buffer.address, buffer.size);
|
||||
auto path{request.inputBuf.at(0).as_string()};
|
||||
|
||||
response.Push<u32>(driver->OpenDevice(path));
|
||||
response.Push(device::NvStatus::Success);
|
||||
@ -31,7 +30,7 @@ namespace skyline::service::nvdrv {
|
||||
// Strip the permissions from the command leaving only the ID
|
||||
cmd &= 0xFFFF;
|
||||
|
||||
std::optional<kernel::ipc::IpcBuffer> buffer{std::nullopt};
|
||||
span<u8> buffer{};
|
||||
if (request.inputBuf.empty() || request.outputBuf.empty()) {
|
||||
if (!request.inputBuf.empty())
|
||||
buffer = request.inputBuf.at(0);
|
||||
@ -39,13 +38,16 @@ namespace skyline::service::nvdrv {
|
||||
buffer = request.outputBuf.at(0);
|
||||
else
|
||||
throw exception("No IOCTL Buffers");
|
||||
} else if (request.inputBuf.at(0).address == request.outputBuf.at(0).address) {
|
||||
buffer = request.inputBuf.at(0);
|
||||
} else if (request.inputBuf[0].data() == request.outputBuf[0].data()) {
|
||||
if (request.inputBuf[0].size() >= request.outputBuf[0].size())
|
||||
buffer = request.inputBuf[0];
|
||||
else
|
||||
buffer = request.outputBuf[0];
|
||||
} else {
|
||||
throw exception("IOCTL Input Buffer (0x{:X}) != Output Buffer (0x{:X})", request.inputBuf[0].address, request.outputBuf[0].address);
|
||||
throw exception("IOCTL Input Buffer (0x{:X}) != Output Buffer (0x{:X})", fmt::ptr(request.inputBuf[0].data()), fmt::ptr(request.outputBuf[0].data()));
|
||||
}
|
||||
|
||||
response.Push(device->HandleIoctl(cmd, device::IoctlType::Ioctl, std::span<u8>(reinterpret_cast<u8 *>(buffer->address), buffer->size), {}));
|
||||
response.Push(device->HandleIoctl(cmd, device::IoctlType::Ioctl, buffer, {}));
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -101,10 +103,16 @@ namespace skyline::service::nvdrv {
|
||||
|
||||
if (request.inputBuf.size() < 2 || request.outputBuf.empty())
|
||||
throw exception("Inadequate amount of buffers for IOCTL2: I - {}, O - {}", request.inputBuf.size(), request.outputBuf.size());
|
||||
else if (request.inputBuf[0].address != request.outputBuf[0].address)
|
||||
throw exception("IOCTL2 Input Buffer (0x{:X}) != Output Buffer (0x{:X}) [Input Buffer #2: 0x{:X}]", request.inputBuf[0].address, request.outputBuf[0].address, request.inputBuf[1].address);
|
||||
else if (request.inputBuf[0].data() != request.outputBuf[0].data())
|
||||
throw exception("IOCTL2 Input Buffer (0x{:X}) != Output Buffer (0x{:X}) [Input Buffer #2: 0x{:X}]", fmt::ptr(request.inputBuf[0].data()), fmt::ptr(request.outputBuf[0].data()), fmt::ptr(request.inputBuf[1].data()));
|
||||
|
||||
response.Push(device->HandleIoctl(cmd, device::IoctlType::Ioctl2, std::span<u8>(reinterpret_cast<u8 *>(request.inputBuf[0].address), request.inputBuf[0].size), std::span<u8>(reinterpret_cast<u8 *>(request.inputBuf[1].address), request.inputBuf[1].size)));
|
||||
span<u8> buffer{};
|
||||
if (request.inputBuf[0].size() >= request.outputBuf[0].size())
|
||||
buffer = request.inputBuf[0];
|
||||
else
|
||||
buffer = request.outputBuf[0];
|
||||
|
||||
response.Push(device->HandleIoctl(cmd, device::IoctlType::Ioctl2, buffer, request.inputBuf[1]));
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -119,10 +127,16 @@ namespace skyline::service::nvdrv {
|
||||
|
||||
if (request.inputBuf.empty() || request.outputBuf.size() < 2)
|
||||
throw exception("Inadequate amount of buffers for IOCTL3: I - {}, O - {}", request.inputBuf.size(), request.outputBuf.size());
|
||||
else if (request.inputBuf[0].address != request.outputBuf[0].address)
|
||||
throw exception("IOCTL3 Input Buffer (0x{:X}) != Output Buffer (0x{:X}) [Output Buffer #2: 0x{:X}]", request.inputBuf[0].address, request.outputBuf[0].address, request.outputBuf[1].address);
|
||||
else if (request.inputBuf[0].data() != request.outputBuf[0].data())
|
||||
throw exception("IOCTL3 Input Buffer (0x{:X}) != Output Buffer (0x{:X}) [Output Buffer #2: 0x{:X}]", fmt::ptr(request.inputBuf[0].data()), fmt::ptr(request.outputBuf[0].data()), fmt::ptr(request.outputBuf[1].data()));
|
||||
|
||||
response.Push(device->HandleIoctl(cmd, device::IoctlType::Ioctl3, std::span<u8>(reinterpret_cast<u8 *>(request.inputBuf[0].address), request.inputBuf[0].size), std::span<u8>(reinterpret_cast<u8 *>(request.outputBuf[1].address), request.outputBuf[1].size)));
|
||||
span<u8> buffer{};
|
||||
if (request.inputBuf[0].size() >= request.outputBuf[0].size())
|
||||
buffer = request.inputBuf[0];
|
||||
else
|
||||
buffer = request.outputBuf[0];
|
||||
|
||||
response.Push(device->HandleIoctl(cmd, device::IoctlType::Ioctl3, buffer, request.outputBuf[1]));
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ namespace skyline::service::nvdrv::device {
|
||||
return name;
|
||||
}
|
||||
|
||||
NvStatus NvDevice::HandleIoctl(u32 cmd, IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
NvStatus NvDevice::HandleIoctl(u32 cmd, IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
std::string_view typeString{[type] {
|
||||
switch (type) {
|
||||
case IoctlType::Ioctl:
|
||||
@ -29,7 +29,7 @@ namespace skyline::service::nvdrv::device {
|
||||
}
|
||||
}()};
|
||||
|
||||
std::pair<std::function<NvStatus(IoctlType, std::span<u8>, std::span<u8>)>, std::string_view> function;
|
||||
std::pair<std::function<NvStatus(IoctlType, span<u8>, span<u8>)>, std::string_view> function;
|
||||
try {
|
||||
function = GetIoctlFunction(cmd);
|
||||
state.logger->Debug("{} @ {}: {}", typeString, GetName(), function.second);
|
||||
|
@ -8,11 +8,11 @@
|
||||
#include <kernel/ipc.h>
|
||||
#include <kernel/types/KEvent.h>
|
||||
|
||||
#define NVFUNC(id, Class, Function) std::pair<u32, std::pair<std::function<NvStatus(Class*, IoctlType, std::span<u8>, std::span<u8>)>, std::string_view>>{id, {&Class::Function, #Function}}
|
||||
#define NVFUNC(id, Class, Function) std::pair<u32, std::pair<std::function<NvStatus(Class*, IoctlType, span<u8>, span<u8>)>, std::string_view>>{id, {&Class::Function, #Function}}
|
||||
#define NVDEVICE_DECL_AUTO(name, value) decltype(value) name = value
|
||||
#define NVDEVICE_DECL(...) \
|
||||
NVDEVICE_DECL_AUTO(functions, frz::make_unordered_map({__VA_ARGS__})); \
|
||||
std::pair<std::function<NvStatus(IoctlType, std::span<u8>, std::span<u8>)>, std::string_view> GetIoctlFunction(u32 id) { \
|
||||
std::pair<std::function<NvStatus(IoctlType, span<u8>, span<u8>)>, std::string_view> GetIoctlFunction(u32 id) { \
|
||||
auto& function = functions.at(id); \
|
||||
return std::make_pair(std::bind(function.first, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3), function.second); \
|
||||
}
|
||||
@ -73,7 +73,7 @@ namespace skyline::service::nvdrv::device {
|
||||
|
||||
virtual ~NvDevice() = default;
|
||||
|
||||
virtual std::pair<std::function<NvStatus(IoctlType, std::span<u8>, std::span<u8>)>, std::string_view> GetIoctlFunction(u32 id) = 0;
|
||||
virtual std::pair<std::function<NvStatus(IoctlType, span<u8>, span<u8>)>, std::string_view> GetIoctlFunction(u32 id) = 0;
|
||||
|
||||
/**
|
||||
* @return The name of the class
|
||||
@ -85,7 +85,7 @@ namespace skyline::service::nvdrv::device {
|
||||
* @brief This handles IOCTL calls for devices
|
||||
* @param cmd The IOCTL command that was called
|
||||
*/
|
||||
NvStatus HandleIoctl(u32 cmd, IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus HandleIoctl(u32 cmd, IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
inline virtual std::shared_ptr<kernel::type::KEvent> QueryEvent(u32 eventId) {
|
||||
return nullptr;
|
||||
|
@ -11,11 +11,11 @@
|
||||
namespace skyline::service::nvdrv::device {
|
||||
NvHostAsGpu::NvHostAsGpu(const DeviceState &state) : NvDevice(state) {}
|
||||
|
||||
NvStatus NvHostAsGpu::BindChannel(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
NvStatus NvHostAsGpu::BindChannel(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
return NvStatus::Success;
|
||||
}
|
||||
|
||||
NvStatus NvHostAsGpu::AllocSpace(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
NvStatus NvHostAsGpu::AllocSpace(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
struct Data {
|
||||
u32 pages; // In
|
||||
u32 pageSize; // In
|
||||
@ -25,7 +25,7 @@ namespace skyline::service::nvdrv::device {
|
||||
u64 offset; // InOut
|
||||
u64 align; // In
|
||||
};
|
||||
} region = util::As<Data>(buffer);
|
||||
} region = buffer.as<Data>();
|
||||
|
||||
u64 size = static_cast<u64>(region.pages) * static_cast<u64>(region.pageSize);
|
||||
|
||||
@ -42,8 +42,8 @@ namespace skyline::service::nvdrv::device {
|
||||
return NvStatus::Success;
|
||||
}
|
||||
|
||||
NvStatus NvHostAsGpu::UnmapBuffer(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
u64 offset{util::As<u64>(buffer)};
|
||||
NvStatus NvHostAsGpu::UnmapBuffer(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
u64 offset{buffer.as<u64>()};
|
||||
|
||||
if (!state.gpu->memoryManager.Unmap(offset))
|
||||
state.logger->Warn("Failed to unmap chunk at 0x{:X}", offset);
|
||||
@ -51,7 +51,7 @@ namespace skyline::service::nvdrv::device {
|
||||
return NvStatus::Success;
|
||||
}
|
||||
|
||||
NvStatus NvHostAsGpu::Modify(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
NvStatus NvHostAsGpu::Modify(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
struct Data {
|
||||
u32 flags; // In
|
||||
u32 kind; // In
|
||||
@ -60,7 +60,7 @@ namespace skyline::service::nvdrv::device {
|
||||
u64 bufferOffset; // In
|
||||
u64 mappingSize; // In
|
||||
u64 offset; // InOut
|
||||
} &data = util::As<Data>(buffer);
|
||||
} &data = buffer.as<Data>();
|
||||
|
||||
try {
|
||||
auto driver = nvdrv::driver.lock();
|
||||
@ -87,7 +87,7 @@ namespace skyline::service::nvdrv::device {
|
||||
}
|
||||
}
|
||||
|
||||
NvStatus NvHostAsGpu::GetVaRegions(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
NvStatus NvHostAsGpu::GetVaRegions(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
/*
|
||||
struct Data {
|
||||
u64 _pad0_;
|
||||
@ -100,12 +100,12 @@ namespace skyline::service::nvdrv::device {
|
||||
u32 pad;
|
||||
u64 pages;
|
||||
} regions[2]; // Out
|
||||
} ®ionInfo = util::As<Data>(buffer);
|
||||
} ®ionInfo = buffer.as<Data>();
|
||||
*/
|
||||
return NvStatus::Success;
|
||||
}
|
||||
|
||||
NvStatus NvHostAsGpu::AllocAsEx(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
NvStatus NvHostAsGpu::AllocAsEx(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
/*
|
||||
struct Data {
|
||||
u32 bigPageSize; // In
|
||||
@ -115,12 +115,12 @@ namespace skyline::service::nvdrv::device {
|
||||
u64 vaRangeStart; // In
|
||||
u64 vaRangeEnd; // In
|
||||
u64 vaRangeSplit; // In
|
||||
} addressSpace = util::As<Data>(buffer);
|
||||
} addressSpace = buffer.as<Data>();
|
||||
*/
|
||||
return NvStatus::Success;
|
||||
}
|
||||
|
||||
NvStatus NvHostAsGpu::Remap(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
NvStatus NvHostAsGpu::Remap(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
struct Entry {
|
||||
u16 flags; // In
|
||||
u16 kind; // In
|
||||
@ -132,7 +132,7 @@ namespace skyline::service::nvdrv::device {
|
||||
|
||||
constexpr u32 MinAlignmentShift{0x10}; // This shift is applied to all addresses passed to Remap
|
||||
|
||||
auto entries{util::AsSpan<Entry>(buffer)};
|
||||
auto entries{buffer.cast<Entry>()};
|
||||
for (auto entry : entries) {
|
||||
try {
|
||||
auto driver = nvdrv::driver.lock();
|
||||
|
@ -16,37 +16,37 @@ namespace skyline::service::nvdrv::device {
|
||||
/**
|
||||
* @brief This binds a channel to the address space (https://switchbrew.org/wiki/NV_services#NVGPU_AS_IOCTL_BIND_CHANNEL)
|
||||
*/
|
||||
NvStatus BindChannel(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus BindChannel(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
/**
|
||||
* @brief This reserves a region in the GPU address space (https://switchbrew.org/wiki/NV_services#NVGPU_AS_IOCTL_ALLOC_SPACE)
|
||||
*/
|
||||
NvStatus AllocSpace(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus AllocSpace(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
/**
|
||||
* @brief This unmaps a region in the GPU address space (https://switchbrew.org/wiki/NV_services#NVGPU_AS_IOCTL_UNMAP_BUFFER)
|
||||
*/
|
||||
NvStatus UnmapBuffer(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus UnmapBuffer(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
/**
|
||||
* @brief This maps a region in the GPU address space (https://switchbrew.org/wiki/NV_services#NVGPU_AS_IOCTL_MODIFY)
|
||||
*/
|
||||
NvStatus Modify(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus Modify(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
/**
|
||||
* @brief This returns the application's GPU address space (https://switchbrew.org/wiki/NV_services#NVGPU_AS_IOCTL_GET_VA_REGIONS)
|
||||
*/
|
||||
NvStatus GetVaRegions(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus GetVaRegions(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
/**
|
||||
* @brief This initializes the application's GPU address space (https://switchbrew.org/wiki/NV_services#NVGPU_AS_IOCTL_ALLOC_AS_EX)
|
||||
*/
|
||||
NvStatus AllocAsEx(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus AllocAsEx(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
/**
|
||||
* @brief Remaps a region of the GPU address space (https://switchbrew.org/wiki/NV_services#NVGPU_AS_IOCTL_REMAP)
|
||||
*/
|
||||
NvStatus Remap(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus Remap(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
NVDEVICE_DECL(
|
||||
NVFUNC(0x4101, NvHostAsGpu, BindChannel),
|
||||
|
@ -16,15 +16,15 @@ namespace skyline::service::nvdrv::device {
|
||||
channelFence.UpdateValue(hostSyncpoint);
|
||||
}
|
||||
|
||||
NvStatus NvHostChannel::SetNvmapFd(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
NvStatus NvHostChannel::SetNvmapFd(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
return NvStatus::Success;
|
||||
}
|
||||
|
||||
NvStatus NvHostChannel::SetSubmitTimeout(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
NvStatus NvHostChannel::SetSubmitTimeout(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
return NvStatus::Success;
|
||||
}
|
||||
|
||||
NvStatus NvHostChannel::SubmitGpfifo(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
NvStatus NvHostChannel::SubmitGpfifo(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
struct Data {
|
||||
u64 address; // In
|
||||
u32 numEntries; // In
|
||||
@ -41,7 +41,7 @@ namespace skyline::service::nvdrv::device {
|
||||
u32 raw;
|
||||
} flags; // In
|
||||
Fence fence; // InOut
|
||||
} &data = util::As<Data>(buffer);
|
||||
} &data = buffer.as<Data>();
|
||||
|
||||
auto driver = nvdrv::driver.lock();
|
||||
auto &hostSyncpoint = driver->hostSyncpoint;
|
||||
@ -54,7 +54,7 @@ namespace skyline::service::nvdrv::device {
|
||||
throw exception("Waiting on a fence through SubmitGpfifo is unimplemented");
|
||||
}
|
||||
|
||||
state.gpu->gpfifo.Push(std::span(state.process->GetPointer<gpu::gpfifo::GpEntry>(data.address), data.numEntries));
|
||||
state.gpu->gpfifo.Push(span(state.process->GetPointer<gpu::gpfifo::GpEntry>(data.address), data.numEntries));
|
||||
|
||||
data.fence.id = channelFence.id;
|
||||
|
||||
@ -69,20 +69,20 @@ namespace skyline::service::nvdrv::device {
|
||||
return NvStatus::Success;
|
||||
}
|
||||
|
||||
NvStatus NvHostChannel::AllocObjCtx(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
NvStatus NvHostChannel::AllocObjCtx(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
return NvStatus::Success;
|
||||
}
|
||||
|
||||
NvStatus NvHostChannel::ZcullBind(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
NvStatus NvHostChannel::ZcullBind(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
return NvStatus::Success;
|
||||
}
|
||||
|
||||
NvStatus NvHostChannel::SetErrorNotifier(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
NvStatus NvHostChannel::SetErrorNotifier(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
return NvStatus::Success;
|
||||
}
|
||||
|
||||
NvStatus NvHostChannel::SetPriority(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
switch (util::As<NvChannelPriority>(buffer)) {
|
||||
NvStatus NvHostChannel::SetPriority(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
switch (buffer.as<NvChannelPriority>()) {
|
||||
case NvChannelPriority::Low:
|
||||
timeslice = 1300;
|
||||
break;
|
||||
@ -97,14 +97,14 @@ namespace skyline::service::nvdrv::device {
|
||||
return NvStatus::Success;
|
||||
}
|
||||
|
||||
NvStatus NvHostChannel::AllocGpfifoEx2(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
NvStatus NvHostChannel::AllocGpfifoEx2(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
struct Data {
|
||||
u32 numEntries; // In
|
||||
u32 numJobs; // In
|
||||
u32 flags; // In
|
||||
Fence fence; // Out
|
||||
u32 reserved[3]; // In
|
||||
} &data = util::As<Data>(buffer);
|
||||
} &data = buffer.as<Data>();
|
||||
|
||||
auto driver = nvdrv::driver.lock();
|
||||
channelFence.UpdateValue(driver->hostSyncpoint);
|
||||
@ -113,7 +113,7 @@ namespace skyline::service::nvdrv::device {
|
||||
return NvStatus::Success;
|
||||
}
|
||||
|
||||
NvStatus NvHostChannel::SetUserData(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
NvStatus NvHostChannel::SetUserData(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
return NvStatus::Success;
|
||||
}
|
||||
|
||||
|
@ -30,47 +30,47 @@ namespace skyline::service::nvdrv::device {
|
||||
/**
|
||||
* @brief This sets the nvmap file descriptor (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_SET_NVMAP_FD)
|
||||
*/
|
||||
NvStatus SetNvmapFd(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus SetNvmapFd(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
/**
|
||||
* @brief This sets the timeout for the channel (https://switchbrew.org/wiki/NV_services#NVHOST_IOCTL_CHANNEL_SET_SUBMIT_TIMEOUT)
|
||||
*/
|
||||
NvStatus SetSubmitTimeout(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus SetSubmitTimeout(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
/**
|
||||
* @brief This submits a command to the GPFIFO (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO)
|
||||
*/
|
||||
NvStatus SubmitGpfifo(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus SubmitGpfifo(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
/**
|
||||
* @brief This allocates a graphic context object (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_ALLOC_OBJ_CTX)
|
||||
*/
|
||||
NvStatus AllocObjCtx(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus AllocObjCtx(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
/**
|
||||
* @brief This initializes the error notifier for this channel (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_ZCULL_BIND)
|
||||
*/
|
||||
NvStatus ZcullBind(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus ZcullBind(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
/**
|
||||
* @brief This initializes the error notifier for this channel (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_SET_ERROR_NOTIFIER)
|
||||
*/
|
||||
NvStatus SetErrorNotifier(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus SetErrorNotifier(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
/**
|
||||
* @brief This sets the priority of the channel (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_SET_PRIORITY)
|
||||
*/
|
||||
NvStatus SetPriority(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus SetPriority(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
/**
|
||||
* @brief This allocates a GPFIFO entry (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_ALLOC_GPFIFO_EX2)
|
||||
*/
|
||||
NvStatus AllocGpfifoEx2(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus AllocGpfifoEx2(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
/**
|
||||
* @brief This sets the user specific data (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_SET_USER_DATA)
|
||||
*/
|
||||
NvStatus SetUserData(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus SetUserData(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
std::shared_ptr<type::KEvent> QueryEvent(u32 eventId);
|
||||
|
||||
|
@ -72,12 +72,12 @@ namespace skyline::service::nvdrv::device {
|
||||
throw exception("Failed to find a free nvhost event!");
|
||||
}
|
||||
|
||||
NvStatus NvHostCtrl::EventWaitImpl(std::span<u8> buffer, bool async) {
|
||||
NvStatus NvHostCtrl::EventWaitImpl(span<u8> buffer, bool async) {
|
||||
struct Data {
|
||||
Fence fence; // In
|
||||
u32 timeout; // In
|
||||
EventValue value; // InOut
|
||||
} &data = util::As<Data>(buffer);
|
||||
} &data = buffer.as<Data>();
|
||||
|
||||
if (data.fence.id >= constant::MaxHwSyncpointCount)
|
||||
return NvStatus::BadValue;
|
||||
@ -135,12 +135,12 @@ namespace skyline::service::nvdrv::device {
|
||||
}
|
||||
}
|
||||
|
||||
NvStatus NvHostCtrl::GetConfig(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
NvStatus NvHostCtrl::GetConfig(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
return NvStatus::BadValue;
|
||||
}
|
||||
|
||||
NvStatus NvHostCtrl::EventSignal(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
auto userEventId{util::As<u32>(buffer)};
|
||||
NvStatus NvHostCtrl::EventSignal(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
auto userEventId{buffer.as<u32>()};
|
||||
state.logger->Debug("Signalling nvhost event: {}", userEventId);
|
||||
|
||||
if (userEventId >= constant::NvHostEventCount || !events.at(userEventId))
|
||||
@ -163,16 +163,16 @@ namespace skyline::service::nvdrv::device {
|
||||
return NvStatus::Success;
|
||||
}
|
||||
|
||||
NvStatus NvHostCtrl::EventWait(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
NvStatus NvHostCtrl::EventWait(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
return EventWaitImpl(buffer, false);
|
||||
}
|
||||
|
||||
NvStatus NvHostCtrl::EventWaitAsync(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
NvStatus NvHostCtrl::EventWaitAsync(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
return EventWaitImpl(buffer, true);
|
||||
}
|
||||
|
||||
NvStatus NvHostCtrl::EventRegister(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
auto userEventId{util::As<u32>(buffer)};
|
||||
NvStatus NvHostCtrl::EventRegister(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
auto userEventId{buffer.as<u32>()};
|
||||
state.logger->Debug("Registering nvhost event: {}", userEventId);
|
||||
|
||||
auto &event = events.at(userEventId);
|
||||
|
@ -87,7 +87,7 @@ namespace skyline {
|
||||
*/
|
||||
u32 FindFreeEvent(u32 syncpointId);
|
||||
|
||||
NvStatus EventWaitImpl(std::span<u8> buffer, bool async);
|
||||
NvStatus EventWaitImpl(span<u8> buffer, bool async);
|
||||
|
||||
public:
|
||||
NvHostCtrl(const DeviceState &state);
|
||||
@ -95,27 +95,27 @@ namespace skyline {
|
||||
/**
|
||||
* @brief This gets the value of an nvdrv setting, it returns an error code on production switches (https://switchbrew.org/wiki/NV_services#NVHOST_IOCTL_CTRL_GET_CONFIG)
|
||||
*/
|
||||
NvStatus GetConfig(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus GetConfig(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
/**
|
||||
* @brief This signals an NvHost event (https://switchbrew.org/wiki/NV_services#NVHOST_IOCTL_CTRL_EVENT_SIGNAL)
|
||||
*/
|
||||
NvStatus EventSignal(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus EventSignal(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
/**
|
||||
* @brief This synchronously waits on an NvHost event (https://switchbrew.org/wiki/NV_services#NVHOST_IOCTL_CTRL_EVENT_WAIT)
|
||||
*/
|
||||
NvStatus EventWait(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus EventWait(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
/**
|
||||
* @brief This asynchronously waits on an NvHost event (https://switchbrew.org/wiki/NV_services#NVHOST_IOCTL_CTRL_EVENT_WAIT_ASYNC)
|
||||
*/
|
||||
NvStatus EventWaitAsync(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus EventWaitAsync(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
/**
|
||||
* @brief This registers an NvHost event (https://switchbrew.org/wiki/NV_services#NVHOST_IOCTL_CTRL_EVENT_REGISTER)
|
||||
*/
|
||||
NvStatus EventRegister(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus EventRegister(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
std::shared_ptr<type::KEvent> QueryEvent(u32 eventId);
|
||||
|
||||
|
@ -7,12 +7,12 @@
|
||||
namespace skyline::service::nvdrv::device {
|
||||
NvHostCtrlGpu::NvHostCtrlGpu(const DeviceState &state) : errorNotifierEvent(std::make_shared<type::KEvent>(state)), unknownEvent(std::make_shared<type::KEvent>(state)), NvDevice(state) {}
|
||||
|
||||
NvStatus NvHostCtrlGpu::ZCullGetCtxSize(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
util::As<u32>(buffer) = 0x1;
|
||||
NvStatus NvHostCtrlGpu::ZCullGetCtxSize(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
buffer.as<u32>() = 0x1;
|
||||
return NvStatus::Success;
|
||||
}
|
||||
|
||||
NvStatus NvHostCtrlGpu::ZCullGetInfo(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
NvStatus NvHostCtrlGpu::ZCullGetInfo(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
struct ZCullInfo {
|
||||
u32 widthAlignPixels{0x20};
|
||||
u32 heightAlignPixels{0x20};
|
||||
@ -26,11 +26,11 @@ namespace skyline::service::nvdrv::device {
|
||||
u32 subregionCount{0x10};
|
||||
} zCullInfo;
|
||||
|
||||
util::As<ZCullInfo>(buffer) = zCullInfo;
|
||||
buffer.as<ZCullInfo>() = zCullInfo;
|
||||
return NvStatus::Success;
|
||||
}
|
||||
|
||||
NvStatus NvHostCtrlGpu::GetCharacteristics(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
NvStatus NvHostCtrlGpu::GetCharacteristics(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
struct GpuCharacteristics {
|
||||
u32 arch{0x120}; // NVGPU_GPU_ARCH_GM200
|
||||
u32 impl{0xB}; // 0xB (NVGPU_GPU_IMPL_GM20B) or 0xE (NVGPU_GPU_IMPL_GM20B_B)
|
||||
@ -73,7 +73,7 @@ namespace skyline::service::nvdrv::device {
|
||||
u64 gpuCharacteristicsBufSize; // InOut
|
||||
u64 gpuCharacteristicsBufAddr; // In
|
||||
GpuCharacteristics gpuCharacteristics; // Out
|
||||
} &data = util::As<Data>(buffer);
|
||||
} &data = buffer.as<Data>();
|
||||
|
||||
if (data.gpuCharacteristicsBufSize < sizeof(GpuCharacteristics))
|
||||
return NvStatus::InvalidSize;
|
||||
@ -84,12 +84,12 @@ namespace skyline::service::nvdrv::device {
|
||||
return NvStatus::Success;
|
||||
}
|
||||
|
||||
NvStatus NvHostCtrlGpu::GetTpcMasks(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
NvStatus NvHostCtrlGpu::GetTpcMasks(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
struct Data {
|
||||
u32 maskBufSize; // In
|
||||
u32 reserved[3]; // In
|
||||
u64 maskBuf; // Out
|
||||
} &data = util::As<Data>(buffer);
|
||||
} &data = buffer.as<Data>();
|
||||
|
||||
if (data.maskBufSize)
|
||||
data.maskBuf = 0x3;
|
||||
@ -97,12 +97,12 @@ namespace skyline::service::nvdrv::device {
|
||||
return NvStatus::Success;
|
||||
}
|
||||
|
||||
NvStatus NvHostCtrlGpu::GetActiveSlotMask(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
NvStatus NvHostCtrlGpu::GetActiveSlotMask(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
struct Data {
|
||||
u32 slot{0x07}; // Out
|
||||
u32 mask{0x01}; // Out
|
||||
} data;
|
||||
util::As<Data>(buffer) = data;
|
||||
buffer.as<Data>() = data;
|
||||
return NvStatus::Success;
|
||||
}
|
||||
|
||||
|
@ -20,27 +20,27 @@ namespace skyline::service::nvdrv::device {
|
||||
/**
|
||||
* @brief This returns a u32 GPU ZCULL Context Size (https://switchbrew.org/wiki/NV_services#NVGPU_GPU_IOCTL_ZCULL_GET_CTX_SIZE)
|
||||
*/
|
||||
NvStatus ZCullGetCtxSize(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus ZCullGetCtxSize(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
/**
|
||||
* @brief This returns a the GPU ZCULL Information (https://switchbrew.org/wiki/NV_services#NVGPU_GPU_IOCTL_ZCULL_GET_INFO)
|
||||
*/
|
||||
NvStatus ZCullGetInfo(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus ZCullGetInfo(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
/**
|
||||
* @brief This returns a struct with certain GPU characteristics (https://switchbrew.org/wiki/NV_services#NVGPU_GPU_IOCTL_GET_CHARACTERISTICS)
|
||||
*/
|
||||
NvStatus GetCharacteristics(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus GetCharacteristics(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
/**
|
||||
* @brief This returns the TPC mask value for each GPC (https://switchbrew.org/wiki/NV_services#NVGPU_GPU_IOCTL_GET_TPC_MASKS)
|
||||
*/
|
||||
NvStatus GetTpcMasks(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus GetTpcMasks(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
/**
|
||||
* @brief This returns the mask value for a ZBC slot (https://switchbrew.org/wiki/NV_services#NVGPU_GPU_IOCTL_ZBC_GET_ACTIVE_SLOT_MASK)
|
||||
*/
|
||||
NvStatus GetActiveSlotMask(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus GetActiveSlotMask(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
std::shared_ptr<type::KEvent> QueryEvent(u32 eventId);
|
||||
|
||||
|
@ -9,11 +9,11 @@ namespace skyline::service::nvdrv::device {
|
||||
|
||||
NvMap::NvMap(const DeviceState &state) : NvDevice(state) {}
|
||||
|
||||
NvStatus NvMap::Create(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
NvStatus NvMap::Create(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
struct Data {
|
||||
u32 size; // In
|
||||
u32 handle; // Out
|
||||
} &data = util::As<Data>(buffer);
|
||||
} &data = buffer.as<Data>();
|
||||
|
||||
handleTable[handleIndex] = std::make_shared<NvMapObject>(idIndex++, data.size);
|
||||
data.handle = handleIndex++;
|
||||
@ -22,11 +22,11 @@ namespace skyline::service::nvdrv::device {
|
||||
return NvStatus::Success;
|
||||
}
|
||||
|
||||
NvStatus NvMap::FromId(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
NvStatus NvMap::FromId(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
struct Data {
|
||||
u32 id; // In
|
||||
u32 handle; // Out
|
||||
} &data = util::As<Data>(buffer);
|
||||
} &data = buffer.as<Data>();
|
||||
|
||||
for (const auto &object : handleTable) {
|
||||
if (object.second->id == data.id) {
|
||||
@ -40,7 +40,7 @@ namespace skyline::service::nvdrv::device {
|
||||
return NvStatus::BadValue;
|
||||
}
|
||||
|
||||
NvStatus NvMap::Alloc(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
NvStatus NvMap::Alloc(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
struct Data {
|
||||
u32 handle; // In
|
||||
u32 heapMask; // In
|
||||
@ -49,7 +49,7 @@ namespace skyline::service::nvdrv::device {
|
||||
u8 kind; // In
|
||||
u8 _pad0_[7];
|
||||
u64 address; // InOut
|
||||
} &data = util::As<Data>(buffer);
|
||||
} &data = buffer.as<Data>();
|
||||
|
||||
try {
|
||||
auto &object = handleTable.at(data.handle);
|
||||
@ -68,14 +68,14 @@ namespace skyline::service::nvdrv::device {
|
||||
}
|
||||
}
|
||||
|
||||
NvStatus NvMap::Free(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
NvStatus NvMap::Free(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
struct Data {
|
||||
u32 handle; // In
|
||||
u32 _pad0_;
|
||||
u64 address; // Out
|
||||
u32 size; // Out
|
||||
u32 flags; // Out
|
||||
} &data = util::As<Data>(buffer);
|
||||
} &data = buffer.as<Data>();
|
||||
|
||||
try {
|
||||
const auto &object = handleTable.at(data.handle);
|
||||
@ -98,13 +98,13 @@ namespace skyline::service::nvdrv::device {
|
||||
}
|
||||
}
|
||||
|
||||
NvStatus NvMap::Param(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
NvStatus NvMap::Param(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
enum class Parameter : u32 { Size = 1, Alignment = 2, Base = 3, HeapMask = 4, Kind = 5, Compr = 6 }; // https://android.googlesource.com/kernel/tegra/+/refs/heads/android-tegra-flounder-3.10-marshmallow/include/linux/nvmap.h#102
|
||||
struct Data {
|
||||
u32 handle; // In
|
||||
Parameter parameter; // In
|
||||
u32 result; // Out
|
||||
} &data = util::As<Data>(buffer);
|
||||
} &data = buffer.as<Data>();
|
||||
|
||||
try {
|
||||
auto &object = handleTable.at(data.handle);
|
||||
@ -143,11 +143,11 @@ namespace skyline::service::nvdrv::device {
|
||||
}
|
||||
}
|
||||
|
||||
NvStatus NvMap::GetId(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
NvStatus NvMap::GetId(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
||||
struct Data {
|
||||
u32 id; // Out
|
||||
u32 handle; // In
|
||||
} &data = util::As<Data>(buffer);
|
||||
} &data = buffer.as<Data>();
|
||||
|
||||
try {
|
||||
data.id = handleTable.at(data.handle)->id;
|
||||
|
@ -44,32 +44,32 @@ namespace skyline::service::nvdrv::device {
|
||||
/**
|
||||
* @brief This creates an NvMapObject and returns an handle to it (https://switchbrew.org/wiki/NV_services#NVMAP_IOC_CREATE)
|
||||
*/
|
||||
NvStatus Create(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus Create(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
/**
|
||||
* @brief This returns the handle of an NvMapObject from it's ID (https://switchbrew.org/wiki/NV_services#NVMAP_IOC_FROM_ID)
|
||||
*/
|
||||
NvStatus FromId(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus FromId(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
/**
|
||||
* @brief This allocates memory for an NvMapObject (https://switchbrew.org/wiki/NV_services#NVMAP_IOC_ALLOC)
|
||||
*/
|
||||
NvStatus Alloc(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus Alloc(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
/**
|
||||
* @brief This frees previously allocated memory (https://switchbrew.org/wiki/NV_services#NVMAP_IOC_FREE)
|
||||
*/
|
||||
NvStatus Free(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus Free(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
/**
|
||||
* @brief This returns a particular parameter from an NvMapObject (https://switchbrew.org/wiki/NV_services#NVMAP_IOC_PARAM)
|
||||
*/
|
||||
NvStatus Param(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus Param(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
/**
|
||||
* @brief This returns the ID of an NvMapObject from it's handle (https://switchbrew.org/wiki/NV_services#NVMAP_IOC_GET_ID)
|
||||
*/
|
||||
NvStatus GetId(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer);
|
||||
NvStatus GetId(IoctlType type, span<u8> buffer, span<u8> inlineBuffer);
|
||||
|
||||
NVDEVICE_DECL(
|
||||
NVFUNC(0x0101, NvMap, Create),
|
||||
|
@ -11,7 +11,7 @@
|
||||
namespace skyline::service::nvdrv {
|
||||
Driver::Driver(const DeviceState &state) : state(state), hostSyncpoint(state) {}
|
||||
|
||||
u32 Driver::OpenDevice(const std::string &path) {
|
||||
u32 Driver::OpenDevice(std::string_view path) {
|
||||
state.logger->Debug("Opening NVDRV device ({}): {}", fdIndex, path);
|
||||
|
||||
switch (util::Hash(path)) {
|
||||
|
@ -46,7 +46,7 @@ namespace skyline::service::nvdrv {
|
||||
* @param path The path of the device to open an FD to
|
||||
* @return The file descriptor to the device
|
||||
*/
|
||||
u32 OpenDevice(const std::string &path);
|
||||
u32 OpenDevice(std::string_view path);
|
||||
|
||||
/**
|
||||
* @brief Returns a particular device with a specific FD
|
||||
|
@ -40,7 +40,7 @@ namespace skyline::service::pl {
|
||||
*pointer++ = font.length ^ SharedFontKey;
|
||||
font.offset = reinterpret_cast<u64>(pointer) - fontSharedMem->kernel.address;
|
||||
|
||||
memcpy(pointer, font.data, font.length);
|
||||
std::memcpy(pointer, font.data, font.length);
|
||||
pointer = reinterpret_cast<u32 *>(reinterpret_cast<u64>(pointer) + font.length);
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
namespace skyline::service::settings {
|
||||
ISettingsServer::ISettingsServer(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager) {}
|
||||
|
||||
constexpr std::array<u64, constant::NewLanguageCodeListSize> LanguageCodeList = {
|
||||
constexpr std::array<u64, constant::NewLanguageCodeListSize> LanguageCodeList{
|
||||
util::MakeMagic<u64>("ja"),
|
||||
util::MakeMagic<u64>("en-US"),
|
||||
util::MakeMagic<u64>("fr"),
|
||||
@ -28,8 +28,7 @@ namespace skyline::service::settings {
|
||||
};
|
||||
|
||||
Result ISettingsServer::GetAvailableLanguageCodes(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
state.process->WriteMemory(LanguageCodeList.data(), request.outputBuf.at(0).address, constant::OldLanguageCodeListSize * sizeof(u64));
|
||||
|
||||
request.outputBuf.at(0).copy_from(span(LanguageCodeList).first(constant::OldLanguageCodeListSize));
|
||||
response.Push<i32>(constant::OldLanguageCodeListSize);
|
||||
return {};
|
||||
}
|
||||
@ -40,8 +39,7 @@ namespace skyline::service::settings {
|
||||
}
|
||||
|
||||
Result ISettingsServer::GetAvailableLanguageCodes2(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
state.process->WriteMemory(LanguageCodeList.data(), request.outputBuf.at(0).address, constant::NewLanguageCodeListSize * sizeof(u64));
|
||||
|
||||
request.outputBuf.at(0).copy_from(LanguageCodeList);
|
||||
response.Push<i32>(constant::NewLanguageCodeListSize);
|
||||
return {};
|
||||
}
|
||||
|
@ -8,8 +8,7 @@ namespace skyline::service::settings {
|
||||
ISystemSettingsServer::ISystemSettingsServer(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager) {}
|
||||
|
||||
Result ISystemSettingsServer::GetFirmwareVersion(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
SysVerTitle title{.major=9, .minor=0, .micro=0, .revMajor=4, .revMinor=0, .platform="NX", .verHash="4de65c071fd0869695b7629f75eb97b2551dbf2f", .dispVer="9.0.0", .dispTitle="NintendoSDK Firmware for NX 9.0.0-4.0"};
|
||||
state.process->WriteMemory(title, request.outputBuf.at(0).address);
|
||||
request.outputBuf.at(0).as<SysVerTitle>() = {.major=9, .minor=0, .micro=0, .revMajor=4, .revMinor=0, .platform="NX", .verHash="4de65c071fd0869695b7629f75eb97b2551dbf2f", .dispVer="9.0.0", .dispTitle="NintendoSDK Firmware for NX 9.0.0-4.0"};
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user