mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-11-22 09:09:18 +01:00
nn_fp: Implement GetMyComment and UpdateCommentAsync (#1173)
This commit is contained in:
parent
573c98b2f8
commit
dc9d99b03b
@ -511,6 +511,8 @@ namespace iosu
|
|||||||
return CallHandler_GetBlackList(fpdClient, vecIn, numVecIn, vecOut, numVecOut);
|
return CallHandler_GetBlackList(fpdClient, vecIn, numVecIn, vecOut, numVecOut);
|
||||||
case FPD_REQUEST_ID::GetFriendListEx:
|
case FPD_REQUEST_ID::GetFriendListEx:
|
||||||
return CallHandler_GetFriendListEx(fpdClient, vecIn, numVecIn, vecOut, numVecOut);
|
return CallHandler_GetFriendListEx(fpdClient, vecIn, numVecIn, vecOut, numVecOut);
|
||||||
|
case FPD_REQUEST_ID::UpdateCommentAsync:
|
||||||
|
return CallHandler_UpdateCommentAsync(fpdClient, vecIn, numVecIn, vecOut, numVecOut);
|
||||||
case FPD_REQUEST_ID::UpdatePreferenceAsync:
|
case FPD_REQUEST_ID::UpdatePreferenceAsync:
|
||||||
return CallHandler_UpdatePreferenceAsync(fpdClient, vecIn, numVecIn, vecOut, numVecOut);
|
return CallHandler_UpdatePreferenceAsync(fpdClient, vecIn, numVecIn, vecOut, numVecOut);
|
||||||
case FPD_REQUEST_ID::AddFriendRequestByPlayRecordAsync:
|
case FPD_REQUEST_ID::AddFriendRequestByPlayRecordAsync:
|
||||||
@ -719,18 +721,23 @@ namespace iosu
|
|||||||
|
|
||||||
nnResult CallHandler_GetMyComment(FPDClient* fpdClient, IPCIoctlVector* vecIn, uint32 numVecIn, IPCIoctlVector* vecOut, uint32 numVecOut)
|
nnResult CallHandler_GetMyComment(FPDClient* fpdClient, IPCIoctlVector* vecIn, uint32 numVecIn, IPCIoctlVector* vecOut, uint32 numVecOut)
|
||||||
{
|
{
|
||||||
static constexpr uint32 MY_COMMENT_LENGTH = 0x12; // are comments utf16? Buffer length is 0x24
|
|
||||||
if(numVecIn != 0 || numVecOut != 1)
|
if(numVecIn != 0 || numVecOut != 1)
|
||||||
return FPResult_InvalidIPCParam;
|
return FPResult_InvalidIPCParam;
|
||||||
if(vecOut->size != MY_COMMENT_LENGTH*sizeof(uint16be))
|
std::basic_string<uint16be> myComment;
|
||||||
|
if(g_fpd.nexFriendSession)
|
||||||
|
{
|
||||||
|
if(vecOut->size != MY_COMMENT_LENGTH * sizeof(uint16be))
|
||||||
{
|
{
|
||||||
cemuLog_log(LogType::Force, "GetMyComment: Unexpected output size");
|
cemuLog_log(LogType::Force, "GetMyComment: Unexpected output size");
|
||||||
return FPResult_InvalidIPCParam;
|
return FPResult_InvalidIPCParam;
|
||||||
}
|
}
|
||||||
std::basic_string<uint16be> myComment;
|
nexComment myNexComment;
|
||||||
myComment.resize(MY_COMMENT_LENGTH);
|
g_fpd.nexFriendSession->getMyComment(myNexComment);
|
||||||
memcpy(vecOut->basePhys.GetPtr(), myComment.data(), MY_COMMENT_LENGTH*sizeof(uint16be));
|
myComment = StringHelpers::FromUtf8(myNexComment.commentString);
|
||||||
return 0;
|
}
|
||||||
|
myComment.insert(0, 1, '\0');
|
||||||
|
memcpy(vecOut->basePhys.GetPtr(), myComment.c_str(), MY_COMMENT_LENGTH * sizeof(uint16be));
|
||||||
|
return FPResult_Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
nnResult CallHandler_GetMyPreference(FPDClient* fpdClient, IPCIoctlVector* vecIn, uint32 numVecIn, IPCIoctlVector* vecOut, uint32 numVecOut)
|
nnResult CallHandler_GetMyPreference(FPDClient* fpdClient, IPCIoctlVector* vecIn, uint32 numVecIn, IPCIoctlVector* vecOut, uint32 numVecOut)
|
||||||
@ -1143,6 +1150,36 @@ namespace iosu
|
|||||||
return FPResult_Ok;
|
return FPResult_Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nnResult CallHandler_UpdateCommentAsync(FPDClient* fpdClient, IPCIoctlVector* vecIn, uint32 numVecIn, IPCIoctlVector* vecOut, uint32 numVecOut)
|
||||||
|
{
|
||||||
|
std::unique_lock _l(g_fpd.mtxFriendSession);
|
||||||
|
if (numVecIn != 1 || numVecOut != 0)
|
||||||
|
return FPResult_InvalidIPCParam;
|
||||||
|
if (!g_fpd.nexFriendSession)
|
||||||
|
return FPResult_RequestFailed;
|
||||||
|
uint32 messageLength = vecIn[0].size / sizeof(uint16be);
|
||||||
|
DeclareInputPtr(newComment, uint16be, messageLength, 0);
|
||||||
|
if (messageLength == 0 || newComment[messageLength-1] != 0)
|
||||||
|
{
|
||||||
|
cemuLog_log(LogType::Force, "UpdateCommentAsync: Message must contain at least a null-termination character");
|
||||||
|
return FPResult_InvalidIPCParam;
|
||||||
|
}
|
||||||
|
IPCCommandBody* cmd = ServiceCallDelayCurrentResponse();
|
||||||
|
|
||||||
|
auto utf8_comment = StringHelpers::ToUtf8(newComment, messageLength);
|
||||||
|
nexComment temporaryComment;
|
||||||
|
temporaryComment.ukn0 = 0;
|
||||||
|
temporaryComment.commentString = utf8_comment;
|
||||||
|
temporaryComment.ukn1 = 0;
|
||||||
|
|
||||||
|
g_fpd.nexFriendSession->updateCommentAsync(temporaryComment, [cmd](NexFriends::RpcErrorCode result) {
|
||||||
|
if (result != NexFriends::ERR_NONE)
|
||||||
|
return ServiceCallAsyncRespond(cmd, FPResult_RequestFailed);
|
||||||
|
ServiceCallAsyncRespond(cmd, FPResult_Ok);
|
||||||
|
});
|
||||||
|
return FPResult_Ok;
|
||||||
|
}
|
||||||
|
|
||||||
nnResult CallHandler_UpdatePreferenceAsync(FPDClient* fpdClient, IPCIoctlVector* vecIn, uint32 numVecIn, IPCIoctlVector* vecOut, uint32 numVecOut)
|
nnResult CallHandler_UpdatePreferenceAsync(FPDClient* fpdClient, IPCIoctlVector* vecIn, uint32 numVecIn, IPCIoctlVector* vecOut, uint32 numVecOut)
|
||||||
{
|
{
|
||||||
std::unique_lock _l(g_fpd.mtxFriendSession);
|
std::unique_lock _l(g_fpd.mtxFriendSession);
|
||||||
|
@ -212,6 +212,7 @@ namespace iosu
|
|||||||
static const int RELATIONSHIP_FRIEND = 3;
|
static const int RELATIONSHIP_FRIEND = 3;
|
||||||
|
|
||||||
static const int GAMEMODE_MAX_MESSAGE_LENGTH = 0x80; // limit includes null-terminator character, so only 0x7F actual characters can be used
|
static const int GAMEMODE_MAX_MESSAGE_LENGTH = 0x80; // limit includes null-terminator character, so only 0x7F actual characters can be used
|
||||||
|
static const int MY_COMMENT_LENGTH = 0x12;
|
||||||
|
|
||||||
enum class FPD_REQUEST_ID
|
enum class FPD_REQUEST_ID
|
||||||
{
|
{
|
||||||
@ -245,6 +246,7 @@ namespace iosu
|
|||||||
CheckSettingStatusAsync = 0x7596,
|
CheckSettingStatusAsync = 0x7596,
|
||||||
GetFriendListEx = 0x75F9,
|
GetFriendListEx = 0x75F9,
|
||||||
GetFriendRequestListEx = 0x76C1,
|
GetFriendRequestListEx = 0x76C1,
|
||||||
|
UpdateCommentAsync = 0x7726,
|
||||||
UpdatePreferenceAsync = 0x7727,
|
UpdatePreferenceAsync = 0x7727,
|
||||||
RemoveFriendAsync = 0x7789,
|
RemoveFriendAsync = 0x7789,
|
||||||
DeleteFriendFlagsAsync = 0x778A,
|
DeleteFriendFlagsAsync = 0x778A,
|
||||||
|
@ -464,6 +464,14 @@ namespace nn
|
|||||||
return ipcCtx->Submit(std::move(ipcCtx));
|
return ipcCtx->Submit(std::move(ipcCtx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nnResult GetMyPlayingGame(iosu::fpd::GameKey* myPlayingGame)
|
||||||
|
{
|
||||||
|
FP_API_BASE();
|
||||||
|
auto ipcCtx = std::make_unique<FPIpcContext>(iosu::fpd::FPD_REQUEST_ID::GetMyPlayingGame);
|
||||||
|
ipcCtx->AddOutput(myPlayingGame, sizeof(iosu::fpd::GameKey));
|
||||||
|
return ipcCtx->Submit(std::move(ipcCtx));
|
||||||
|
}
|
||||||
|
|
||||||
nnResult GetMyPreference(iosu::fpd::FPDPreference* myPreference)
|
nnResult GetMyPreference(iosu::fpd::FPDPreference* myPreference)
|
||||||
{
|
{
|
||||||
FP_API_BASE();
|
FP_API_BASE();
|
||||||
@ -472,6 +480,14 @@ namespace nn
|
|||||||
return ipcCtx->Submit(std::move(ipcCtx));
|
return ipcCtx->Submit(std::move(ipcCtx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nnResult GetMyComment(uint16be* myComment)
|
||||||
|
{
|
||||||
|
FP_API_BASE();
|
||||||
|
auto ipcCtx = std::make_unique<FPIpcContext>(iosu::fpd::FPD_REQUEST_ID::GetMyComment);
|
||||||
|
ipcCtx->AddOutput(myComment, iosu::fpd::MY_COMMENT_LENGTH * sizeof(uint16be));
|
||||||
|
return ipcCtx->Submit(std::move(ipcCtx));
|
||||||
|
}
|
||||||
|
|
||||||
nnResult GetMyMii(FFLData_t* fflData)
|
nnResult GetMyMii(FFLData_t* fflData)
|
||||||
{
|
{
|
||||||
FP_API_BASE();
|
FP_API_BASE();
|
||||||
@ -607,6 +623,20 @@ namespace nn
|
|||||||
return resultBuf != 0 ? 1 : 0;
|
return resultBuf != 0 ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nnResult UpdateCommentAsync(uint16be* newComment, void* funcPtr, void* customParam)
|
||||||
|
{
|
||||||
|
FP_API_BASE();
|
||||||
|
auto ipcCtx = std::make_unique<FPIpcContext>(iosu::fpd::FPD_REQUEST_ID::UpdateCommentAsync);
|
||||||
|
uint32 commentLen = CafeStringHelpers::Length(newComment, iosu::fpd::MY_COMMENT_LENGTH-1);
|
||||||
|
if (commentLen >= iosu::fpd::MY_COMMENT_LENGTH-1)
|
||||||
|
{
|
||||||
|
cemuLog_log(LogType::Force, "UpdateCommentAsync: message too long");
|
||||||
|
return FPResult_InvalidIPCParam;
|
||||||
|
}
|
||||||
|
ipcCtx->AddInput(newComment, sizeof(uint16be) * commentLen + 2);
|
||||||
|
return ipcCtx->SubmitAsync(std::move(ipcCtx), funcPtr, customParam);
|
||||||
|
}
|
||||||
|
|
||||||
nnResult UpdatePreferenceAsync(iosu::fpd::FPDPreference* newPreference, void* funcPtr, void* customParam)
|
nnResult UpdatePreferenceAsync(iosu::fpd::FPDPreference* newPreference, void* funcPtr, void* customParam)
|
||||||
{
|
{
|
||||||
FP_API_BASE();
|
FP_API_BASE();
|
||||||
@ -763,7 +793,9 @@ namespace nn
|
|||||||
cafeExportRegisterFunc(GetMyAccountId, "nn_fp", "GetMyAccountId__Q2_2nn2fpFPc", LogType::NN_FP);
|
cafeExportRegisterFunc(GetMyAccountId, "nn_fp", "GetMyAccountId__Q2_2nn2fpFPc", LogType::NN_FP);
|
||||||
cafeExportRegisterFunc(GetMyScreenName, "nn_fp", "GetMyScreenName__Q2_2nn2fpFPw", LogType::NN_FP);
|
cafeExportRegisterFunc(GetMyScreenName, "nn_fp", "GetMyScreenName__Q2_2nn2fpFPw", LogType::NN_FP);
|
||||||
cafeExportRegisterFunc(GetMyMii, "nn_fp", "GetMyMii__Q2_2nn2fpFP12FFLStoreData", LogType::NN_FP);
|
cafeExportRegisterFunc(GetMyMii, "nn_fp", "GetMyMii__Q2_2nn2fpFP12FFLStoreData", LogType::NN_FP);
|
||||||
|
cafeExportRegisterFunc(GetMyPlayingGame, "nn_fp", "GetMyPlayingGame__Q2_2nn2fpFPQ3_2nn2fp7GameKey", LogType::NN_FP);
|
||||||
cafeExportRegisterFunc(GetMyPreference, "nn_fp", "GetMyPreference__Q2_2nn2fpFPQ3_2nn2fp10Preference", LogType::NN_FP);
|
cafeExportRegisterFunc(GetMyPreference, "nn_fp", "GetMyPreference__Q2_2nn2fpFPQ3_2nn2fp10Preference", LogType::NN_FP);
|
||||||
|
cafeExportRegisterFunc(GetMyComment, "nn_fp", "GetMyComment__Q2_2nn2fpFPQ3_2nn2fp7Comment", LogType::NN_FP);
|
||||||
|
|
||||||
cafeExportRegisterFunc(GetFriendAccountId, "nn_fp", "GetFriendAccountId__Q2_2nn2fpFPA17_cPCUiUi", LogType::NN_FP);
|
cafeExportRegisterFunc(GetFriendAccountId, "nn_fp", "GetFriendAccountId__Q2_2nn2fpFPA17_cPCUiUi", LogType::NN_FP);
|
||||||
cafeExportRegisterFunc(GetFriendScreenName, "nn_fp", "GetFriendScreenName__Q2_2nn2fpFPA11_wPCUiUibPUc", LogType::NN_FP);
|
cafeExportRegisterFunc(GetFriendScreenName, "nn_fp", "GetFriendScreenName__Q2_2nn2fpFPA11_wPCUiUibPUc", LogType::NN_FP);
|
||||||
@ -774,6 +806,7 @@ namespace nn
|
|||||||
|
|
||||||
cafeExportRegisterFunc(CheckSettingStatusAsync, "nn_fp", "CheckSettingStatusAsync__Q2_2nn2fpFPUcPFQ2_2nn6ResultPv_vPv", LogType::NN_FP);
|
cafeExportRegisterFunc(CheckSettingStatusAsync, "nn_fp", "CheckSettingStatusAsync__Q2_2nn2fpFPUcPFQ2_2nn6ResultPv_vPv", LogType::NN_FP);
|
||||||
cafeExportRegisterFunc(IsPreferenceValid, "nn_fp", "IsPreferenceValid__Q2_2nn2fpFv", LogType::NN_FP);
|
cafeExportRegisterFunc(IsPreferenceValid, "nn_fp", "IsPreferenceValid__Q2_2nn2fpFv", LogType::NN_FP);
|
||||||
|
cafeExportRegisterFunc(UpdateCommentAsync, "nn_fp", "UpdateCommentAsync__Q2_2nn2fpFPCwPFQ2_2nn6ResultPv_vPv", LogType::NN_FP);
|
||||||
cafeExportRegisterFunc(UpdatePreferenceAsync, "nn_fp", "UpdatePreferenceAsync__Q2_2nn2fpFPCQ3_2nn2fp10PreferencePFQ2_2nn6ResultPv_vPv", LogType::NN_FP);
|
cafeExportRegisterFunc(UpdatePreferenceAsync, "nn_fp", "UpdatePreferenceAsync__Q2_2nn2fpFPCQ3_2nn2fp10PreferencePFQ2_2nn6ResultPv_vPv", LogType::NN_FP);
|
||||||
cafeExportRegisterFunc(GetRequestBlockSettingAsync, "nn_fp", "GetRequestBlockSettingAsync__Q2_2nn2fpFPUcPCUiUiPFQ2_2nn6ResultPv_vPv", LogType::NN_FP);
|
cafeExportRegisterFunc(GetRequestBlockSettingAsync, "nn_fp", "GetRequestBlockSettingAsync__Q2_2nn2fpFPUcPCUiUiPFQ2_2nn6ResultPv_vPv", LogType::NN_FP);
|
||||||
|
|
||||||
|
@ -277,7 +277,8 @@ void NexFriends::handleResponse_getAllInformation(nexServiceResponse_t* response
|
|||||||
}
|
}
|
||||||
NexFriends* session = (NexFriends*)nexFriends;
|
NexFriends* session = (NexFriends*)nexFriends;
|
||||||
session->myPreference = nexPrincipalPreference(&response->data);
|
session->myPreference = nexPrincipalPreference(&response->data);
|
||||||
nexComment comment(&response->data);
|
auto comment = nexComment(&response->data);
|
||||||
|
session->myComment = comment;
|
||||||
if (response->data.hasReadOutOfBounds())
|
if (response->data.hasReadOutOfBounds())
|
||||||
return;
|
return;
|
||||||
// acquire lock on lists
|
// acquire lock on lists
|
||||||
@ -391,6 +392,28 @@ void NexFriends::getMyPreference(nexPrincipalPreference& preference)
|
|||||||
preference = myPreference;
|
preference = myPreference;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NexFriends::updateCommentAsync(nexComment newComment, std::function<void(RpcErrorCode)> cb)
|
||||||
|
{
|
||||||
|
uint8 tempNexBufferArray[1024];
|
||||||
|
nexPacketBuffer packetBuffer(tempNexBufferArray, sizeof(tempNexBufferArray), true);
|
||||||
|
newComment.writeData(&packetBuffer);
|
||||||
|
nexCon->callMethod(
|
||||||
|
NEX_PROTOCOL_FRIENDS_WIIU, 15, &packetBuffer, [this, cb, newComment](nexServiceResponse_t* response) -> void {
|
||||||
|
if (!response->isSuccessful)
|
||||||
|
return cb(NexFriends::ERR_RPC_FAILED);
|
||||||
|
this->myComment = newComment;
|
||||||
|
return cb(NexFriends::ERR_NONE);
|
||||||
|
},
|
||||||
|
true);
|
||||||
|
// TEST
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NexFriends::getMyComment(nexComment& comment)
|
||||||
|
{
|
||||||
|
comment = myComment;
|
||||||
|
}
|
||||||
|
|
||||||
bool NexFriends::addProvisionalFriendByPidGuessed(uint32 principalId)
|
bool NexFriends::addProvisionalFriendByPidGuessed(uint32 principalId)
|
||||||
{
|
{
|
||||||
uint8 tempNexBufferArray[512];
|
uint8 tempNexBufferArray[512];
|
||||||
|
@ -297,7 +297,9 @@ public:
|
|||||||
|
|
||||||
void writeData(nexPacketBuffer* pb) const override
|
void writeData(nexPacketBuffer* pb) const override
|
||||||
{
|
{
|
||||||
cemu_assert_unimplemented();
|
pb->writeU8(ukn0);
|
||||||
|
pb->writeString(commentString.c_str());
|
||||||
|
pb->writeU64(ukn1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void readData(nexPacketBuffer* pb) override
|
void readData(nexPacketBuffer* pb) override
|
||||||
@ -554,6 +556,7 @@ public:
|
|||||||
bool getFriendRequestByMessageId(nexFriendRequest& friendRequestData, bool* isIncoming, uint64 messageId);
|
bool getFriendRequestByMessageId(nexFriendRequest& friendRequestData, bool* isIncoming, uint64 messageId);
|
||||||
bool isOnline();
|
bool isOnline();
|
||||||
void getMyPreference(nexPrincipalPreference& preference);
|
void getMyPreference(nexPrincipalPreference& preference);
|
||||||
|
void getMyComment(nexComment& comment);
|
||||||
|
|
||||||
// asynchronous API (data has to be requested)
|
// asynchronous API (data has to be requested)
|
||||||
bool addProvisionalFriend(char* name, std::function<void(RpcErrorCode)> cb);
|
bool addProvisionalFriend(char* name, std::function<void(RpcErrorCode)> cb);
|
||||||
@ -565,6 +568,7 @@ public:
|
|||||||
void acceptFriendRequest(uint64 messageId, std::function<void(RpcErrorCode)> cb);
|
void acceptFriendRequest(uint64 messageId, std::function<void(RpcErrorCode)> cb);
|
||||||
void deleteFriendRequest(uint64 messageId, std::function<void(RpcErrorCode)> cb); // rejecting incoming friend request (differs from blocking friend requests)
|
void deleteFriendRequest(uint64 messageId, std::function<void(RpcErrorCode)> cb); // rejecting incoming friend request (differs from blocking friend requests)
|
||||||
bool updatePreferencesAsync(const nexPrincipalPreference newPreferences, std::function<void(RpcErrorCode)> cb);
|
bool updatePreferencesAsync(const nexPrincipalPreference newPreferences, std::function<void(RpcErrorCode)> cb);
|
||||||
|
bool updateCommentAsync(const nexComment newComment, std::function<void(RpcErrorCode)> cb);
|
||||||
void updateMyPresence(nexPresenceV2& myPresence);
|
void updateMyPresence(nexPresenceV2& myPresence);
|
||||||
|
|
||||||
void setNotificationHandler(void(*notificationHandler)(NOTIFICATION_TYPE notificationType, uint32 pid));
|
void setNotificationHandler(void(*notificationHandler)(NOTIFICATION_TYPE notificationType, uint32 pid));
|
||||||
@ -619,6 +623,7 @@ private:
|
|||||||
// local friend state
|
// local friend state
|
||||||
nexPresenceV2 myPresence;
|
nexPresenceV2 myPresence;
|
||||||
nexPrincipalPreference myPreference;
|
nexPrincipalPreference myPreference;
|
||||||
|
nexComment myComment;
|
||||||
|
|
||||||
std::recursive_mutex mtx_lists;
|
std::recursive_mutex mtx_lists;
|
||||||
std::vector<nexFriend> list_friends;
|
std::vector<nexFriend> list_friends;
|
||||||
|
Loading…
Reference in New Issue
Block a user