Skip to content

Commit dc9d99b

Browse files
authored
nn_fp: Implement GetMyComment and UpdateCommentAsync (#1173)
1 parent 573c98b commit dc9d99b

File tree

5 files changed

+110
-10
lines changed

5 files changed

+110
-10
lines changed

src/Cafe/IOSU/legacy/iosu_fpd.cpp

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,8 @@ namespace iosu
511511
return CallHandler_GetBlackList(fpdClient, vecIn, numVecIn, vecOut, numVecOut);
512512
case FPD_REQUEST_ID::GetFriendListEx:
513513
return CallHandler_GetFriendListEx(fpdClient, vecIn, numVecIn, vecOut, numVecOut);
514+
case FPD_REQUEST_ID::UpdateCommentAsync:
515+
return CallHandler_UpdateCommentAsync(fpdClient, vecIn, numVecIn, vecOut, numVecOut);
514516
case FPD_REQUEST_ID::UpdatePreferenceAsync:
515517
return CallHandler_UpdatePreferenceAsync(fpdClient, vecIn, numVecIn, vecOut, numVecOut);
516518
case FPD_REQUEST_ID::AddFriendRequestByPlayRecordAsync:
@@ -719,18 +721,23 @@ namespace iosu
719721

720722
nnResult CallHandler_GetMyComment(FPDClient* fpdClient, IPCIoctlVector* vecIn, uint32 numVecIn, IPCIoctlVector* vecOut, uint32 numVecOut)
721723
{
722-
static constexpr uint32 MY_COMMENT_LENGTH = 0x12; // are comments utf16? Buffer length is 0x24
723724
if(numVecIn != 0 || numVecOut != 1)
724725
return FPResult_InvalidIPCParam;
725-
if(vecOut->size != MY_COMMENT_LENGTH*sizeof(uint16be))
726+
std::basic_string<uint16be> myComment;
727+
if(g_fpd.nexFriendSession)
726728
{
727-
cemuLog_log(LogType::Force, "GetMyComment: Unexpected output size");
728-
return FPResult_InvalidIPCParam;
729+
if(vecOut->size != MY_COMMENT_LENGTH * sizeof(uint16be))
730+
{
731+
cemuLog_log(LogType::Force, "GetMyComment: Unexpected output size");
732+
return FPResult_InvalidIPCParam;
733+
}
734+
nexComment myNexComment;
735+
g_fpd.nexFriendSession->getMyComment(myNexComment);
736+
myComment = StringHelpers::FromUtf8(myNexComment.commentString);
729737
}
730-
std::basic_string<uint16be> myComment;
731-
myComment.resize(MY_COMMENT_LENGTH);
732-
memcpy(vecOut->basePhys.GetPtr(), myComment.data(), MY_COMMENT_LENGTH*sizeof(uint16be));
733-
return 0;
738+
myComment.insert(0, 1, '\0');
739+
memcpy(vecOut->basePhys.GetPtr(), myComment.c_str(), MY_COMMENT_LENGTH * sizeof(uint16be));
740+
return FPResult_Ok;
734741
}
735742

736743
nnResult CallHandler_GetMyPreference(FPDClient* fpdClient, IPCIoctlVector* vecIn, uint32 numVecIn, IPCIoctlVector* vecOut, uint32 numVecOut)
@@ -1143,6 +1150,36 @@ namespace iosu
11431150
return FPResult_Ok;
11441151
}
11451152

