aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorduck912 <350528965+Duck912@users.noreply.github.com>2026-10-31 01:45:56 -0400
committerDuck912 <350528965+Duck912@users.noreply.github.com>2026-11-01 14:58:36 -0500
commit5f0325e2b4e72c3d10c44c7445bf73bc63e0ea32 (patch)
tree85e3226b371ab968d7de7225af36b8b7740f60eb /src
parent1d945527856d2eb9390d5030d1ae6b3ab1ab97dd (diff)
nx2:gpu: create graphics devices and report an empty gsv partition
Fire Emblem: Fortune's Weave creates a graphics device with gpu 41 and uses the returned id in later NvRm calls; auto-stubbed, it got id 0 and NVN setup failed. Hand out ids from 1 and free them with 42. gpu 202 answered (0, 0) for an empty partition, which the SDK reads as a one-byte partition at address 0. An empty one is min ~0, max 0. Assisted-by: Claude Opus 5.5 (debugging, porting and drafting) Signed-off-by: duck912 <350528965+Duck912@users.noreply.github.com>
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/service/nx2_gsv.h37
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),