Use u64s for FmtCast + Remove Functional Casts + Fix VMM Bugs

This commit is contained in:
◱ PixelyIon 2020-10-10 23:10:12 +05:30 committed by ◱ PixelyIon
parent 1db76dee1e
commit 745ea19f42
13 changed files with 51 additions and 50 deletions

View File

@ -64,7 +64,6 @@ add_library(skyline SHARED
${source_DIR}/skyline/kernel/types/KProcess.cpp ${source_DIR}/skyline/kernel/types/KProcess.cpp
${source_DIR}/skyline/kernel/types/KThread.cpp ${source_DIR}/skyline/kernel/types/KThread.cpp
${source_DIR}/skyline/kernel/types/KSharedMemory.cpp ${source_DIR}/skyline/kernel/types/KSharedMemory.cpp
${source_DIR}/skyline/kernel/types/KTransferMemory.cpp
${source_DIR}/skyline/kernel/types/KPrivateMemory.cpp ${source_DIR}/skyline/kernel/types/KPrivateMemory.cpp
${source_DIR}/skyline/services/serviceman.cpp ${source_DIR}/skyline/services/serviceman.cpp
${source_DIR}/skyline/services/base_service.cpp ${source_DIR}/skyline/services/base_service.cpp

View File

@ -82,9 +82,9 @@ namespace skyline {
namespace util { namespace util {
/** /**
* @brief A way to implicitly cast all typed pointers to void pointers, this is used for libfmt as it requires wrapping non-void pointers with fmt::ptr * @brief A way to implicitly cast all pointers to u64s, this is used for libfmt as we use 0x{:X} to print pointers
* @note There's the exception of signed char pointers as they represent C Strings * @note There's the exception of signed char pointers as they represent C Strings
* @note This does not cover std::shared_ptr or std::unique_ptr and those will have to be explicitly passed through fmt::ptr * @note This does not cover std::shared_ptr or std::unique_ptr and those will have to be explicitly casted to u64 or passed through fmt::ptr
*/ */
template<class T> template<class T>
constexpr auto FmtCast(T object) { constexpr auto FmtCast(T object) {
@ -92,7 +92,7 @@ namespace skyline {
if constexpr (std::is_same<char, typename std::remove_cv<typename std::remove_pointer<T>::type>::type>::value) if constexpr (std::is_same<char, typename std::remove_cv<typename std::remove_pointer<T>::type>::type>::value)
return reinterpret_cast<typename std::common_type<char *, T>::type>(object); return reinterpret_cast<typename std::common_type<char *, T>::type>(object);
else else
return reinterpret_cast<const void *>(object); return reinterpret_cast<const u64>(object);
else else
return object; return object;
} }

View File

@ -63,7 +63,7 @@ namespace skyline::gpu::gpfifo {
break; break;
case PushBufferMethodHeader::SecOp::OneInc: case PushBufferMethodHeader::SecOp::OneInc:
for (u16 i{}; i < methodHeader->methodCount; i++) for (u16 i{}; i < methodHeader->methodCount; i++)
Send(MethodParams{static_cast<u16>(methodHeader->methodAddress + bool(i)), *++entry, methodHeader->methodSubChannel, i == methodHeader->methodCount - 1}); Send(MethodParams{static_cast<u16>(methodHeader->methodAddress + static_cast<bool>(i)), *++entry, methodHeader->methodSubChannel, i == methodHeader->methodCount - 1});
break; break;
case PushBufferMethodHeader::SecOp::ImmdDataMethod: case PushBufferMethodHeader::SecOp::ImmdDataMethod:

View File

@ -30,8 +30,8 @@ namespace skyline::kernel::ipc {
for (u8 index{}; header->xNo > index; index++) { for (u8 index{}; header->xNo > index; index++) {
auto bufX{reinterpret_cast<BufferDescriptorX *>(pointer)}; auto bufX{reinterpret_cast<BufferDescriptorX *>(pointer)};
if (bufX->Pointer()) { if (bufX->Pointer()) {
inputBuf.emplace_back(bufX->Pointer(), u16(bufX->size)); inputBuf.emplace_back(bufX->Pointer(), static_cast<u16>(bufX->size));
state.logger->Debug("Buf X #{} AD: 0x{:X} SZ: 0x{:X} CTR: {}", index, u64(bufX->Pointer()), u16(bufX->size), u16(bufX->Counter())); state.logger->Debug("Buf X #{}: 0x{:X}, 0x{:X}, #{}", index, bufX->Pointer(), static_cast<u16>(bufX->size), static_cast<u16>(bufX->Counter()));
} }
pointer += sizeof(BufferDescriptorX); pointer += sizeof(BufferDescriptorX);
} }
@ -40,7 +40,7 @@ namespace skyline::kernel::ipc {
auto bufA{reinterpret_cast<BufferDescriptorABW *>(pointer)}; auto bufA{reinterpret_cast<BufferDescriptorABW *>(pointer)};
if (bufA->Pointer()) { if (bufA->Pointer()) {
inputBuf.emplace_back(bufA->Pointer(), bufA->Size()); inputBuf.emplace_back(bufA->Pointer(), bufA->Size());
state.logger->Debug("Buf A #{} AD: 0x{:X} SZ: 0x{:X}", index, u64(bufA->Pointer()), u64(bufA->Size())); state.logger->Debug("Buf A #{}: 0x{:X}, 0x{:X}", index, bufA->Pointer(), static_cast<u64>(bufA->Size()));
} }
pointer += sizeof(BufferDescriptorABW); pointer += sizeof(BufferDescriptorABW);
} }
@ -49,7 +49,7 @@ namespace skyline::kernel::ipc {
auto bufB{reinterpret_cast<BufferDescriptorABW *>(pointer)}; auto bufB{reinterpret_cast<BufferDescriptorABW *>(pointer)};
if (bufB->Pointer()) { if (bufB->Pointer()) {
outputBuf.emplace_back(bufB->Pointer(), bufB->Size()); outputBuf.emplace_back(bufB->Pointer(), bufB->Size());
state.logger->Debug("Buf B #{} AD: 0x{:X} SZ: 0x{:X}", index, u64(bufB->Pointer()), u64(bufB->Size())); state.logger->Debug("Buf B #{}: 0x{:X}, 0x{:X}", index, bufB->Pointer(), static_cast<u64>(bufB->Size()));
} }
pointer += sizeof(BufferDescriptorABW); pointer += sizeof(BufferDescriptorABW);
} }
@ -59,7 +59,7 @@ namespace skyline::kernel::ipc {
if (bufW->Pointer()) { if (bufW->Pointer()) {
outputBuf.emplace_back(bufW->Pointer(), bufW->Size()); outputBuf.emplace_back(bufW->Pointer(), bufW->Size());
outputBuf.emplace_back(bufW->Pointer(), bufW->Size()); outputBuf.emplace_back(bufW->Pointer(), bufW->Size());
state.logger->Debug("Buf W #{} AD: 0x{:X} SZ: 0x{:X}", index, u64(bufW->Pointer()), u16(bufW->Size())); state.logger->Debug("Buf W #{}: 0x{:X}, 0x{:X}", index, bufW->Pointer(), static_cast<u16>(bufW->Size()));
} }
pointer += sizeof(BufferDescriptorABW); pointer += sizeof(BufferDescriptorABW);
} }
@ -95,34 +95,34 @@ namespace skyline::kernel::ipc {
payloadOffset = cmdArg; payloadOffset = cmdArg;
if (payload->magic != util::MakeMagic<u32>("SFCI") && (header->type != CommandType::Control && header->type != CommandType::ControlWithContext)) // SFCI is the magic in received IPC messages if (payload->magic != util::MakeMagic<u32>("SFCI") && (header->type != CommandType::Control && header->type != CommandType::ControlWithContext)) // SFCI is the magic in received IPC messages
state.logger->Debug("Unexpected Magic in PayloadHeader: 0x{:X}", u32(payload->magic)); state.logger->Debug("Unexpected Magic in PayloadHeader: 0x{:X}", static_cast<u32>(payload->magic));
pointer += constant::IpcPaddingSum - padding + cBufferLengthSize; pointer += constant::IpcPaddingSum - padding + cBufferLengthSize;
if (header->cFlag == BufferCFlag::SingleDescriptor) { if (header->cFlag == BufferCFlag::SingleDescriptor) {
auto bufC{reinterpret_cast<BufferDescriptorC *>(pointer)}; auto bufC{reinterpret_cast<BufferDescriptorC *>(pointer)};
if (bufC->address) { if (bufC->address) {
outputBuf.emplace_back(bufC->Pointer(), u16(bufC->size)); outputBuf.emplace_back(bufC->Pointer(), static_cast<u16>(bufC->size));
state.logger->Debug("Buf C: AD: 0x{:X} SZ: 0x{:X}", bufC->Pointer(), u16(bufC->size)); state.logger->Debug("Buf C: 0x{:X}, 0x{:X}", bufC->Pointer(), static_cast<u16>(bufC->size));
} }
} else if (header->cFlag > BufferCFlag::SingleDescriptor) { } else if (header->cFlag > BufferCFlag::SingleDescriptor) {
for (u8 index{}; (static_cast<u8>(header->cFlag) - 2) > index; index++) { // (cFlag - 2) C descriptors are present for (u8 index{}; (static_cast<u8>(header->cFlag) - 2) > index; index++) { // (cFlag - 2) C descriptors are present
auto bufC{reinterpret_cast<BufferDescriptorC *>(pointer)}; auto bufC{reinterpret_cast<BufferDescriptorC *>(pointer)};
if (bufC->address) { if (bufC->address) {
outputBuf.emplace_back(bufC->Pointer(), u16(bufC->size)); outputBuf.emplace_back(bufC->Pointer(), static_cast<u16>(bufC->size));
state.logger->Debug("Buf C #{} AD: 0x{:X} SZ: 0x{:X}", index, bufC->Pointer(), u16(bufC->size)); state.logger->Debug("Buf C #{}: 0x{:X}, 0x{:X}", index, bufC->Pointer(), static_cast<u16>(bufC->size));
} }
pointer += sizeof(BufferDescriptorC); pointer += sizeof(BufferDescriptorC);
} }
} }
if (header->type == CommandType::Request || header->type == CommandType::RequestWithContext) { if (header->type == CommandType::Request || header->type == CommandType::RequestWithContext) {
state.logger->Debug("Header: Input No: {}, Output No: {}, Raw Size: {}", inputBuf.size(), outputBuf.size(), u64(cmdArgSz)); state.logger->Debug("Header: Input No: {}, Output No: {}, Raw Size: {}", inputBuf.size(), outputBuf.size(), static_cast<u64>(cmdArgSz));
if (header->handleDesc) if (header->handleDesc)
state.logger->Debug("Handle Descriptor: Send PID: {}, Copy Count: {}, Move Count: {}", bool(handleDesc->sendPid), u32(handleDesc->copyCount), u32(handleDesc->moveCount)); state.logger->Debug("Handle Descriptor: Send PID: {}, Copy Count: {}, Move Count: {}", static_cast<bool>(handleDesc->sendPid), static_cast<u32>(handleDesc->copyCount), static_cast<u32>(handleDesc->moveCount));
if (isDomain) if (isDomain)
state.logger->Debug("Domain Header: Command: {}, Input Object Count: {}, Object ID: 0x{:X}", domain->command, domain->inputCount, domain->objectId); state.logger->Debug("Domain Header: Command: {}, Input Object Count: {}, Object ID: 0x{:X}", domain->command, domain->inputCount, domain->objectId);
state.logger->Debug("Command ID: 0x{:X}", u32(payload->value)); state.logger->Debug("Command ID: 0x{:X}", static_cast<u32>(payload->value));
} }
} }
@ -183,6 +183,6 @@ namespace skyline::kernel::ipc {
} }
} }
state.logger->Debug("Output: Raw Size: {}, Command ID: 0x{:X}, Copy Handles: {}, Move Handles: {}", u32(header->rawSize), u32(payloadHeader->value), copyHandles.size(), moveHandles.size()); state.logger->Debug("Output: Raw Size: {}, Command ID: 0x{:X}, Copy Handles: {}, Move Handles: {}", static_cast<u32>(header->rawSize), static_cast<u32>(payloadHeader->value), copyHandles.size(), moveHandles.size());
} }
} }

