diff options
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/hle/service/nx2_gsv.h | 37 |
1 files changed, 36 insertions, 1 deletions
diff --git a/src/core/hle/service/nx2_gsv.h b/src/core/hle/service/nx2_gsv.h index 628bdeda5b..72ef2d39d4 100644 --- a/src/core/hle/service/nx2_gsv.h +++ b/src/core/hle/service/nx2_gsv.h @@ -21,6 +21,7 @@ #include <optional> #include <memory> #include <mutex> +#include <utility> #include <vector> #include "common/alignment.h" @@ -48,6 +49,7 @@ #include "core/hle/kernel/k_readable_event.h" #include "core/hle/kernel/k_session.h" #include "core/hle/kernel/k_transfer_memory.h" +#include "core/hle/kernel/svc_results.h" #include "core/memory.h" #include "video_core/host1x/host1x.h" #include "video_core/host1x/nx2_video_decoder.h" @@ -304,6 +306,8 @@ public: {21, &INx2GpuSession::Start, "Start (guessed)"}, {22, &INx2GpuSession::OpenSubSession, "OpenSubSession (guessed)"}, {33, &INx2GpuSession::GetCount33, "Unknown33 (u32 count)"}, + {41, &INx2GpuSession::CreateGraphicsDevice, "CreateGraphicsDevice"}, + {42, &INx2GpuSession::DestroyGraphicsDevice, "DestroyGraphicsDevice"}, {201, &INx2GpuSession::GetUserPartition, "GetUserPartition (newer SDKs)"}, {202, &INx2GpuSession::GetGsvPartition, "GetGsvPartition (newer SDKs)"}, {203, &INx2GpuSession::GetVaRange, "GetVaRange (guessed)"}, @@ -395,9 +399,39 @@ private: static_cast<u32>(second), static_cast<u32>(second >> 32)}); } + // An empty partition is min = ~0, max = 0 (min > max). Fire Emblem: Fortune's Weave's SDK + // reads (0, 0) as a one-byte partition at address 0 and aborts in nn::gpu::sdk. void GetGsvPartition(HLERequestContext& ctx) { LOG_WARNING(Service, "(STUBBED) nx2:gpu TIPC 202 [2]={:#x}, empty", ctx.CommandBuffer()[2]); - TipcReplyWords(ctx, {0, 0, 0, 0}); + TipcReplyWords(ctx, {~0U, ~0U, 0, 0}); + } + + // Fire Emblem: Fortune's Weave: 41(name u64, flags u64, debug label u64) returns a device id + // that later NvRm calls name; 0 is not a valid id. Only flags 0 has been seen. + void CreateGraphicsDevice(HLERequestContext& ctx) { + const auto* b = ctx.CommandBuffer(); + const u64 name = u64{b[2]} | (u64{b[3]} << 32); + const u64 flags = u64{b[4]} | (u64{b[5]} << 32); + u32 id = 0; + for (u32 candidate = 1; candidate < m_devices.size(); ++candidate) { + if (!m_devices[candidate]) { + m_devices[candidate] = true; + id = candidate; + break; + } + } + LOG_INFO(Service, "nx2:gpu 41 create graphics device name={:#x} flags={:#x} -> id {}", name, + flags, id); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(id != 0 ? ResultSuccess : Kernel::ResultOutOfResource); + rb.Push(id); + } + + void DestroyGraphicsDevice(HLERequestContext& ctx) { + const u32 id = ctx.CommandBuffer()[2] & 0xff; + const bool existed = id < m_devices.size() && std::exchange(m_devices[id], false); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(existed ? ResultSuccess : Kernel::ResultNotFound); } void OpenSubSession(HLERequestContext& ctx) { @@ -1246,6 +1280,7 @@ private: std::array<Kernel::KEvent*, NumIds> m_events{}; std::map<u32, GpuMemory> m_memory; u32 m_next_memory_handle{1}; + std::array<bool, 64> m_devices{}; // gpu 41 graphics device ids (0 unused) }; // Native memory and images handed out by the Switch 2 graphics server (gsv 111/114/423/429/315), |
