From 9acc324228b7028f947e053a08c18543f631e5ce Mon Sep 17 00:00:00 2001 From: Duck912 <350528965+Duck912@users.noreply.github.com> Date: Sun, 1 Nov 2026 21:41:49 -0500 Subject: nx2:vi2: report the display's maximum buffer resolution Command 106 was auto-stubbed, and Fire Emblem: Fortune's Weave treats its empty reply as mode 0 and picks its 720p tier (rendering at 360p). Report mode 4 (1440p) docked and 2 (1080p, the screen) handheld; the game then renders at 720p and 540p and upscales to those. EDEN_VI2_MAX_RESOLUTION_MODE overrides the mode. Assisted-by: Claude Opus 5.5 (debugging, implementation and drafting) Signed-off-by: Duck912 <350528965+Duck912@users.noreply.github.com> --- src/core/hle/service/nx2_gsv.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'src/core') diff --git a/src/core/hle/service/nx2_gsv.h b/src/core/hle/service/nx2_gsv.h index 397e2aacb8..5a2963f179 100644 --- a/src/core/hle/service/nx2_gsv.h +++ b/src/core/hle/service/nx2_gsv.h @@ -1454,6 +1454,7 @@ public: // auto stub's empty success reply works, but logged two lines per call (a 50 MB log // in an 18 minute session). {105, &INx2Vi2Session::SucceedQuietly, "Unknown105 (display \"default\")"}, + {106, &INx2Vi2Session::GetBufferMaxResolution, "GetBufferMaxResolution"}, {228, &INx2Vi2Session::CancelClientBuffer, "CancelClientBuffer"}, {229, &INx2Vi2Session::PresentClientBuffer, "PresentClientBuffer"}, }); @@ -1847,6 +1848,29 @@ private: rb.Push(0); } + // The highest buffer resolution mode of the "default" display. Fire Emblem: Fortune's Weave picks + // its output from it: 1 -> 1280x720, 2 -> 1920x1080, 4 and 8 -> 2560x1440; 0 (the auto stub's + // reply), 3 and 5 fall back to 720p. Docked reports 4, handheld 2 (the screen is 1080p); + // EDEN_VI2_MAX_RESOLUTION_MODE= overrides. + void GetBufferMaxResolution(HLERequestContext& ctx) { + const auto* packet = ctx.CommandBuffer(); + const u64 name = u64{packet[2]} | (u64{packet[3]} << 32); + constexpr u64 DefaultDisplay = 0x00746c7561666564ULL; // "default" + Result result = Kernel::ResultInvalidCombination; + u64 mode{}; + if (packet[0] == 0x7a && packet[1] == 2) { + result = Result{ErrorModule::VI, 7}; + if (name == DefaultDisplay) { + static const char* forced = std::getenv("EDEN_VI2_MAX_RESOLUTION_MODE"); + mode = forced ? std::strtoull(forced, nullptr, 0) : Settings::IsDockedMode() ? 4 : 2; + result = ResultSuccess; + } + } + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(result.raw); + rb.Push(mode); + } + // The same reply as the auto stub (success, no data), without its log lines. void SucceedQuietly(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2}; -- cgit v1.2.3