Merge pull request #1703 from DarkLordZach/nvdec-ioctl
nvdrv: Stub nvdec/vic ioctls to bypass nvdec movies
This commit is contained in:
commit
02ea62568f
4 changed files with 256 additions and 3 deletions
|
@ -22,6 +22,18 @@ u32 nvhost_nvdec::ioctl(Ioctl command, const std::vector<u8>& input, const std::
|
||||||
switch (static_cast<IoctlCommand>(command.raw)) {
|
switch (static_cast<IoctlCommand>(command.raw)) {
|
||||||
case IoctlCommand::IocSetNVMAPfdCommand:
|
case IoctlCommand::IocSetNVMAPfdCommand:
|
||||||
return SetNVMAPfd(input, output);
|
return SetNVMAPfd(input, output);
|
||||||
|
case IoctlCommand::IocSubmit:
|
||||||
|
return Submit(input, output);
|
||||||
|
case IoctlCommand::IocGetSyncpoint:
|
||||||
|
return GetSyncpoint(input, output);
|
||||||
|
case IoctlCommand::IocGetWaitbase:
|
||||||
|
return GetWaitbase(input, output);
|
||||||
|
case IoctlCommand::IocMapBuffer:
|
||||||
|
return MapBuffer(input, output);
|
||||||
|
case IoctlCommand::IocMapBufferEx:
|
||||||
|
return MapBufferEx(input, output);
|
||||||
|
case IoctlCommand::IocUnmapBufferEx:
|
||||||
|
return UnmapBufferEx(input, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
UNIMPLEMENTED_MSG("Unimplemented ioctl");
|
UNIMPLEMENTED_MSG("Unimplemented ioctl");
|
||||||
|
@ -30,11 +42,67 @@ u32 nvhost_nvdec::ioctl(Ioctl command, const std::vector<u8>& input, const std::
|
||||||
|
|
||||||
u32 nvhost_nvdec::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) {
|
u32 nvhost_nvdec::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||||
IoctlSetNvmapFD params{};
|
IoctlSetNvmapFD params{};
|
||||||
std::memcpy(¶ms, input.data(), input.size());
|
std::memcpy(¶ms, input.data(), sizeof(IoctlSetNvmapFD));
|
||||||
LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
|
LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
|
||||||
|
|
||||||
nvmap_fd = params.nvmap_fd;
|
nvmap_fd = params.nvmap_fd;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 nvhost_nvdec::Submit(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||||
|
IoctlSubmit params{};
|
||||||
|
std::memcpy(¶ms, input.data(), sizeof(IoctlSubmit));
|
||||||
|
LOG_WARNING(Service_NVDRV, "(STUBBED) called");
|
||||||
|
std::memcpy(output.data(), ¶ms, sizeof(IoctlSubmit));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 nvhost_nvdec::GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||||
|
IoctlGetSyncpoint params{};
|
||||||
|
std::memcpy(¶ms, input.data(), sizeof(IoctlGetSyncpoint));
|
||||||
|
LOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown);
|
||||||
|
params.value = 0; // Seems to be hard coded at 0
|
||||||
|
std::memcpy(output.data(), ¶ms, sizeof(IoctlGetSyncpoint));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 nvhost_nvdec::GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||||
|
IoctlGetWaitbase params{};
|
||||||
|
std::memcpy(¶ms, input.data(), sizeof(IoctlGetWaitbase));
|
||||||
|
LOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown);
|
||||||
|
params.value = 0; // Seems to be hard coded at 0
|
||||||
|
std::memcpy(output.data(), ¶ms, sizeof(IoctlGetWaitbase));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 nvhost_nvdec::MapBuffer(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||||
|
IoctlMapBuffer params{};
|
||||||
|
std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer));
|
||||||
|
LOG_WARNING(Service_NVDRV, "(STUBBED) called with address={:08X}{:08X}", params.address_2,
|
||||||
|
params.address_1);
|
||||||
|
params.address_1 = 0;
|
||||||
|
params.address_2 = 0;
|
||||||
|
std::memcpy(output.data(), ¶ms, sizeof(IoctlMapBuffer));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 nvhost_nvdec::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||||
|
IoctlMapBufferEx params{};
|
||||||
|
std::memcpy(¶ms, input.data(), sizeof(IoctlMapBufferEx));
|
||||||
|
LOG_WARNING(Service_NVDRV, "(STUBBED) called with address={:08X}{:08X}", params.address_2,
|
||||||
|
params.address_1);
|
||||||
|
params.address_1 = 0;
|
||||||
|
params.address_2 = 0;
|
||||||
|
std::memcpy(output.data(), ¶ms, sizeof(IoctlMapBufferEx));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 nvhost_nvdec::UnmapBufferEx(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||||
|
IoctlUnmapBufferEx params{};
|
||||||
|
std::memcpy(¶ms, input.data(), sizeof(IoctlUnmapBufferEx));
|
||||||
|
LOG_WARNING(Service_NVDRV, "(STUBBED) called");
|
||||||
|
std::memcpy(output.data(), ¶ms, sizeof(IoctlUnmapBufferEx));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Service::Nvidia::Devices
|
} // namespace Service::Nvidia::Devices
|
||||||
|
|
|
@ -23,16 +23,66 @@ public:
|
||||||
private:
|
private:
|
||||||
enum class IoctlCommand : u32_le {
|
enum class IoctlCommand : u32_le {
|
||||||
IocSetNVMAPfdCommand = 0x40044801,
|
IocSetNVMAPfdCommand = 0x40044801,
|
||||||
|
IocSubmit = 0xC0400001,
|
||||||
|
IocGetSyncpoint = 0xC0080002,
|
||||||
|
IocGetWaitbase = 0xC0080003,
|
||||||
|
IocMapBuffer = 0xC01C0009,
|
||||||
|
IocMapBufferEx = 0xC0A40009,
|
||||||
|
IocUnmapBufferEx = 0xC0A4000A,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IoctlSetNvmapFD {
|
struct IoctlSetNvmapFD {
|
||||||
u32_le nvmap_fd;
|
u32_le nvmap_fd;
|
||||||
};
|
};
|
||||||
static_assert(sizeof(IoctlSetNvmapFD) == 4, "IoctlSetNvmapFD is incorrect size");
|
static_assert(sizeof(IoctlSetNvmapFD) == 0x4, "IoctlSetNvmapFD is incorrect size");
|
||||||
|
|
||||||
|
struct IoctlSubmit {
|
||||||
|
INSERT_PADDING_BYTES(0x40); // TODO(DarkLordZach): RE this structure
|
||||||
|
};
|
||||||
|
static_assert(sizeof(IoctlSubmit) == 0x40, "IoctlSubmit has incorrect size");
|
||||||
|
|
||||||
|
struct IoctlGetSyncpoint {
|
||||||
|
u32 unknown; // seems to be ignored? Nintendo added this
|
||||||
|
u32 value;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(IoctlGetSyncpoint) == 0x08, "IoctlGetSyncpoint has incorrect size");
|
||||||
|
|
||||||
|
struct IoctlGetWaitbase {
|
||||||
|
u32 unknown; // seems to be ignored? Nintendo added this
|
||||||
|
u32 value;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(IoctlGetWaitbase) == 0x08, "IoctlGetWaitbase has incorrect size");
|
||||||
|
|
||||||
|
struct IoctlMapBuffer {
|
||||||
|
u32 unknown;
|
||||||
|
u32 address_1;
|
||||||
|
u32 address_2;
|
||||||
|
INSERT_PADDING_BYTES(0x10); // TODO(DarkLordZach): RE this structure
|
||||||
|
};
|
||||||
|
static_assert(sizeof(IoctlMapBuffer) == 0x1C, "IoctlMapBuffer is incorrect size");
|
||||||
|
|
||||||
|
struct IoctlMapBufferEx {
|
||||||
|
u32 unknown;
|
||||||
|
u32 address_1;
|
||||||
|
u32 address_2;
|
||||||
|
INSERT_PADDING_BYTES(0x98); // TODO(DarkLordZach): RE this structure
|
||||||
|
};
|
||||||
|
static_assert(sizeof(IoctlMapBufferEx) == 0xA4, "IoctlMapBufferEx has incorrect size");
|
||||||
|
|
||||||
|
struct IoctlUnmapBufferEx {
|
||||||
|
INSERT_PADDING_BYTES(0xA4); // TODO(DarkLordZach): RE this structure
|
||||||
|
};
|
||||||
|
static_assert(sizeof(IoctlUnmapBufferEx) == 0xA4, "IoctlUnmapBufferEx has incorrect size");
|
||||||
|
|
||||||
u32_le nvmap_fd{};
|
u32_le nvmap_fd{};
|
||||||
|
|
||||||
u32 SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output);
|
u32 SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output);
|
||||||
|
u32 Submit(const std::vector<u8>& input, std::vector<u8>& output);
|
||||||
|
u32 GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output);
|
||||||
|
u32 GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output);
|
||||||
|
u32 MapBuffer(const std::vector<u8>& input, std::vector<u8>& output);
|
||||||
|
u32 MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output);
|
||||||
|
u32 UnmapBufferEx(const std::vector<u8>& input, std::vector<u8>& output);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::Nvidia::Devices
|
} // namespace Service::Nvidia::Devices
|
||||||
|
|
|
@ -22,6 +22,18 @@ u32 nvhost_vic::ioctl(Ioctl command, const std::vector<u8>& input, const std::ve
|
||||||
switch (static_cast<IoctlCommand>(command.raw)) {
|
switch (static_cast<IoctlCommand>(command.raw)) {
|
||||||
case IoctlCommand::IocSetNVMAPfdCommand:
|
case IoctlCommand::IocSetNVMAPfdCommand:
|
||||||
return SetNVMAPfd(input, output);
|
return SetNVMAPfd(input, output);
|
||||||
|
case IoctlCommand::IocSubmit:
|
||||||
|
return Submit(input, output);
|
||||||
|
case IoctlCommand::IocGetSyncpoint:
|
||||||
|
return GetSyncpoint(input, output);
|
||||||
|
case IoctlCommand::IocGetWaitbase:
|
||||||
|
return GetWaitbase(input, output);
|
||||||
|
case IoctlCommand::IocMapBuffer:
|
||||||
|
return MapBuffer(input, output);
|
||||||
|
case IoctlCommand::IocMapBufferEx:
|
||||||
|
return MapBuffer(input, output);
|
||||||
|
case IoctlCommand::IocUnmapBufferEx:
|
||||||
|
return UnmapBufferEx(input, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
UNIMPLEMENTED_MSG("Unimplemented ioctl");
|
UNIMPLEMENTED_MSG("Unimplemented ioctl");
|
||||||
|
@ -30,11 +42,71 @@ u32 nvhost_vic::ioctl(Ioctl command, const std::vector<u8>& input, const std::ve
|
||||||
|
|
||||||
u32 nvhost_vic::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) {
|
u32 nvhost_vic::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||||
IoctlSetNvmapFD params{};
|
IoctlSetNvmapFD params{};
|
||||||
std::memcpy(¶ms, input.data(), input.size());
|
std::memcpy(¶ms, input.data(), sizeof(IoctlSetNvmapFD));
|
||||||
LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
|
LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
|
||||||
|
|
||||||
nvmap_fd = params.nvmap_fd;
|
nvmap_fd = params.nvmap_fd;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 nvhost_vic::Submit(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||||
|
IoctlSubmit params{};
|
||||||
|
std::memcpy(¶ms, input.data(), sizeof(IoctlSubmit));
|
||||||
|
LOG_WARNING(Service_NVDRV, "(STUBBED) called");
|
||||||
|
|
||||||
|
// Workaround for Luigi's Mansion 3, as nvhost_vic is not implemented for asynch GPU
|
||||||
|
params.command_buffer = {};
|
||||||
|
|
||||||
|
std::memcpy(output.data(), ¶ms, sizeof(IoctlSubmit));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 nvhost_vic::GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||||
|
IoctlGetSyncpoint params{};
|
||||||
|
std::memcpy(¶ms, input.data(), sizeof(IoctlGetSyncpoint));
|
||||||
|
LOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown);
|
||||||
|
params.value = 0; // Seems to be hard coded at 0
|
||||||
|
std::memcpy(output.data(), ¶ms, sizeof(IoctlGetSyncpoint));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 nvhost_vic::GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||||
|
IoctlGetWaitbase params{};
|
||||||
|
std::memcpy(¶ms, input.data(), sizeof(IoctlGetWaitbase));
|
||||||
|
LOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown);
|
||||||
|
params.value = 0; // Seems to be hard coded at 0
|
||||||
|
std::memcpy(output.data(), ¶ms, sizeof(IoctlGetWaitbase));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 nvhost_vic::MapBuffer(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||||
|
IoctlMapBuffer params{};
|
||||||
|
std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer));
|
||||||
|
LOG_WARNING(Service_NVDRV, "(STUBBED) called with address={:08X}{:08X}", params.address_2,
|
||||||
|
params.address_1);
|
||||||
|
params.address_1 = 0;
|
||||||
|
params.address_2 = 0;
|
||||||
|
std::memcpy(output.data(), ¶ms, sizeof(IoctlMapBuffer));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 nvhost_vic::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||||
|
IoctlMapBufferEx params{};
|
||||||
|
std::memcpy(¶ms, input.data(), sizeof(IoctlMapBufferEx));
|
||||||
|
LOG_WARNING(Service_NVDRV, "(STUBBED) called with address={:08X}{:08X}", params.address_2,
|
||||||
|
params.address_1);
|
||||||
|
params.address_1 = 0;
|
||||||
|
params.address_2 = 0;
|
||||||
|
std::memcpy(output.data(), ¶ms, sizeof(IoctlMapBufferEx));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 nvhost_vic::UnmapBufferEx(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||||
|
IoctlUnmapBufferEx params{};
|
||||||
|
std::memcpy(¶ms, input.data(), sizeof(IoctlUnmapBufferEx));
|
||||||
|
LOG_WARNING(Service_NVDRV, "(STUBBED) called");
|
||||||
|
std::memcpy(output.data(), ¶ms, sizeof(IoctlUnmapBufferEx));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Service::Nvidia::Devices
|
} // namespace Service::Nvidia::Devices
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/swap.h"
|
#include "common/swap.h"
|
||||||
|
@ -23,6 +24,12 @@ public:
|
||||||
private:
|
private:
|
||||||
enum class IoctlCommand : u32_le {
|
enum class IoctlCommand : u32_le {
|
||||||
IocSetNVMAPfdCommand = 0x40044801,
|
IocSetNVMAPfdCommand = 0x40044801,
|
||||||
|
IocSubmit = 0xC0400001,
|
||||||
|
IocGetSyncpoint = 0xC0080002,
|
||||||
|
IocGetWaitbase = 0xC0080003,
|
||||||
|
IocMapBuffer = 0xC01C0009,
|
||||||
|
IocMapBufferEx = 0xC03C0009,
|
||||||
|
IocUnmapBufferEx = 0xC03C000A,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IoctlSetNvmapFD {
|
struct IoctlSetNvmapFD {
|
||||||
|
@ -30,9 +37,65 @@ private:
|
||||||
};
|
};
|
||||||
static_assert(sizeof(IoctlSetNvmapFD) == 4, "IoctlSetNvmapFD is incorrect size");
|
static_assert(sizeof(IoctlSetNvmapFD) == 4, "IoctlSetNvmapFD is incorrect size");
|
||||||
|
|
||||||
|
struct IoctlSubmitCommandBuffer {
|
||||||
|
u32 id;
|
||||||
|
u32 offset;
|
||||||
|
u32 count;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(IoctlSubmitCommandBuffer) == 0xC,
|
||||||
|
"IoctlSubmitCommandBuffer is incorrect size");
|
||||||
|
|
||||||
|
struct IoctlSubmit {
|
||||||
|
u32 command_buffer_count;
|
||||||
|
u32 relocations_count;
|
||||||
|
u32 syncpt_count;
|
||||||
|
u32 wait_count;
|
||||||
|
std::array<IoctlSubmitCommandBuffer, 4> command_buffer;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(IoctlSubmit) == 0x40, "IoctlSubmit is incorrect size");
|
||||||
|
|
||||||
|
struct IoctlGetSyncpoint {
|
||||||
|
u32 unknown; // seems to be ignored? Nintendo added this
|
||||||
|
u32 value;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(IoctlGetSyncpoint) == 0x8, "IoctlGetSyncpoint is incorrect size");
|
||||||
|
|
||||||
|
struct IoctlGetWaitbase {
|
||||||
|
u32 unknown; // seems to be ignored? Nintendo added this
|
||||||
|
u32 value;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(IoctlGetWaitbase) == 0x8, "IoctlGetWaitbase is incorrect size");
|
||||||
|
|
||||||
|
struct IoctlMapBuffer {
|
||||||
|
u32 unknown;
|
||||||
|
u32 address_1;
|
||||||
|
u32 address_2;
|
||||||
|
INSERT_PADDING_BYTES(0x10); // TODO(DarkLordZach): RE this structure
|
||||||
|
};
|
||||||
|
static_assert(sizeof(IoctlMapBuffer) == 0x1C, "IoctlMapBuffer is incorrect size");
|
||||||
|
|
||||||
|
struct IoctlMapBufferEx {
|
||||||
|
u32 unknown;
|
||||||
|
u32 address_1;
|
||||||
|
u32 address_2;
|
||||||
|
INSERT_PADDING_BYTES(0x30); // TODO(DarkLordZach): RE this structure
|
||||||
|
};
|
||||||
|
static_assert(sizeof(IoctlMapBufferEx) == 0x3C, "IoctlMapBufferEx is incorrect size");
|
||||||
|
|
||||||
|
struct IoctlUnmapBufferEx {
|
||||||
|
INSERT_PADDING_BYTES(0x3C); // TODO(DarkLordZach): RE this structure
|
||||||
|
};
|
||||||
|
static_assert(sizeof(IoctlUnmapBufferEx) == 0x3C, "IoctlUnmapBufferEx is incorrect size");
|
||||||
|
|
||||||
u32_le nvmap_fd{};
|
u32_le nvmap_fd{};
|
||||||
|
|
||||||
u32 SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output);
|
u32 SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output);
|
||||||
|
u32 Submit(const std::vector<u8>& input, std::vector<u8>& output);
|
||||||
|
u32 GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output);
|
||||||
|
u32 GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output);
|
||||||
|
u32 MapBuffer(const std::vector<u8>& input, std::vector<u8>& output);
|
||||||
|
u32 MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output);
|
||||||
|
u32 UnmapBufferEx(const std::vector<u8>& input, std::vector<u8>& output);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::Nvidia::Devices
|
} // namespace Service::Nvidia::Devices
|
||||||
|
|
Loading…
Reference in a new issue