View File

@ -85,7 +85,7 @@ namespace skyline::kernel {
auto upper{std::upper_bound(chunks.begin(), chunks.end(), chunk.ptr, [](const u8 *ptr, const ChunkDescriptor &chunk) -> bool { return ptr < chunk.ptr; })}; auto upper{std::upper_bound(chunks.begin(), chunks.end(), chunk.ptr, [](const u8 *ptr, const ChunkDescriptor &chunk) -> bool { return ptr < chunk.ptr; })};
if (upper == chunks.begin()) if (upper == chunks.begin())
throw exception("InsertChunk: Chunk inserted outside address space: 0x{:X} - 0x{:X} and 0x{:X} - 0x{:X}", upper->ptr, fmt::ptr(upper->ptr + upper->size), chunk.ptr, fmt::ptr(chunk.ptr + chunk.size)); throw exception("InsertChunk: Chunk inserted outside address space: 0x{:X} - 0x{:X} and 0x{:X} - 0x{:X}", upper->ptr, upper->ptr + upper->size, chunk.ptr, chunk.ptr + chunk.size);
upper = chunks.erase(upper, std::upper_bound(upper, chunks.end(), chunk.ptr + chunk.size, [](const u8 *ptr, const ChunkDescriptor &chunk) -> bool { return ptr < chunk.ptr; })); upper = chunks.erase(upper, std::upper_bound(upper, chunks.end(), chunk.ptr + chunk.size, [](const u8 *ptr, const ChunkDescriptor &chunk) -> bool { return ptr < chunk.ptr; }));
if (upper != chunks.end() && upper->ptr < chunk.ptr + chunk.size) { if (upper != chunks.end() && upper->ptr < chunk.ptr + chunk.size) {
@ -99,8 +99,21 @@ namespace skyline::kernel {
lower->state = chunk.state; lower->state = chunk.state;
lower->permission = chunk.permission; lower->permission = chunk.permission;
lower->attributes = chunk.attributes; lower->attributes = chunk.attributes;
} else if (lower->ptr + lower->size > chunk.ptr + chunk.size) {
auto lowerExtension{*lower};
lowerExtension.ptr = chunk.ptr + chunk.size;
lowerExtension.size = (lower->ptr + lower->size) - lowerExtension.ptr;
lower->size = chunk.ptr - lower->ptr;
if (lower->size) {
upper = chunks.insert(upper, lowerExtension);
chunks.insert(upper, chunk);
} else {
*lower = chunk;
chunks.insert(upper, lowerExtension);
}
} else if (chunk.IsCompatible(*lower)) { } else if (chunk.IsCompatible(*lower)) {
lower->size = lower->size + chunk.size; lower->size = std::max(lower->ptr + lower->size, chunk.ptr + chunk.size) - lower->ptr;
} else { } else {
if (lower->ptr + lower->size > chunk.ptr) if (lower->ptr + lower->size > chunk.ptr)
lower->size = chunk.ptr - lower->ptr; lower->size = chunk.ptr - lower->ptr;

View File

@ -71,7 +71,7 @@ namespace skyline::kernel::svc {
newChunk.attributes.isUncached = value.isUncached; newChunk.attributes.isUncached = value.isUncached;
state.process->memory.InsertChunk(newChunk); state.process->memory.InsertChunk(newChunk);
state.logger->Debug("svcSetMemoryAttribute: Set caching to {} at 0x{:X} for 0x{:X} bytes", bool(value.isUncached), pointer, size); state.logger->Debug("svcSetMemoryAttribute: Set caching to {} at 0x{:X} for 0x{:X} bytes", static_cast<bool>(value.isUncached), pointer, size);
state.ctx->gpr.w0 = Result{}; state.ctx->gpr.w0 = Result{};
} }
@ -119,7 +119,7 @@ namespace skyline::kernel::svc {
throw exception("svcMapMemory: Cannot find memory object in handle table for address 0x{:X}", source); throw exception("svcMapMemory: Cannot find memory object in handle table for address 0x{:X}", source);
object->item->UpdatePermission(source, size, {false, false, false}); object->item->UpdatePermission(source, size, {false, false, false});
state.logger->Debug("svcMapMemory: Mapped range 0x{:X} - 0x{:X} to 0x{:X} - 0x{:X} (Size: 0x{:X} bytes)", source, fmt::ptr(source + size), destination, fmt::ptr(destination + size), size); state.logger->Debug("svcMapMemory: Mapped range 0x{:X} - 0x{:X} to 0x{:X} - 0x{:X} (Size: 0x{:X} bytes)", source, source + size, destination, destination + size, size);
state.ctx->gpr.w0 = Result{}; state.ctx->gpr.w0 = Result{};
} }
@ -196,7 +196,7 @@ namespace skyline::kernel::svc {
.ipcRefCount = 0, .ipcRefCount = 0,
}; };
state.logger->Debug("svcQueryMemory: Address: 0x{:X}, Size: 0x{:X}, Type: 0x{:X}, Is Uncached: {}, Permissions: {}{}{}", memInfo.address, memInfo.size, memInfo.type, bool(chunk->attributes.isUncached), chunk->permission.r ? 'R' : '-', chunk->permission.w ? 'W' : '-', chunk->permission.x ? 'X' : '-'); state.logger->Debug("svcQueryMemory: Address: 0x{:X}, Size: 0x{:X}, Type: 0x{:X}, Is Uncached: {}, Permissions: {}{}{}", memInfo.address, memInfo.size, memInfo.type, static_cast<bool>(chunk->attributes.isUncached), chunk->permission.r ? 'R' : '-', chunk->permission.w ? 'W' : '-', chunk->permission.x ? 'X' : '-');
} else { } else {
auto addressSpaceEnd{reinterpret_cast<u64>(state.process->memory.addressSpace.address + state.process->memory.addressSpace.size)}; auto addressSpaceEnd{reinterpret_cast<u64>(state.process->memory.addressSpace.address + state.process->memory.addressSpace.size)};
@ -517,7 +517,7 @@ namespace skyline::kernel::svc {
void ArbitrateUnlock(const DeviceState &state) { void ArbitrateUnlock(const DeviceState &state) {
auto mutex{reinterpret_cast<u32*>(state.ctx->gpr.x0)}; auto mutex{reinterpret_cast<u32*>(state.ctx->gpr.x0)};
if (!util::WordAligned(mutex)) { if (!util::WordAligned(mutex)) {
state.logger->Warn("svcArbitrateUnlock: mutex pointer not word aligned: 0x{:X}", mutex); state.logger->Warn("svcArbitrateUnlock: 'mutex' not word aligned: 0x{:X}", mutex);
state.ctx->gpr.w0 = result::InvalidAddress; state.ctx->gpr.w0 = result::InvalidAddress;
return; return;
} }
@ -536,7 +536,7 @@ namespace skyline::kernel::svc {
void WaitProcessWideKeyAtomic(const DeviceState &state) { void WaitProcessWideKeyAtomic(const DeviceState &state) {
auto mutex{reinterpret_cast<u32*>(state.ctx->gpr.x0)}; auto mutex{reinterpret_cast<u32*>(state.ctx->gpr.x0)};
if (!util::WordAligned(mutex)) { if (!util::WordAligned(mutex)) {
state.logger->Warn("svcWaitProcessWideKeyAtomic: mutex pointer not word aligned: 0x{:X}", mutex); state.logger->Warn("svcWaitProcessWideKeyAtomic: 'mutex' not word aligned: 0x{:X}", mutex);
state.ctx->gpr.w0 = result::InvalidAddress; state.ctx->gpr.w0 = result::InvalidAddress;
return; return;
} }

View File

@ -16,7 +16,7 @@ namespace skyline::kernel::type {
this->ptr = reinterpret_cast<u8*>(mmap(ptr, size, PROT_READ | PROT_WRITE | PROT_EXEC, (ptr ? MAP_FIXED : 0) | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)); this->ptr = reinterpret_cast<u8*>(mmap(ptr, size, PROT_READ | PROT_WRITE | PROT_EXEC, (ptr ? MAP_FIXED : 0) | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0));
if (this->ptr == MAP_FAILED) if (this->ptr == MAP_FAILED)
throw exception("An occurred while mapping private memory: {} with {} @ 0x{:X}", strerror(errno), ptr, size); throw exception("An occurred while mapping private memory: {} with 0x{:X} @ 0x{:X}", strerror(errno), ptr, size);
state.process->memory.InsertChunk(ChunkDescriptor{ state.process->memory.InsertChunk(ChunkDescriptor{
.ptr = this->ptr, .ptr = this->ptr,

View File

@ -1,15 +0,0 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
#include <asm/unistd.h>
#include <nce.h>
#include <os.h>
#include "KProcess.h"
#include "KTransferMemory.h"
namespace skyline::kernel::type {
KTransferMemory::KTransferMemory(const DeviceState &state, u8* ptr, size_t size, memory::Permission permission, memory::MemoryState memState) : KSharedMemory(state, size, memState, KType::KTransferMemory) {
std::memcpy(kernel.ptr, ptr, size);
Map(ptr, size, permission);
}
};

View File

@ -3,7 +3,7 @@
#pragma once #pragma once
#include "KMemory.h" #include "KSharedMemory.h"
namespace skyline::kernel::type { namespace skyline::kernel::type {
/** /**
@ -11,6 +11,9 @@ namespace skyline::kernel::type {
*/ */
class KTransferMemory : public KSharedMemory { class KTransferMemory : public KSharedMemory {
public: public:
KTransferMemory(const DeviceState &state, u8 *ptr, size_t size, memory::Permission permission, memory::MemoryState memState = memory::states::TransferMemory); KTransferMemory(const DeviceState &state, u8 *ptr, size_t size, memory::Permission permission, memory::MemoryState memState = memory::states::TransferMemory) : KSharedMemory(state, size, memState, KType::KTransferMemory) {
std::memcpy(kernel.ptr, ptr, size);
Map(ptr, size, permission);
}
}; };
} }

View File

@ -35,7 +35,7 @@ namespace skyline::loader {
continue; continue;
loadInfo = NsoLoader::LoadNso(nsoFile, process, state, offset); loadInfo = NsoLoader::LoadNso(nsoFile, process, state, offset);
state.logger->Info("Loaded nso '{}' at 0x{:X}", nso, fmt::ptr(base + offset)); state.logger->Info("Loaded nso '{}' at 0x{:X}", nso, base + offset);
offset += loadInfo.size; offset += loadInfo.size;
} }

View File

@ -40,7 +40,7 @@ namespace skyline::service::audio {
} &data{request.inputBuf.at(0).as<Data>()}; } &data{request.inputBuf.at(0).as<Data>()};
auto tag{request.Pop<u64>()}; auto tag{request.Pop<u64>()};
state.logger->Debug("Appending buffer with address: 0x{:X}, size: 0x{:X}", data.sampleBuffer, data.sampleSize); state.logger->Debug("Appending buffer at 0x{:X}, Size: 0x{:X}", data.sampleBuffer, data.sampleSize);
span samples(data.sampleBuffer, data.sampleSize / sizeof(i16)); span samples(data.sampleBuffer, data.sampleSize / sizeof(i16));
if (sampleRate != constant::SampleRate) { if (sampleRate != constant::SampleRate) {

View File

@ -151,12 +151,13 @@ namespace skyline::service::hid {
auto &device{state.input->npad.at(handle.id)}; auto &device{state.input->npad.at(handle.id)};
if (device.type == handle.GetType()) { if (device.type == handle.GetType()) {
if (i + 1 != handles.size() && handles[i + 1].id == handle.id && handles[i + 1].isRight && !handle.isRight) { if (i + 1 != handles.size() && handles[i + 1].id == handle.id && handles[i + 1].isRight && !handle.isRight) {
state.logger->Debug("Vibration #{}&{} - Handle: 0x{:02X} (0b{:05b}), Vibration: {:.2f}@{:.2f}Hz, {:.2f}@{:.2f}Hz - {:.2f}@{:.2f}Hz, {:.2f}@{:.2f}Hz", i, i + 1, u8(handle.id), u8(handle.type), values[i].amplitudeLow, values[i].frequencyLow, values[i].amplitudeHigh, values[i].frequencyHigh, values[i + 1].amplitudeLow, values[i + 1].frequencyLow, values[i + 1].amplitudeHigh, values[i + 1].frequencyHigh); state.logger->Debug("Vibration #{}&{} - Handle: 0x{:02X} (0b{:05b}), Vibration: {:.2f}@{:.2f}Hz, {:.2f}@{:.2f}Hz - {:.2f}@{:.2f}Hz, {:.2f}@{:.2f}Hz", i, i + 1, static_cast<u8>(handle.id), static_cast<u8>(handle.type), values[i].amplitudeLow, values[i].frequencyLow, values[i].amplitudeHigh, values[i].frequencyHigh, values[i + 1].amplitudeLow, values[i + 1].frequencyLow, values[i + 1]
.amplitudeHigh, values[i + 1].frequencyHigh);
device.Vibrate(values[i], values[i + 1]); device.Vibrate(values[i], values[i + 1]);
i++; i++;
} else { } else {
const auto &value{values[i]}; const auto &value{values[i]};
state.logger->Debug("Vibration #{} - Handle: 0x{:02X} (0b{:05b}), Vibration: {:.2f}@{:.2f}Hz, {:.2f}@{:.2f}Hz", i, u8(handle.id), u8(handle.type), value.amplitudeLow, value.frequencyLow, value.amplitudeHigh, value.frequencyHigh); state.logger->Debug("Vibration #{} - Handle: 0x{:02X} (0b{:05b}), Vibration: {:.2f}@{:.2f}Hz, {:.2f}@{:.2f}Hz", i, static_cast<u8>(handle.id), static_cast<u8>(handle.type), value.amplitudeLow, value.frequencyLow, value.amplitudeHigh, value.frequencyHigh);
device.Vibrate(handle.isRight, value); device.Vibrate(handle.isRight, value);
} }
} }

View File

@ -59,7 +59,7 @@ namespace skyline::service::nvdrv::device {
object->pointer = data.pointer; object->pointer = data.pointer;
object->status = NvMapObject::Status::Allocated; object->status = NvMapObject::Status::Allocated;
state.logger->Debug("Handle: 0x{:X}, HeapMask: 0x{:X}, Flags: {}, Align: 0x{:X}, Kind: {}, Address: 0x{:X}", data.handle, data.heapMask, data.flags, data.align, data.kind, data.pointer); state.logger->Debug("Handle: 0x{:X}, HeapMask: 0x{:X}, Flags: {}, Align: 0x{:X}, Kind: {}, Pointer: 0x{:X}", data.handle, data.heapMask, data.flags, data.align, data.kind, data.pointer);
return NvStatus::Success; return NvStatus::Success;
} catch (const std::out_of_range &) { } catch (const std::out_of_range &) {
state.logger->Warn("Invalid NvMap handle: 0x{:X}", data.handle); state.logger->Warn("Invalid NvMap handle: 0x{:X}", data.handle);
@ -89,7 +89,7 @@ namespace skyline::service::nvdrv::device {
data.size = object->size; data.size = object->size;
handleTable.erase(data.handle); handleTable.erase(data.handle);
state.logger->Debug("Handle: 0x{:X} -> Address: 0x{:X}, Size: 0x{:X}, Flags: 0x{:X}", data.handle, data.pointer, data.size, data.flags); state.logger->Debug("Handle: 0x{:X} -> Pointer: 0x{:X}, Size: 0x{:X}, Flags: 0x{:X}", data.handle, data.pointer, data.size, data.flags);
return NvStatus::Success; return NvStatus::Success;
} catch (const std::out_of_range &) { } catch (const std::out_of_range &) {
state.logger->Warn("Invalid NvMap handle: 0x{:X}", data.handle); state.logger->Warn("Invalid NvMap handle: 0x{:X}", data.handle);