mirror of
https://github.com/cemu-project/Cemu.git
synced 2026-08-23 02:30:29 -05:00
Merge branch 'cemu-project:main' into main
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
project(cemuMain)
|
||||
|
||||
option(CEMU_CXX_FLAGS "Additional flags used for compiling Cemu source code")
|
||||
separate_arguments(CEMU_CXX_FLAGS NATIVE_COMMAND ${CEMU_CXX_FLAGS})
|
||||
if(CEMU_CXX_FLAGS)
|
||||
add_compile_options(${CEMU_CXX_FLAGS})
|
||||
endif()
|
||||
|
||||
@@ -2163,8 +2163,7 @@ void VulkanRenderer::ProcessFinishedCommandBuffers()
|
||||
// not signaled
|
||||
break;
|
||||
}
|
||||
cemuLog_log(LogType::Force, "vkGetFenceStatus returned unexpected error {}", (sint32)fenceStatus);
|
||||
cemu_assert_debug(false);
|
||||
UnrecoverableError(fmt::format("vkGetFenceStatus returned unexpected error {}", (sint32)fenceStatus).c_str());
|
||||
}
|
||||
if (finishedCmdBuffers)
|
||||
{
|
||||
@@ -2183,7 +2182,7 @@ void VulkanRenderer::WaitForNextFinishedCommandBuffer()
|
||||
}
|
||||
else if (result != VK_SUCCESS)
|
||||
{
|
||||
cemuLog_log(LogType::Force, "vkWaitForFences: Returned unhandled error {}", (sint32)result);
|
||||
UnrecoverableError(fmt::format("vkWaitForFences: Returned unhandled error {}", (sint32)result).c_str());
|
||||
}
|
||||
// process
|
||||
ProcessFinishedCommandBuffers();
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace iosu
|
||||
std::atomic_uint64_t m_notificationQueueIndex{1};
|
||||
}g_NotificationQueue;
|
||||
|
||||
struct
|
||||
struct
|
||||
{
|
||||
bool isThreadStarted;
|
||||
bool isInitialized2;
|
||||
@@ -214,12 +214,9 @@ namespace iosu
|
||||
friendData->friendExtraData.gameKey.ukn08 = frd->presence.gameKey.ukn;
|
||||
NexPresenceToGameMode(&frd->presence, &friendData->friendExtraData.gameMode);
|
||||
|
||||
auto fixed_presence_msg = '\0' + frd->presence.msg; // avoid first character of comment from being cut off
|
||||
friendData->friendExtraData.gameModeDescription.assignFromUTF8(fixed_presence_msg);
|
||||
|
||||
auto fixed_comment = '\0' + frd->comment.commentString; // avoid first character of comment from being cut off
|
||||
friendData->friendExtraData.comment.assignFromUTF8(fixed_comment);
|
||||
|
||||
friendData->friendExtraData.gameModeDescription.assignFromUTF8(frd->presence.msg);
|
||||
friendData->friendExtraData.comment.commentString.assignFromUTF8(frd->comment.commentString);
|
||||
|
||||
// set valid dates
|
||||
friendData->uknDate.year = 2018;
|
||||
friendData->uknDate.day = 1;
|
||||
@@ -293,7 +290,7 @@ namespace iosu
|
||||
memset(friendRequest, 0, sizeof(FriendRequest));
|
||||
|
||||
friendRequest->pid = frdReq->principalInfo.principalId;
|
||||
|
||||
|
||||
strncpy((char*)friendRequest->nnid, frdReq->principalInfo.nnid, sizeof(friendRequest->nnid));
|
||||
friendRequest->nnid[sizeof(friendRequest->nnid) - 1] = '\0';
|
||||
|
||||
@@ -723,20 +720,19 @@ namespace iosu
|
||||
{
|
||||
if(numVecIn != 0 || numVecOut != 1)
|
||||
return FPResult_InvalidIPCParam;
|
||||
std::vector<uint16be> myComment;
|
||||
Comment outComment;
|
||||
if(g_fpd.nexFriendSession)
|
||||
{
|
||||
if(vecOut->size != MY_COMMENT_LENGTH * sizeof(uint16be))
|
||||
if(vecOut->size != sizeof(Comment))
|
||||
{
|
||||
cemuLog_log(LogType::Force, "GetMyComment: Unexpected output size");
|
||||
return FPResult_InvalidIPCParam;
|
||||
}
|
||||
nexComment myNexComment;
|
||||
g_fpd.nexFriendSession->getMyComment(myNexComment);
|
||||
myComment = StringHelpers::FromUtf8(myNexComment.commentString);
|
||||
outComment.commentString.assignFromUTF8(myNexComment.commentString);
|
||||
}
|
||||
myComment.insert(myComment.begin(), '\0');
|
||||
memcpy(vecOut->basePhys.GetPtr(), myComment.data(), MY_COMMENT_LENGTH * sizeof(uint16be));
|
||||
memcpy(vecOut->basePhys.GetPtr(), &outComment, sizeof(Comment));
|
||||
return FPResult_Ok;
|
||||
}
|
||||
|
||||
@@ -1166,10 +1162,9 @@ namespace iosu
|
||||
}
|
||||
IPCCommandBody* cmd = ServiceCallDelayCurrentResponse();
|
||||
|
||||
auto utf8_comment = StringHelpers::ToUtf8(newComment, messageLength);
|
||||
nexComment temporaryComment;
|
||||
temporaryComment.ukn0 = 0;
|
||||
temporaryComment.commentString = utf8_comment;
|
||||
temporaryComment.commentString = StringHelpers::ToUtf8(newComment, messageLength-1);
|
||||
temporaryComment.ukn1 = 0;
|
||||
|
||||
g_fpd.nexFriendSession->updateCommentAsync(temporaryComment, [cmd](NexFriends::RpcErrorCode result) {
|
||||
@@ -1456,7 +1451,7 @@ namespace iosu
|
||||
iosu::act::getAccountId(currentSlot, accountId);
|
||||
FFLData_t miiData;
|
||||
act::getMii(currentSlot, &miiData);
|
||||
uint16 screenName[ACT_NICKNAME_LENGTH + 1] = { 0 };
|
||||
uint16 screenName[ACT_NICKNAME_SIZE] = { 0 };
|
||||
act::getScreenname(currentSlot, screenName);
|
||||
uint32 countryCode = 0;
|
||||
act::getCountryIndex(currentSlot, &countryCode);
|
||||
@@ -1488,7 +1483,7 @@ namespace iosu
|
||||
const uint32_t hostIp = ((struct sockaddr_in*)addrs->ai_addr)->sin_addr.s_addr;
|
||||
freeaddrinfo(addrs);
|
||||
g_fpd.mtxFriendSession.lock();
|
||||
g_fpd.nexFriendSession = new NexFriends(hostIp, nexTokenResult.nexToken.port, "ridfebb9", myPid, nexTokenResult.nexToken.nexPassword, nexTokenResult.nexToken.token, accountId, (uint8*)&miiData, (wchar_t*)screenName, (uint8)countryCode, g_fpd.myPresence);
|
||||
g_fpd.nexFriendSession = new NexFriends(hostIp, nexTokenResult.nexToken.port, "ridfebb9", myPid, nexTokenResult.nexToken.nexPassword, nexTokenResult.nexToken.token, accountId, (uint8*)&miiData, screenName, (uint8)countryCode, g_fpd.myPresence);
|
||||
g_fpd.nexFriendSession->setNotificationHandler(NotificationHandler);
|
||||
g_fpd.mtxFriendSession.unlock();
|
||||
cemuLog_log(LogType::Force, "IOSU_FPD: Created friend server session");
|
||||
@@ -1532,4 +1527,3 @@ namespace iosu
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,14 @@ namespace iosu
|
||||
{
|
||||
namespace fpd
|
||||
{
|
||||
static const int RELATIONSHIP_INVALID = 0;
|
||||
static const int RELATIONSHIP_FRIENDREQUEST_OUT = 1;
|
||||
static const int RELATIONSHIP_FRIENDREQUEST_IN = 2;
|
||||
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 MY_COMMENT_LENGTH = 0x11; // includes null-terminator character
|
||||
|
||||
struct FPDDate
|
||||
{
|
||||
/* +0x0 */ uint16be year;
|
||||
@@ -67,6 +75,14 @@ namespace iosu
|
||||
};
|
||||
static_assert(sizeof(GameMode) == 0x2C);
|
||||
|
||||
struct Comment
|
||||
{
|
||||
/* +0x00 */ uint8 unk0;
|
||||
/* +0x01 */ uint8 unk1;
|
||||
/* +0x02 */ CafeWideString<MY_COMMENT_LENGTH> commentString;
|
||||
};
|
||||
static_assert(sizeof(Comment) == 0x24);
|
||||
|
||||
struct FriendData
|
||||
{
|
||||
/* +0x000 */ uint8 type; // type (Non-Zero -> Friend, 0 -> Friend request ? )
|
||||
@@ -83,23 +99,27 @@ namespace iosu
|
||||
// sub struct (the part above seems to be shared with friend requests)
|
||||
union
|
||||
{
|
||||
struct
|
||||
struct
|
||||
{
|
||||
/* +0x0A0 */ Profile profile; // this is returned for nn_fp.GetFriendProfile
|
||||
/* +0x0A4 */ uint32be ukn0A4;
|
||||
/* +0x0A8 */ GameKey gameKey;
|
||||
/* +0x0B8 */ GameMode gameMode;
|
||||
/* +0x0E4 */ CafeWideString<0x82> gameModeDescription;
|
||||
/* +0x0E4 */ uint8 unk0E4;
|
||||
/* +0x0E5 */ uint8 unk0E5;
|
||||
/* +0x0E6 */ CafeWideString<GAMEMODE_MAX_MESSAGE_LENGTH> gameModeDescription;
|
||||
/* +0x1E6 */ uint8 unk1E6;
|
||||
/* +0x1E7 */ uint8 unk1E7;
|
||||
/* +0x1E8 */ Profile profile1E8; // how does it differ from the one at 0xA0? Returned by GetFriendPresence
|
||||
/* +0x1EC */ uint8 isOnline;
|
||||
/* +0x1ED */ uint8 _padding1ED[3];
|
||||
// some other sub struct?
|
||||
/* +0x1F0 */ CafeWideString<0x12> comment; // pops up every few seconds in friend list
|
||||
/* +0x1F0 */ Comment comment; // pops up every few seconds in friend list
|
||||
/* +0x214 */ uint32be _padding214;
|
||||
/* +0x218 */ FPDDate approvalTime;
|
||||
/* +0x220 */ FPDDate lastOnline;
|
||||
}friendExtraData;
|
||||
struct
|
||||
struct
|
||||
{
|
||||
/* +0x0A0 */ uint64be messageId; // guessed. If 0, then relationship is FRIENDSHIP_REQUEST_OUT, otherwise FRIENDSHIP_REQUEST_IN
|
||||
/* +0x0A8 */ uint8 ukn0A8;
|
||||
@@ -118,9 +138,9 @@ namespace iosu
|
||||
};
|
||||
static_assert(sizeof(FriendData) == 0x228);
|
||||
static_assert(offsetof(FriendData, friendExtraData.gameKey) == 0x0A8);
|
||||
static_assert(offsetof(FriendData, friendExtraData.gameModeDescription) == 0x0E4);
|
||||
static_assert(offsetof(FriendData, friendExtraData.gameModeDescription) == 0x0E6);
|
||||
static_assert(offsetof(FriendData, friendExtraData.comment) == 0x1F0);
|
||||
|
||||
|
||||
static_assert(offsetof(FriendData, requestExtraData.messageId) == 0x0A0);
|
||||
static_assert(offsetof(FriendData, requestExtraData.comment) == 0x0AA);
|
||||
static_assert(offsetof(FriendData, requestExtraData.uknMessage) == 0x12C);
|
||||
@@ -206,14 +226,6 @@ namespace iosu
|
||||
};
|
||||
static_assert(sizeof(FPDPreference) == 4);
|
||||
|
||||
static const int RELATIONSHIP_INVALID = 0;
|
||||
static const int RELATIONSHIP_FRIENDREQUEST_OUT = 1;
|
||||
static const int RELATIONSHIP_FRIENDREQUEST_IN = 2;
|
||||
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 MY_COMMENT_LENGTH = 0x12;
|
||||
|
||||
enum class FPD_REQUEST_ID
|
||||
{
|
||||
LoginAsync = 0x2775,
|
||||
|
||||
@@ -273,6 +273,13 @@ bool RPLLoader_ProcessHeaders(std::string_view moduleName, uint8* rplData, uint3
|
||||
// init modulename
|
||||
rplLoaderContext->moduleName.assign(moduleName);
|
||||
|
||||
std::string fileName{moduleName};
|
||||
fileName.append(rplLoaderContext->IsRPX() ? ".rpx" : ".rpl");
|
||||
|
||||
// allocate modulename in PPC memory
|
||||
rplLoaderContext->ppcName = coreinit_allocFromSysArea(fileName.size() + 1, 4);
|
||||
memcpy(rplLoaderContext->ppcName.GetPtr(), fileName.data(), fileName.size() + 1);
|
||||
|
||||
// load CRC section
|
||||
uint32 crcTableExpectedSize = sectionCount * sizeof(uint32be);
|
||||
if (!RPLLoader_CheckBounds(rplLoaderContext, crcSection->fileOffset, crcTableExpectedSize))
|
||||
@@ -2070,6 +2077,18 @@ uint32 RPLLoader_GetHandleByModuleName(const char* name)
|
||||
return RPL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
const std::string RPLLoader_GetModuleNameByHandle(uint32 handle)
|
||||
{
|
||||
for (auto& dep : rplDependencyList)
|
||||
{
|
||||
if (dep->coreinitHandle == handle)
|
||||
return dep->moduleName;
|
||||
}
|
||||
|
||||
return "";
|
||||
|
||||
}
|
||||
|
||||
uint32 RPLLoader_GetMaxTLSModuleIndex()
|
||||
{
|
||||
return rplLoader_currentTlsModuleIndex - 1;
|
||||
@@ -2381,6 +2400,20 @@ RPLModule** RPLLoader_GetModuleList()
|
||||
return rplModuleList;
|
||||
}
|
||||
|
||||
RPLModule* RPLLoader_GetModuleByName(std::string_view name)
|
||||
{
|
||||
std::string normalizedName = _RPLLoader_ExtractModuleNameFromPath(name);
|
||||
RPLModule** modules = RPLLoader_GetModuleList();
|
||||
|
||||
for (uint32 i = 0; i < RPLLoader_GetModuleCount(); i++)
|
||||
{
|
||||
if (modules[i]->moduleName == normalizedName)
|
||||
return modules[i];
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sint32 RPLLoader_GetModuleCount()
|
||||
{
|
||||
return rplModuleCount;
|
||||
|
||||
@@ -36,6 +36,7 @@ void RPLLoader_UpdateDependencies();
|
||||
void RPLLoader_LoadCoreinit();
|
||||
|
||||
uint32 RPLLoader_GetHandleByModuleName(const char* name);
|
||||
const std::string RPLLoader_GetModuleNameByHandle(uint32 handle);
|
||||
uint32 RPLLoader_GetMaxTLSModuleIndex();
|
||||
bool RPLLoader_GetTLSDataByTLSIndex(sint16 tlsModuleIndex, uint8** tlsData, sint32* tlsSize);
|
||||
|
||||
@@ -46,6 +47,7 @@ uint32 RPLLoader_GetSDA2Base();
|
||||
|
||||
sint32 RPLLoader_GetModuleCount();
|
||||
RPLModule** RPLLoader_GetModuleList();
|
||||
RPLModule* RPLLoader_GetModuleByName(std::string_view name);
|
||||
|
||||
MEMPTR<void> RPLLoader_AllocateCodeCaveMem(uint32 alignment, uint32 size);
|
||||
void RPLLoader_ReleaseCodeCaveMem(MEMPTR<void> addr);
|
||||
|
||||
@@ -156,6 +156,7 @@ struct RPLModule
|
||||
MEMPTR<void> regionMappingBase_text; // base destination address for text region
|
||||
MPTR regionMappingBase_data; // base destination address for data region
|
||||
MPTR regionMappingBase_loaderInfo; // base destination address for loaderInfo region
|
||||
MEMPTR<char> ppcName; // name of the module in PPC memory
|
||||
uint8* tempRegionPtr;
|
||||
uint32 tempRegionAllocSize;
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "Cafe/OS/common/OSCommon.h"
|
||||
#include "Cafe/HW/Espresso/PPCCallback.h"
|
||||
#include "Cafe/OS/RPL/rpl.h"
|
||||
#include "Cafe/OS/RPL/rpl_structs.h"
|
||||
#include "Cafe/OS/libs/coreinit/coreinit_DynLoad.h"
|
||||
#include "Cafe/OS/libs/coreinit/coreinit_MEM.h"
|
||||
|
||||
@@ -11,6 +12,8 @@ namespace coreinit
|
||||
MPTR _osDynLoadTLSFuncAlloc = MPTR_NULL;
|
||||
MPTR _osDynLoadTLSFuncFree = MPTR_NULL;
|
||||
|
||||
static std::vector<NotifyCallbackEntry> notifyCallbacks;
|
||||
|
||||
uint32 OSDynLoad_SetAllocator(MPTR allocFunc, MPTR freeFunc)
|
||||
{
|
||||
_osDynLoadFuncAlloc = allocFunc;
|
||||
@@ -108,6 +111,34 @@ namespace coreinit
|
||||
cemuLog_logDebug(LogType::Force, "OSDynLoad_Acquire() failed to load module '{}'", libName);
|
||||
return 0xFFFCFFE9; // module not found
|
||||
}
|
||||
|
||||
for (const auto& cb : notifyCallbacks)
|
||||
{
|
||||
MEMPTR<OSDynLoad_NotifyData> notifyData;
|
||||
notifyData = (OSDynLoad_NotifyData*)OSDynLoad_AllocatorAlloc(sizeof(OSDynLoad_NotifyData), 4);
|
||||
RPLModule* module = RPLLoader_GetModuleByName(tempLibName);
|
||||
|
||||
if (!module)
|
||||
break;
|
||||
|
||||
notifyData->name = module->ppcName.GetMPTR();
|
||||
|
||||
notifyData->textAddr = module->regionMappingBase_text.GetBEValue();
|
||||
notifyData->textOffset = module->regionMappingBase_text.GetMPTR() - module->regionOrigAddr_text;
|
||||
notifyData->textSize = module->regionSize_text;
|
||||
|
||||
notifyData->dataAddr = module->regionMappingBase_data;
|
||||
notifyData->dataOffset = module->regionMappingBase_data - module->regionOrigAddr_data;
|
||||
notifyData->dataSize = module->regionSize_data;
|
||||
|
||||
notifyData->readAddr = module->regionMappingBase_data;
|
||||
notifyData->readOffset = module->regionMappingBase_data - module->regionOrigAddr_data;
|
||||
notifyData->readSize = module->regionSize_data;
|
||||
|
||||
PPCCoreCallback(cb.callback, moduleHandleOut, cb.userContext.GetMPTR(), 1, notifyData.GetMPTR());
|
||||
OSDynLoad_AllocatorFree(notifyData);
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -120,6 +151,35 @@ namespace coreinit
|
||||
{
|
||||
if (moduleHandle == RPL_INVALID_HANDLE)
|
||||
return;
|
||||
|
||||
for (const auto& cb : notifyCallbacks)
|
||||
{
|
||||
MEMPTR<OSDynLoad_NotifyData> notifyData;
|
||||
notifyData = (OSDynLoad_NotifyData*)OSDynLoad_AllocatorAlloc(sizeof(OSDynLoad_NotifyData), 4);
|
||||
RPLModule* module = RPLLoader_GetModuleByName(RPLLoader_GetModuleNameByHandle(moduleHandle));
|
||||
|
||||
if (!module)
|
||||
break;
|
||||
|
||||
notifyData->name = module->ppcName.GetMPTR();
|
||||
|
||||
notifyData->textAddr = module->regionMappingBase_text.GetBEValue();
|
||||
notifyData->textOffset = module->regionMappingBase_text.GetMPTR() - module->regionOrigAddr_text;
|
||||
notifyData->textSize = module->regionSize_text;
|
||||
|
||||
notifyData->dataAddr = module->regionMappingBase_data;
|
||||
notifyData->dataOffset = module->regionMappingBase_data - module->regionOrigAddr_data;
|
||||
notifyData->dataSize = module->regionSize_data;
|
||||
|
||||
notifyData->readAddr = module->regionMappingBase_data;
|
||||
notifyData->readOffset = module->regionMappingBase_data - module->regionOrigAddr_data;
|
||||
notifyData->readSize = module->regionSize_data;
|
||||
|
||||
PPCCoreCallback(cb.callback, moduleHandle, cb.userContext.GetMPTR(), 2, notifyData.GetMPTR());
|
||||
OSDynLoad_AllocatorFree(notifyData);
|
||||
|
||||
}
|
||||
|
||||
RPLLoader_RemoveDependency(moduleHandle);
|
||||
RPLLoader_UpdateDependencies();
|
||||
}
|
||||
@@ -146,6 +206,73 @@ namespace coreinit
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 OSDynLoad_GetModuleName(uint32 moduleHandle, char* nameBuf, sint32be* nameBufSize)
|
||||
{
|
||||
if (moduleHandle == 0xFFFFFFFF)
|
||||
{
|
||||
// main module
|
||||
// Assassins Creed 4 has this handle hardcoded
|
||||
moduleHandle = RPLLoader_GetMainModuleHandle();
|
||||
}
|
||||
|
||||
const std::string moduleName = RPLLoader_GetModuleNameByHandle(moduleHandle);
|
||||
std::strncpy(nameBuf, moduleName.c_str(), *nameBufSize);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
sint32 OSDynLoad_GetNumberOfRPLs()
|
||||
{
|
||||
return RPLLoader_GetModuleCount();
|
||||
}
|
||||
|
||||
uint32 OSDynLoad_GetRPLInfo(uint32 first, uint32 count, OSDynLoad_NotifyData* outInfos)
|
||||
{
|
||||
if (count == 0)
|
||||
return 1;
|
||||
RPLModule** modules = RPLLoader_GetModuleList();
|
||||
|
||||
for (uint32 i = first; i < count; i++)
|
||||
{
|
||||
outInfos[i].name = modules[i]->ppcName.GetMPTR();
|
||||
|
||||
outInfos[i].textAddr = modules[i]->regionMappingBase_text.GetBEValue();
|
||||
outInfos[i].textOffset = modules[i]->regionMappingBase_text.GetMPTR() - modules[i]->regionOrigAddr_text;
|
||||
outInfos[i].textSize = modules[i]->regionSize_text;
|
||||
|
||||
outInfos[i].dataAddr = modules[i]->regionMappingBase_data;
|
||||
outInfos[i].dataOffset = modules[i]->regionMappingBase_data - modules[i]->regionOrigAddr_data;
|
||||
outInfos[i].dataSize = modules[i]->regionSize_data;
|
||||
|
||||
outInfos[i].readAddr = modules[i]->regionMappingBase_data;
|
||||
outInfos[i].readOffset = modules[i]->regionMappingBase_data - modules[i]->regionOrigAddr_data;
|
||||
outInfos[i].readSize = modules[i]->regionSize_data;
|
||||
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32 OSDynLoad_AddNotifyCallback(MEMPTR<OSDynLoadNotifyFunc> notifyFn, MEMPTR<void> userContext)
|
||||
{
|
||||
if (!notifyFn)
|
||||
return 0xBAD1000E; // notify function pointer is null
|
||||
|
||||
notifyCallbacks.emplace_back(notifyFn, userContext);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 OSDynLoad_DelNotifyCallback(MEMPTR<OSDynLoadNotifyFunc> notifyFn, MEMPTR<void> userContext)
|
||||
{
|
||||
std::erase_if(notifyCallbacks, [&](const NotifyCallbackEntry& entry)
|
||||
{
|
||||
return entry.callback.GetMPTR() == notifyFn.GetMPTR() && entry.userContext == userContext;
|
||||
});
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void InitializeDynLoad()
|
||||
{
|
||||
cafeExportRegister("coreinit", OSDynLoad_SetAllocator, LogType::Placeholder);
|
||||
@@ -157,5 +284,11 @@ namespace coreinit
|
||||
cafeExportRegister("coreinit", OSDynLoad_Release, LogType::Placeholder);
|
||||
cafeExportRegister("coreinit", OSDynLoad_IsModuleLoaded, LogType::Placeholder);
|
||||
cafeExportRegister("coreinit", OSDynLoad_FindExport, LogType::Placeholder);
|
||||
cafeExportRegister("coreinit", OSDynLoad_GetModuleName, LogType::Placeholder);
|
||||
cafeExportRegister("coreinit", OSDynLoad_GetNumberOfRPLs, LogType::Placeholder);
|
||||
cafeExportRegister("coreinit", OSDynLoad_GetRPLInfo, LogType::Placeholder);
|
||||
|
||||
cafeExportRegister("coreinit", OSDynLoad_AddNotifyCallback, LogType::Placeholder);
|
||||
cafeExportRegister("coreinit", OSDynLoad_DelNotifyCallback, LogType::Placeholder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,33 @@
|
||||
|
||||
namespace coreinit
|
||||
{
|
||||
struct OSDynLoad_NotifyData
|
||||
{
|
||||
MEMPTR<char> name;
|
||||
|
||||
uint32be textAddr;
|
||||
uint32be textOffset;
|
||||
uint32be textSize;
|
||||
|
||||
uint32be dataAddr;
|
||||
uint32be dataOffset;
|
||||
uint32be dataSize;
|
||||
|
||||
uint32be readAddr;
|
||||
uint32be readOffset;
|
||||
uint32be readSize;
|
||||
};
|
||||
|
||||
using OSDynLoadNotifyFunc = void (*)(uint32be* module, void *userContext, sint32 notifyReason, OSDynLoad_NotifyData *infos);
|
||||
|
||||
struct NotifyCallbackEntry
|
||||
{
|
||||
MEMPTR<OSDynLoadNotifyFunc> callback;
|
||||
MEMPTR<void> userContext;
|
||||
|
||||
NotifyCallbackEntry(MEMPTR<OSDynLoadNotifyFunc> func, MEMPTR<void> context) : callback(func), userContext(context) {}
|
||||
};
|
||||
|
||||
uint32 OSDynLoad_SetAllocator(MPTR allocFunc, MPTR freeFunc);
|
||||
void OSDynLoad_SetTLSAllocator(MPTR allocFunc, MPTR freeFunc);
|
||||
uint32 OSDynLoad_GetAllocator(betype<MPTR>* funcAlloc, betype<MPTR>* funcFree);
|
||||
@@ -14,5 +41,12 @@ namespace coreinit
|
||||
void OSDynLoad_Release(uint32 moduleHandle);
|
||||
uint32 OSDynLoad_FindExport(uint32 moduleHandle, uint32 isData, const char* exportName, betype<MPTR>* addrOut);
|
||||
|
||||
uint32 OSDynLoad_GetModuleName(uint32 moduleHandle, char* nameBuf, sint32be* nameBufSize);
|
||||
sint32 OSDynLoad_GetNumberOfRPLs();
|
||||
uint32 OSDynLoad_GetRPLInfo(uint32 first, uint32 count, OSDynLoad_NotifyData* outInfos);
|
||||
|
||||
uint32 OSDynLoad_AddNotifyCallback(MEMPTR<OSDynLoadNotifyFunc> notifyFn, MEMPTR<void> userContext);
|
||||
uint32 OSDynLoad_DelNotifyCallback(MEMPTR<OSDynLoadNotifyFunc> notifyFn, MEMPTR<void> userContext);
|
||||
|
||||
void InitializeDynLoad();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -484,7 +484,7 @@ namespace nn
|
||||
{
|
||||
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));
|
||||
ipcCtx->AddOutput(myComment, sizeof(iosu::fpd::Comment));
|
||||
return ipcCtx->Submit(std::move(ipcCtx));
|
||||
}
|
||||
|
||||
@@ -627,13 +627,13 @@ namespace nn
|
||||
{
|
||||
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)
|
||||
uint32 commentLen = CafeStringHelpers::Length(newComment, iosu::fpd::MY_COMMENT_LENGTH);
|
||||
if (commentLen >= iosu::fpd::MY_COMMENT_LENGTH)
|
||||
{
|
||||
cemuLog_log(LogType::Force, "UpdateCommentAsync: message too long");
|
||||
return FPResult_InvalidIPCParam;
|
||||
}
|
||||
ipcCtx->AddInput(newComment, sizeof(uint16be) * commentLen + 2);
|
||||
ipcCtx->AddInput(newComment, sizeof(uint16be) * (commentLen + 1));
|
||||
return ipcCtx->SubmitAsync(std::move(ipcCtx), funcPtr, customParam);
|
||||
}
|
||||
|
||||
@@ -840,4 +840,3 @@ namespace nn
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#include "Cafe/IOSU/legacy/iosu_act.h"
|
||||
#include "prudp.h"
|
||||
#include "nex.h"
|
||||
#include "nexFriends.h"
|
||||
#include "Cafe/CafeSystem.h"
|
||||
#include "util/helpers/StringHelpers.h"
|
||||
|
||||
static const int NOTIFICATION_SRV_FRIEND_OFFLINE = 0x0A; // the opposite event (friend online) is notified via _PRESENCE_CHANGE
|
||||
static const int NOTIFICATION_SRV_FRIEND_PRESENCE_CHANGE = 0x18;
|
||||
@@ -195,7 +197,7 @@ void nexFriends_protocolNotification_processRequest(nexServiceRequest_t* request
|
||||
request->nex->sendRequestResponse(request, 0x80000000, nullptr, 0);
|
||||
}
|
||||
|
||||
NexFriends::NexFriends(uint32 authServerIp, uint16 authServerPort, const char* accessKey, uint32 pid, const char* nexPassword, const char* nexToken, const char* nnid, uint8* miiData, const wchar_t* miiNickname, uint8 countryCode, nexPresenceV2& myPresence)
|
||||
NexFriends::NexFriends(uint32 authServerIp, uint16 authServerPort, const char* accessKey, uint32 pid, const char* nexPassword, const char* nexToken, const char* nnid, uint8* miiData, const uint16* miiNickname, uint8 countryCode, nexPresenceV2& myPresence)
|
||||
: nexCon(nullptr)
|
||||
{
|
||||
memcpy(this->miiData, miiData, FFL_SIZE);
|
||||
@@ -203,7 +205,7 @@ NexFriends::NexFriends(uint32 authServerIp, uint16 authServerPort, const char* a
|
||||
this->pid = pid;
|
||||
this->countryCode = countryCode;
|
||||
this->myPresence = myPresence;
|
||||
this->miiNickname = boost::nowide::narrow(miiNickname);
|
||||
this->miiNickname = StringHelpers::ToUtf8FromLE(miiNickname, ACT_NICKNAME_LENGTH);
|
||||
cemu_assert_debug(this->miiNickname.size() <= 96-1);
|
||||
auth.serverIp = authServerIp;
|
||||
auth.port = authServerPort;
|
||||
@@ -511,7 +513,7 @@ void NexFriends::trackNotifications()
|
||||
{
|
||||
bool entryFound = false;
|
||||
for (auto& frqNew : list_friendReqIncoming)
|
||||
{
|
||||
{
|
||||
if (frqNew.principalInfo.principalId == frqPrevious.principalInfo.principalId)
|
||||
{
|
||||
entryFound = true;
|
||||
|
||||
@@ -264,7 +264,7 @@ public:
|
||||
pb->writeU8(showGame);
|
||||
pb->writeU8(blockFriendRequests);
|
||||
}
|
||||
|
||||
|
||||
void readData(nexPacketBuffer* pb) override
|
||||
{
|
||||
showOnline = pb->readU8();
|
||||
@@ -537,7 +537,7 @@ public:
|
||||
};
|
||||
|
||||
public:
|
||||
NexFriends(uint32 authServerIp, uint16 authServerPort, const char* accessKey, uint32 pid, const char* nexPassword, const char* nexToken, const char* nnid, uint8* miiData, const wchar_t* miiNickname, uint8 countryCode, nexPresenceV2& myPresence);
|
||||
NexFriends(uint32 authServerIp, uint16 authServerPort, const char* accessKey, uint32 pid, const char* nexPassword, const char* nexToken, const char* nnid, uint8* miiData, const uint16* miiNickname, uint8 countryCode, nexPresenceV2& myPresence);
|
||||
|
||||
~NexFriends();
|
||||
|
||||
@@ -586,7 +586,7 @@ private:
|
||||
|
||||
void generateNotification(NOTIFICATION_TYPE notificationType, uint32 pid);
|
||||
void trackNotifications();
|
||||
|
||||
|
||||
// notification-service handlers
|
||||
void processServerNotification_friendOffline(uint32 pid);
|
||||
void processServerNotification_presenceChange(uint32 pid, nexPresenceV2& presence);
|
||||
@@ -612,7 +612,7 @@ private:
|
||||
uint32 numFailedLogins;
|
||||
uint32 numSuccessfulLogins;
|
||||
// auth
|
||||
struct
|
||||
struct
|
||||
{
|
||||
uint32 serverIp;
|
||||
uint16 port;
|
||||
@@ -629,7 +629,7 @@ private:
|
||||
std::vector<nexFriend> list_friends;
|
||||
std::vector<nexFriendRequest> list_friendReqOutgoing;
|
||||
std::vector<nexFriendRequest> list_friendReqIncoming;
|
||||
struct
|
||||
struct
|
||||
{
|
||||
std::vector<nexFriend> list_friends;
|
||||
std::vector<nexFriendRequest> list_friendReqOutgoing;
|
||||
|
||||
@@ -110,6 +110,20 @@ namespace StringHelpers
|
||||
return ToUtf8(input.data(), input.size());
|
||||
}
|
||||
|
||||
// convert little-endian wide string to utf8 string
|
||||
static std::string ToUtf8FromLE(const uint16* ptr, size_t maxLength)
|
||||
{
|
||||
std::wstringstream result;
|
||||
while (*ptr != 0 && maxLength > 0)
|
||||
{
|
||||
auto c = (uint16)*ptr;
|
||||
result << static_cast<wchar_t>(c);
|
||||
ptr++;
|
||||
maxLength--;
|
||||
}
|
||||
return boost::nowide::narrow(result.str());
|
||||
}
|
||||
|
||||
// convert utf8 string to Wii U big-endian wchar_t string
|
||||
static std::vector<uint16be> FromUtf8(std::string_view str)
|
||||
{
|
||||
@@ -285,4 +299,3 @@ namespace StringHelpers
|
||||
std::string_view m_str;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user