1153+
nnResult CallHandler_UpdateCommentAsync(FPDClient* fpdClient, IPCIoctlVector* vecIn, uint32 numVecIn, IPCIoctlVector* vecOut, uint32 numVecOut)
1154+
{
1155+
std::unique_lock _l(g_fpd.mtxFriendSession);
1156+
if (numVecIn != 1 || numVecOut != 0)
1157+
return FPResult_InvalidIPCParam;
1158+
if (!g_fpd.nexFriendSession)
1159+
return FPResult_RequestFailed;
1160+
uint32 messageLength = vecIn[0].size / sizeof(uint16be);
1161+
DeclareInputPtr(newComment, uint16be, messageLength, 0);
1162+
if (messageLength == 0 || newComment[messageLength-1] != 0)
1163+
{
1164+
cemuLog_log(LogType::Force, "UpdateCommentAsync: Message must contain at least a null-termination character");
1165+
return FPResult_InvalidIPCParam;
1166+
}
1167+
IPCCommandBody* cmd = ServiceCallDelayCurrentResponse();
1168+
1169+
auto utf8_comment = StringHelpers::ToUtf8(newComment, messageLength);
1170+
nexComment temporaryComment;
1171+
temporaryComment.ukn0 = 0;
1172+
temporaryComment.commentString = utf8_comment;
1173+
temporaryComment.ukn1 = 0;
1174+
1175+
g_fpd.nexFriendSession->updateCommentAsync(temporaryComment, [cmd](NexFriends::RpcErrorCode result) {
1176+
if (result != NexFriends::ERR_NONE)
1177+
return ServiceCallAsyncRespond(cmd, FPResult_RequestFailed);
1178+
ServiceCallAsyncRespond(cmd, FPResult_Ok);
1179+
});
1180+
return FPResult_Ok;
1181+
}
1182+
11461183
nnResult CallHandler_UpdatePreferenceAsync(FPDClient* fpdClient, IPCIoctlVector* vecIn, uint32 numVecIn, IPCIoctlVector* vecOut, uint32 numVecOut)
11471184
{
11481185
std::unique_lock _l(g_fpd.mtxFriendSession);

src/Cafe/IOSU/legacy/iosu_fpd.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ namespace iosu
212212
static const int RELATIONSHIP_FRIEND = 3;
213213

214214
static const int GAMEMODE_MAX_MESSAGE_LENGTH = 0x80; // limit includes null-terminator character, so only 0x7F actual characters can be used
215+
static const int MY_COMMENT_LENGTH = 0x12;
215216

216217
enum class FPD_REQUEST_ID
217218
{
@@ -245,6 +246,7 @@ namespace iosu
245246
CheckSettingStatusAsync = 0x7596,
246247
GetFriendListEx = 0x75F9,
247248
GetFriendRequestListEx = 0x76C1,
249+
UpdateCommentAsync = 0x7726,
248250
UpdatePreferenceAsync = 0x7727,
249251
RemoveFriendAsync = 0x7789,
250252
DeleteFriendFlagsAsync = 0x778A,

src/Cafe/OS/libs/nn_fp/nn_fp.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,14 @@ namespace nn
464464
return ipcCtx->Submit(std::move(ipcCtx));
465465
}
466466

467+
nnResult GetMyPlayingGame(iosu::fpd::GameKey* myPlayingGame)
468+
{
469+
FP_API_BASE();
470+
auto ipcCtx = std::make_unique<FPIpcContext>(iosu::fpd::FPD_REQUEST_ID::GetMyPlayingGame);
471+
ipcCtx->AddOutput(myPlayingGame, sizeof(iosu::fpd::GameKey));
472+
return ipcCtx->Submit(std::move(ipcCtx));
473+
}
474+
467475
nnResult GetMyPreference(iosu::fpd::FPDPreference* myPreference)
468476
{
469477
FP_API_BASE();
@@ -472,6 +480,14 @@ namespace nn
472480
return ipcCtx->Submit(std::move(ipcCtx));
473481
}
474482

483+
nnResult GetMyComment(uint16be* myComment)
484+
{
485+
FP_API_BASE();
486+
auto ipcCtx = std::make_unique<FPIpcContext>(iosu::fpd::FPD_REQUEST_ID::GetMyComment);
487+
ipcCtx->AddOutput(myComment, iosu::fpd::MY_COMMENT_LENGTH * sizeof(uint16be));
488+
return ipcCtx->Submit(std::move(ipcCtx));
489+
}
490+
475491
nnResult GetMyMii(FFLData_t* fflData)
476492
{
477493
FP_API_BASE();
@@ -607,6 +623,20 @@ namespace nn
607623
return resultBuf != 0 ? 1 : 0;
608624
}
609625

626+
nnResult UpdateCommentAsync(uint16be* newComment, void* funcPtr, void* customParam)
627+
{
628+
FP_API_BASE();
629+
auto ipcCtx = std::make_unique<FPIpcContext>(iosu::fpd::FPD_REQUEST_ID::UpdateCommentAsync);
630+
uint32 commentLen = CafeStringHelpers::Length(newComment, iosu::fpd::MY_COMMENT_LENGTH-1);
631+
if (commentLen >= iosu::fpd::MY_COMMENT_LENGTH-1)
632+
{
633+
cemuLog_log(LogType::Force, "UpdateCommentAsync: message too long");
634+
return FPResult_InvalidIPCParam;
635+
}
636+
ipcCtx->AddInput(newComment, sizeof(uint16be) * commentLen + 2);
637+
return ipcCtx->SubmitAsync(std::move(ipcCtx), funcPtr, customParam);
638+
}
639+
610640
nnResult UpdatePreferenceAsync(iosu::fpd::FPDPreference* newPreference, void* funcPtr, void* customParam)
611641
{
612642
FP_API_BASE();
@@ -763,7 +793,9 @@ namespace nn
763793
cafeExportRegisterFunc(GetMyAccountId, "nn_fp", "GetMyAccountId__Q2_2nn2fpFPc", LogType::NN_FP);
764794
cafeExportRegisterFunc(GetMyScreenName, "nn_fp", "GetMyScreenName__Q2_2nn2fpFPw", LogType::NN_FP);
765795
cafeExportRegisterFunc(GetMyMii, "nn_fp", "GetMyMii__Q2_2nn2fpFP12FFLStoreData", LogType::NN_FP);
796+
cafeExportRegisterFunc(GetMyPlayingGame, "nn_fp", "GetMyPlayingGame__Q2_2nn2fpFPQ3_2nn2fp7GameKey", LogType::NN_FP);
766797
cafeExportRegisterFunc(GetMyPreference, "nn_fp", "GetMyPreference__Q2_2nn2fpFPQ3_2nn2fp10Preference", LogType::NN_FP);
798+
cafeExportRegisterFunc(GetMyComment, "nn_fp", "GetMyComment__Q2_2nn2fpFPQ3_2nn2fp7Comment", LogType::NN_FP);
767799

768800
cafeExportRegisterFunc(GetFriendAccountId, "nn_fp", "GetFriendAccountId__Q2_2nn2fpFPA17_cPCUiUi", LogType::NN_FP);
769801
cafeExportRegisterFunc(GetFriendScreenName, "nn_fp", "GetFriendScreenName__Q2_2nn2fpFPA11_wPCUiUibPUc", LogType::NN_FP);
@@ -774,6 +806,7 @@ namespace nn
774806

775807
cafeExportRegisterFunc(CheckSettingStatusAsync, "nn_fp", "CheckSettingStatusAsync__Q2_2nn2fpFPUcPFQ2_2nn6ResultPv_vPv", LogType::NN_FP);
776808
cafeExportRegisterFunc(IsPreferenceValid, "nn_fp", "IsPreferenceValid__Q2_2nn2fpFv", LogType::NN_FP);
809+
cafeExportRegisterFunc(UpdateCommentAsync, "nn_fp", "UpdateCommentAsync__Q2_2nn2fpFPCwPFQ2_2nn6ResultPv_vPv", LogType::NN_FP);
777810
cafeExportRegisterFunc(UpdatePreferenceAsync, "nn_fp", "UpdatePreferenceAsync__Q2_2nn2fpFPCQ3_2nn2fp10PreferencePFQ2_2nn6ResultPv_vPv", LogType::NN_FP);
778811
cafeExportRegisterFunc(GetRequestBlockSettingAsync, "nn_fp", "GetRequestBlockSettingAsync__Q2_2nn2fpFPUcPCUiUiPFQ2_2nn6ResultPv_vPv", LogType::NN_FP);
779812

src/Cemu/nex/nexFriends.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,8 @@ void NexFriends::handleResponse_getAllInformation(nexServiceResponse_t* response
277277
}
278278
NexFriends* session = (NexFriends*)nexFriends;
279279
session->myPreference = nexPrincipalPreference(&response->data);
280-
nexComment comment(&response->data);
280+
auto comment = nexComment(&response->data);
281+
session->myComment = comment;
281282
if (response->data.hasReadOutOfBounds())
282283
return;
283284
// acquire lock on lists
@@ -391,6 +392,28 @@ void NexFriends::getMyPreference(nexPrincipalPreference& preference)
391392
preference = myPreference;
392393
}
393394

395+
bool NexFriends::updateCommentAsync(nexComment newComment, std::function<void(RpcErrorCode)> cb)
396+
{
397+
uint8 tempNexBufferArray[1024];
398+
nexPacketBuffer packetBuffer(tempNexBufferArray, sizeof(tempNexBufferArray), true);
399+
newComment.writeData(&packetBuffer);
400+
nexCon->callMethod(
401+
NEX_PROTOCOL_FRIENDS_WIIU, 15, &packetBuffer, [this, cb, newComment](nexServiceResponse_t* response) -> void {
402+
if (!response->isSuccessful)
403+
return cb(NexFriends::ERR_RPC_FAILED);
404+
this->myComment = newComment;
405+
return cb(NexFriends::ERR_NONE);
406+
},
407+
true);
408+
// TEST
409+
return true;
410+
}
411+
412+
void NexFriends::getMyComment(nexComment& comment)
413+
{
414+
comment = myComment;
415+
}
416+
394417
bool NexFriends::addProvisionalFriendByPidGuessed(uint32 principalId)
395418
{
396419
uint8 tempNexBufferArray[512];

src/Cemu/nex/nexFriends.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,9 @@ class nexComment : public nexType
297297

298298
void writeData(nexPacketBuffer* pb) const override
299299
{
300-
cemu_assert_unimplemented();
300+
pb->writeU8(ukn0);
301+
pb->writeString(commentString.c_str());
302+
pb->writeU64(ukn1);
301303
}
302304

303305
void readData(nexPacketBuffer* pb) override
@@ -554,6 +556,7 @@ class NexFriends
554556
bool getFriendRequestByMessageId(nexFriendRequest& friendRequestData, bool* isIncoming, uint64 messageId);
555557
bool isOnline();
556558
void getMyPreference(nexPrincipalPreference& preference);
559+
void getMyComment(nexComment& comment);
557560

558561
// asynchronous API (data has to be requested)
559562
bool addProvisionalFriend(char* name, std::function<void(RpcErrorCode)> cb);
@@ -565,6 +568,7 @@ class NexFriends
565568
void acceptFriendRequest(uint64 messageId, std::function<void(RpcErrorCode)> cb);
566569
void deleteFriendRequest(uint64 messageId, std::function<void(RpcErrorCode)> cb); // rejecting incoming friend request (differs from blocking friend requests)
567570
bool updatePreferencesAsync(const nexPrincipalPreference newPreferences, std::function<void(RpcErrorCode)> cb);
571+
bool updateCommentAsync(const nexComment newComment, std::function<void(RpcErrorCode)> cb);
568572
void updateMyPresence(nexPresenceV2& myPresence);
569573

570574
void setNotificationHandler(void(*notificationHandler)(NOTIFICATION_TYPE notificationType, uint32 pid));
@@ -619,6 +623,7 @@ class NexFriends
619623
// local friend state
620624
nexPresenceV2 myPresence;
621625
nexPrincipalPreference myPreference;
626+
nexComment myComment;
622627

623628
std::recursive_mutex mtx_lists;
624629
std::vector<nexFriend> list_friends;

0 commit comments

Comments
 (0)