aboutsummaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorkraibse <33869366+kraibse@users.noreply.github.com>2026-11-01 12:19:37 +0100
committerkraibse <33869366+kraibse@users.noreply.github.com>2026-11-02 00:11:26 +0100
commit3fe4f1b189f9e57c1e18f2dc3fad2815943edebb (patch)
tree6b3500e14ba0d67bec438c1e4f105461ef070d40 /src/core
parent16967eb30e97937f4ac3b200e681adde70089161 (diff)
nx2: answer nx2:camera commands without a log line per call
GameChat polls nx2:camera command 29 every frame; it was logged as an unimplemented function (Critical plus Warning), 40,000 times in one session. Answer 3, 21 and 29 with the same empty success, logging each once. Assisted-by: Claude Sonnet 5.5 (code) (cherry picked from commit 0b7b562898bba137934420b366e3980476ee221f)
Diffstat (limited to 'src/core')
-rw-r--r--src/core/hle/service/nx2_gsv.h36
1 files changed, 31 insertions, 5 deletions
diff --git a/src/core/hle/service/nx2_gsv.h b/src/core/hle/service/nx2_gsv.h
index 9d0fd597b2..f4e026a6db 100644
--- a/src/core/hle/service/nx2_gsv.h
+++ b/src/core/hle/service/nx2_gsv.h
@@ -1511,6 +1511,34 @@ private:
std::map<u32, Kernel::KEvent*> m_events;
};
+// nn::camera::sdk camera context (gsv 602). GameChat builds its local camera video storage from it
+// and polls it every frame. Nothing about the commands is known beyond the arguments seen (3 and
+// 21 take the camera name "Default", 29 a u32 0x180 = 384, the width of the 384x216 camera images),
+// and the game runs on an empty success, so they answer that without a log line per call.
+class INx2CameraSession final : public ServiceFramework<INx2CameraSession> {
+public:
+ explicit INx2CameraSession(Core::System& system_) : ServiceFramework{system_, "nx2:camera"} {
+ RegisterHandlersTipc({
+ {3, &INx2CameraSession::Stub, "Unknown3 (camera name \"Default\")"},
+ {21, &INx2CameraSession::Stub, "Unknown21 (camera name \"Default\")"},
+ {29, &INx2CameraSession::Stub, "Unknown29 (u32 0x180, polled every frame)"},
+ });
+ }
+
+private:
+ void Stub(HLERequestContext& ctx) {
+ const u32 command = ctx.GetCommand();
+ if (m_logged.insert(command).second) {
+ LOG_WARNING(Service, "(STUBBED) nx2:camera TIPC {} [2]={:#x} [3]={:#x}, returning success",
+ command, ctx.CommandBuffer()[2], ctx.CommandBuffer()[3]);
+ }
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+ }
+
+ std::set<u32> m_logged;
+};
+
// Video decoder output images (nn::codec image pools, gsv 991/911/961). The preference
// (MakeDecodeImagePreference) holds an output layout code at word 1 and (width - 1) |
// (height - 1) << 16 at word 2. Codes come in pairs, one per CodecMode: 1/4 NV12 (format 3, what
@@ -2915,13 +2943,11 @@ private:
// nn::camera::sdk::CreateCameraContext sends 601() then 602(u64 1), which returns the camera
// context session (handle at word 3, result at word 4). Auto-stubbed, 602 had no handle, the
- // SDK sent 603 (destroy) and title 1 (1.8.0) aborted with 2034-0000. Its commands fall
- // through to the nx2 auto stub.
+ // SDK sent 603 (destroy) and title 1 (1.8.0) aborted with 2034-0000. Its commands are
+ // answered by INx2CameraSession.
void OpenCameraSession(HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) nx2:gsv TIPC 602, returning a nx2:camera session");
- ReturnRawSession(system, ctx,
- std::make_shared<INx2StubInterface>(
- system, INx2StubInterface::InternName("nx2:camera")));
+ ReturnRawSession(system, ctx, std::make_shared<INx2CameraSession>(system));
}
// nn::chat::gsv::Initialize sends 1201 then 1202, the same pair as 901/902 and 1001/1002.