From 345ba088d1972f70374dcb98b4253cfadc632590 Mon Sep 17 00:00:00 2001 From: Arian Kordi Date: Thu, 9 Jul 2026 12:39:58 -0400 Subject: [PATCH] coreinit_FS: Invoke attach callback after FSAddClientEx to inform title that SD card was inserted. --- src/Cafe/OS/libs/coreinit/coreinit_FS.cpp | 38 +++++++++++++++++------ src/Cafe/OS/libs/coreinit/coreinit_FS.h | 9 +++++- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp b/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp index 433c83e9..2634c2bf 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp @@ -275,7 +275,23 @@ namespace coreinit cemuLog_log(LogType::Force, "FSShutdown called"); } - FS_RESULT FSAddClientEx(FSClient_t* fsClient, uint32 uknR4, uint32 errHandling) + struct AttachCallbackData + { + /* +0x00 */ uint8 unk[0x1c]; + /* +0x1c */ char mountName[8]; + }; + + SysAllocator s_fsAttachCallbackData; + + void invokeAttachCallback(FSAttachParams& attachParams) + { + *s_fsAttachCallbackData = { .mountName = "sdcard" /* expected by Mii Maker */ }; + PPCCoreCallback(attachParams.userCallback, + 0 /* r3 = unknown */, 1 /* r4 = non-zero means device is attached */, + s_fsAttachCallbackData.GetMPTR(), attachParams.userContext); + } + + FS_RESULT FSAddClientEx(FSClient_t* fsClient, FSAttachParams* attachParams, uint32 errHandling) { if (!sFSInitialized || sFSShutdown || !fsClient) { @@ -283,15 +299,13 @@ namespace coreinit return FS_RESULT::FATAL_ERROR; } FSLockMutex(); - if (uknR4 != 0) + if (attachParams != nullptr && + attachParams->userCallback == nullptr) { - uint32 uknValue = memory_readU32(uknR4 + 0x00); - if (uknValue == 0) - { - FSUnlockMutex(); - __FSErrorAndBlock("FSAddClientEx - unknown error"); - return FS_RESULT::FATAL_ERROR; - } + FSUnlockMutex(); + // "FS: FSAddClient: attachParams->userCallback must be set.\n" + __FSErrorAndBlock("FSAddClientEx - unknown error"); + return FS_RESULT::FATAL_ERROR; } if (__FSIsClientRegistered(__FSGetClientBody(fsClient))) { @@ -324,12 +338,16 @@ namespace coreinit fsClientBody->fsClientBodyNext = nullptr; } FSUnlockMutex(); + + if (attachParams != nullptr) // invoke right before returning + invokeAttachCallback(*attachParams); + return FS_RESULT::SUCCESS; } FS_RESULT FSAddClient(FSClient_t* fsClient, uint32 errHandling) { - return FSAddClientEx(fsClient, 0, errHandling); + return FSAddClientEx(fsClient, nullptr, errHandling); } FS_RESULT FSDelClient(FSClient_t* fsClient, uint32 errHandling) diff --git a/src/Cafe/OS/libs/coreinit/coreinit_FS.h b/src/Cafe/OS/libs/coreinit/coreinit_FS.h index 76dcac85..286735fc 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_FS.h +++ b/src/Cafe/OS/libs/coreinit/coreinit_FS.h @@ -18,6 +18,13 @@ struct FSAsyncParams }; static_assert(sizeof(FSAsyncParams) == 0xC); +struct FSAttachParams +{ + MEMPTR userCallback; + MEMPTR userContext; +}; +static_assert(sizeof(FSAttachParams) == 0x8); + namespace coreinit { struct FSCmdBlockBody; @@ -242,7 +249,7 @@ namespace coreinit sint32 __FSQueryInfoAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint8* queryString, uint32 queryType, void* queryResult, uint32 errHandling, FSAsyncParams* fsAsyncParams); // coreinit exports - FS_RESULT FSAddClientEx(FSClient_t* fsClient, uint32 uknR4, uint32 errHandling); + FS_RESULT FSAddClientEx(FSClient_t* fsClient, FSAttachParams* attachParams, uint32 errHandling); FS_RESULT FSAddClient(FSClient_t* fsClient, uint32 errHandling); FS_RESULT FSDelClient(FSClient_t* fsClient, uint32 errHandling);