mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	Merge pull request #1703 from DarkLordZach/nvdec-ioctl
nvdrv: Stub nvdec/vic ioctls to bypass nvdec movies
This commit is contained in:
		
						commit
						02ea62568f
					
				@ -22,6 +22,18 @@ u32 nvhost_nvdec::ioctl(Ioctl command, const std::vector<u8>& input, const std::
 | 
			
		||||
    switch (static_cast<IoctlCommand>(command.raw)) {
 | 
			
		||||
    case IoctlCommand::IocSetNVMAPfdCommand:
 | 
			
		||||
        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");
 | 
			
		||||
@ -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) {
 | 
			
		||||
    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);
 | 
			
		||||
 | 
			
		||||
    nvmap_fd = params.nvmap_fd;
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
@ -23,16 +23,66 @@ public:
 | 
			
		||||
private:
 | 
			
		||||
    enum class IoctlCommand : u32_le {
 | 
			
		||||
        IocSetNVMAPfdCommand = 0x40044801,
 | 
			
		||||
        IocSubmit = 0xC0400001,
 | 
			
		||||
        IocGetSyncpoint = 0xC0080002,
 | 
			
		||||
        IocGetWaitbase = 0xC0080003,
 | 
			
		||||
        IocMapBuffer = 0xC01C0009,
 | 
			
		||||
        IocMapBufferEx = 0xC0A40009,
 | 
			
		||||
        IocUnmapBufferEx = 0xC0A4000A,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    struct IoctlSetNvmapFD {
 | 
			
		||||
        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 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
 | 
			
		||||
 | 
			
		||||
@ -22,6 +22,18 @@ u32 nvhost_vic::ioctl(Ioctl command, const std::vector<u8>& input, const std::ve
 | 
			
		||||
    switch (static_cast<IoctlCommand>(command.raw)) {
 | 
			
		||||
    case IoctlCommand::IocSetNVMAPfdCommand:
 | 
			
		||||
        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");
 | 
			
		||||
@ -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) {
 | 
			
		||||
    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);
 | 
			
		||||
 | 
			
		||||
    nvmap_fd = params.nvmap_fd;
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
@ -4,6 +4,7 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <array>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "common/swap.h"
 | 
			
		||||
@ -23,6 +24,12 @@ public:
 | 
			
		||||
private:
 | 
			
		||||
    enum class IoctlCommand : u32_le {
 | 
			
		||||
        IocSetNVMAPfdCommand = 0x40044801,
 | 
			
		||||
        IocSubmit = 0xC0400001,
 | 
			
		||||
        IocGetSyncpoint = 0xC0080002,
 | 
			
		||||
        IocGetWaitbase = 0xC0080003,
 | 
			
		||||
        IocMapBuffer = 0xC01C0009,
 | 
			
		||||
        IocMapBufferEx = 0xC03C0009,
 | 
			
		||||
        IocUnmapBufferEx = 0xC03C000A,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    struct IoctlSetNvmapFD {
 | 
			
		||||
@ -30,9 +37,65 @@ private:
 | 
			
		||||
    };
 | 
			
		||||
    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 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
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user