nn_fp: Full rework of friend service

This commit is contained in:
Exzap
2023-10-17 05:26:30 +02:00
parent 13a50a915e
commit 0d71885c88
37 changed files with 2862 additions and 1991 deletions
+19 -5
View File
@@ -526,6 +526,13 @@ namespace CafeSystem
cemuLog_log(LogType::Force, "Platform: {}", platform);
}
static std::vector<IOSUModule*> s_iosuModules =
{
// entries in this list are ordered by initialization order. Shutdown in reverse order
iosu::kernel::GetModule(),
iosu::fpd::GetModule()
};
// initialize all subsystems which are persistent and don't depend on a game running
void Initialize()
{
@@ -550,14 +557,15 @@ namespace CafeSystem
// allocate memory for all SysAllocators
// must happen before COS module init, but also before iosu::kernel::Initialize()
SysAllocatorContainer::GetInstance().Initialize();
// init IOSU
// init IOSU modules
for(auto& module : s_iosuModules)
module->SystemLaunch();
// init IOSU (deprecated manual init)
iosuCrypto_init();
iosu::kernel::Initialize();
iosu::fsa::Initialize();
iosuIoctl_init();
iosuAct_init_depr();
iosu::act::Initialize();
iosu::fpd::Initialize();
iosu::iosuMcp_init();
iosu::mcp::Init();
iosu::iosuAcp_init();
@@ -593,11 +601,14 @@ namespace CafeSystem
// if a title is running, shut it down
if (sSystemRunning)
ShutdownTitle();
// shutdown persistent subsystems
// shutdown persistent subsystems (deprecated manual shutdown)
iosu::odm::Shutdown();
iosu::act::Stop();
iosu::mcp::Shutdown();
iosu::fsa::Shutdown();
// shutdown IOSU modules
for(auto it = s_iosuModules.rbegin(); it != s_iosuModules.rend(); ++it)
(*it)->SystemExit();
s_initialized = false;
}
@@ -821,7 +832,8 @@ namespace CafeSystem
void _LaunchTitleThread()
{
// init
for(auto& module : s_iosuModules)
module->TitleStart();
cemu_initForGame();
// enter scheduler
if (ActiveSettings::GetCPUMode() == CPUMode::MulticoreRecompiler)
@@ -956,6 +968,8 @@ namespace CafeSystem
nn::save::ResetToDefaultState();
coreinit::__OSDeleteAllActivePPCThreads();
RPLLoader_ResetState();
for(auto it = s_iosuModules.rbegin(); it != s_iosuModules.rend(); ++it)
(*it)->TitleStop();
// stop time tracking
iosu::pdm::Stop();
// reset Cemu subsystems
@@ -19,7 +19,7 @@ void PPCInterpreter_handleUnsupportedHLECall(PPCInterpreter_t* hCPU)
std::vector<void(*)(PPCInterpreter_t* hCPU)>* sPPCHLETable{};
HLEIDX PPCInterpreter_registerHLECall(HLECALL hleCall)
HLEIDX PPCInterpreter_registerHLECall(HLECALL hleCall, std::string hleName)
{
if (!sPPCHLETable)
sPPCHLETable = new std::vector<void(*)(PPCInterpreter_t* hCPU)>();
+1 -1
View File
@@ -230,7 +230,7 @@ static inline float flushDenormalToZero(float f)
typedef void(*HLECALL)(PPCInterpreter_t* hCPU);
typedef sint32 HLEIDX;
HLEIDX PPCInterpreter_registerHLECall(HLECALL hleCall);
HLEIDX PPCInterpreter_registerHLECall(HLECALL hleCall, std::string hleName);
HLECALL PPCInterpreter_getHLECall(HLEIDX funcIndex);
// HLE scheduler
+13 -1
View File
@@ -1,6 +1,9 @@
#pragma once
using IOSMsgQueueId = uint32;
using IOSTimerId = uint32;
static constexpr IOSTimerId IOSInvalidTimerId = 0xFFFFFFFF;
// returned for syscalls
// maybe also shared with IPC?
@@ -19,4 +22,13 @@ enum IOS_ERROR : sint32
inline bool IOS_ResultIsError(const IOS_ERROR err)
{
return (err & 0x80000000) != 0;
}
}
class IOSUModule
{
public:
virtual void SystemLaunch() {}; // CafeSystem is initialized
virtual void SystemExit() {}; // CafeSystem is shutdown
virtual void TitleStart() {}; // foreground title is launched
virtual void TitleStop() {}; // foreground title is closed
};
+226 -6
View File
@@ -1,6 +1,8 @@
#include "iosu_kernel.h"
#include "util/helpers/fspinlock.h"
#include "util/helpers/helpers.h"
#include "Cafe/OS/libs/coreinit/coreinit_IPC.h"
#include "util/highresolutiontimer/HighResolutionTimer.h"
namespace iosu
{
@@ -8,6 +10,9 @@ namespace iosu
{
std::mutex sInternalMutex;
void IOS_DestroyResourceManagerForQueueId(IOSMsgQueueId msgQueueId);
void _IPCDestroyAllHandlesForMsgQueue(IOSMsgQueueId msgQueueId);
static void _assume_lock()
{
#ifdef CEMU_DEBUG_ASSERT
@@ -84,6 +89,19 @@ namespace iosu
return queueHandle;
}
IOS_ERROR IOS_DestroyMessageQueue(IOSMsgQueueId msgQueueId)
{
std::unique_lock _l(sInternalMutex);
IOSMessageQueue* msgQueue = nullptr;
IOS_ERROR r = _IOS_GetMessageQueue(msgQueueId, msgQueue);
if (r != IOS_ERROR_OK)
return r;
msgQueue->msgArraySize = 0;
msgQueue->queueHandle = 0;
IOS_DestroyResourceManagerForQueueId(msgQueueId);
return IOS_ERROR_OK;
}
IOS_ERROR IOS_SendMessage(IOSMsgQueueId msgQueueId, IOSMessage message, uint32 flags)
{
std::unique_lock _l(sInternalMutex);
@@ -146,6 +164,133 @@ namespace iosu
return IOS_ERROR_OK;
}
/* timer */
std::mutex sTimerMutex;
std::condition_variable sTimerCV;
std::atomic_bool sTimerThreadStop;
struct IOSTimer
{
IOSMsgQueueId queueId;
uint32 message;
HRTick nextFire;
HRTick repeat;
bool isValid;
};
std::vector<IOSTimer> sTimers;
std::vector<IOSTimerId> sTimersFreeHandles;
auto sTimerSortComparator = [](const IOSTimerId& idA, const IOSTimerId& idB)
{
// order by nextFire, then by timerId to avoid duplicate keys
IOSTimer& timerA = sTimers[idA];
IOSTimer& timerB = sTimers[idB];
if (timerA.nextFire != timerB.nextFire)
return timerA.nextFire < timerB.nextFire;
return idA < idB;
};
std::set<IOSTimerId, decltype(sTimerSortComparator)> sTimerByFireTime;
IOSTimer& IOS_GetFreeTimer()
{
cemu_assert_debug(!sTimerMutex.try_lock()); // lock must be held by current thread
if (sTimersFreeHandles.empty())
return sTimers.emplace_back();
IOSTimerId timerId = sTimersFreeHandles.back();
sTimersFreeHandles.pop_back();
return sTimers[timerId];
}
void IOS_TimerSetNextFireTime(IOSTimer& timer, HRTick nextFire)
{
cemu_assert_debug(!sTimerMutex.try_lock()); // lock must be held by current thread
IOSTimerId timerId = &timer - sTimers.data();
auto it = sTimerByFireTime.find(timerId);
if(it != sTimerByFireTime.end())
sTimerByFireTime.erase(it);
timer.nextFire = nextFire;
if(nextFire != 0)
sTimerByFireTime.insert(timerId);
}
void IOS_StopTimerInternal(IOSTimerId timerId)
{
cemu_assert_debug(!sTimerMutex.try_lock());
IOS_TimerSetNextFireTime(sTimers[timerId], 0);
}
IOS_ERROR IOS_CreateTimer(uint32 startMicroseconds, uint32 repeatMicroseconds, uint32 queueId, uint32 message)
{
std::unique_lock _l(sTimerMutex);
IOSTimer& timer = IOS_GetFreeTimer();
timer.queueId = queueId;
timer.message = message;
HRTick nextFire = HighResolutionTimer::now().getTick() + HighResolutionTimer::microsecondsToTicks(startMicroseconds);
timer.repeat = HighResolutionTimer::microsecondsToTicks(repeatMicroseconds);
IOS_TimerSetNextFireTime(timer, nextFire);
timer.isValid = true;
sTimerCV.notify_one();
return (IOS_ERROR)(&timer - sTimers.data());
}
IOS_ERROR IOS_StopTimer(IOSTimerId timerId)
{
std::unique_lock _l(sTimerMutex);
if (timerId >= sTimers.size() || !sTimers[timerId].isValid)
return IOS_ERROR_INVALID;
IOS_StopTimerInternal(timerId);
return IOS_ERROR_OK;
}
IOS_ERROR IOS_DestroyTimer(IOSTimerId timerId)
{
std::unique_lock _l(sTimerMutex);
if (timerId >= sTimers.size() || !sTimers[timerId].isValid)
return IOS_ERROR_INVALID;
IOS_StopTimerInternal(timerId);
sTimers[timerId].isValid = false;
sTimersFreeHandles.push_back(timerId);
return IOS_ERROR_OK;
}
void IOSTimerThread()
{
SetThreadName("IOS-Timer");
std::unique_lock _l(sTimerMutex);
while (!sTimerThreadStop)
{
if (sTimerByFireTime.empty())
{
sTimerCV.wait_for(_l, std::chrono::milliseconds(10000));
continue;
}
IOSTimerId timerId = *sTimerByFireTime.begin();
IOSTimer& timer = sTimers[timerId];
HRTick now = HighResolutionTimer::now().getTick();
if (now >= timer.nextFire)
{
if(timer.repeat == 0)
IOS_TimerSetNextFireTime(timer, 0);
else
IOS_TimerSetNextFireTime(timer, timer.nextFire + timer.repeat);
IOSMsgQueueId queueId = timer.queueId;
uint32 message = timer.message;
// fire timer
_l.unlock();
IOSMessage msg;
IOS_SendMessage(queueId, message, 1);
_l.lock();
continue;
}
else
{
sTimerCV.wait_for(_l, std::chrono::microseconds(HighResolutionTimer::ticksToMicroseconds(timer.nextFire - now)));
}
}
}
/* devices and IPC */
struct IOSResourceManager
@@ -209,6 +354,23 @@ namespace iosu
return IOS_ERROR_OK;
}
void IOS_DestroyResourceManagerForQueueId(IOSMsgQueueId msgQueueId)
{
_assume_lock();
// destroy all IPC handles associated with this queue
_IPCDestroyAllHandlesForMsgQueue(msgQueueId);
// destroy device resource manager
for (auto& it : sDeviceResources)
{
if (it.isSet && it.msgQueueId == msgQueueId)
{
it.isSet = false;
it.path.clear();
it.msgQueueId = 0;
}
}
}
IOS_ERROR IOS_DeviceAssociateId(const char* devicePath, uint32 id)
{
// not yet implemented
@@ -344,6 +506,22 @@ namespace iosu
return IOS_ERROR_OK;
}
void _IPCDestroyAllHandlesForMsgQueue(IOSMsgQueueId msgQueueId)
{
_assume_lock();
for (auto& it : sActiveDeviceHandles)
{
if (it.isSet && it.msgQueueId == msgQueueId)
{
it.isSet = false;
it.path.clear();
it.handleCheckValue = 0;
it.hasDispatchTargetHandle = false;
it.msgQueueId = 0;
}
}
}
IOS_ERROR _IPCAssignDispatchTargetHandle(IOSDevHandle devHandle, IOSDevHandle internalHandle)
{
std::unique_lock _lock(sInternalMutex);
@@ -453,7 +631,6 @@ namespace iosu
uint32 numIn = dispatchCmd->body.args[1];
uint32 numOut = dispatchCmd->body.args[2];
IPCIoctlVector* vec = MEMPTR<IPCIoctlVector>(cmd.args[3]).GetPtr();
// copy the vector array
uint32 numVec = numIn + numOut;
if (numVec <= 8)
@@ -466,8 +643,23 @@ namespace iosu
// reuse the original vector pointer
cemuLog_log(LogType::Force, "Info: Ioctlv command with more than 8 vectors");
}
IOS_ERROR r = _IPCDispatchToResourceManager(dispatchCmd->body.devHandle, dispatchCmd);
return r;
return _IPCDispatchToResourceManager(dispatchCmd->body.devHandle, dispatchCmd);
}
// normally COS kernel handles this, but currently we skip the IPC getting proxied through it
IOS_ERROR _IPCHandlerIn_TranslateVectorAddresses(IOSDispatchableCommand* dispatchCmd)
{
uint32 numIn = dispatchCmd->body.args[1];
uint32 numOut = dispatchCmd->body.args[2];
IPCIoctlVector* vec = MEMPTR<IPCIoctlVector>(dispatchCmd->body.args[3]).GetPtr();
for (uint32 i = 0; i < numIn + numOut; i++)
{
if (vec[i].baseVirt == nullptr && vec[i].size != 0)
return IOS_ERROR_INVALID;
// todo - check for valid pointer range
vec[i].basePhys = vec[i].baseVirt;
}
return IOS_ERROR_OK;
}
// called by COS directly
@@ -494,7 +686,11 @@ namespace iosu
r = _IPCHandlerIn_IOS_Ioctl(dispatchCmd);
break;
case IPCCommandId::IOS_IOCTLV:
r = _IPCHandlerIn_IOS_Ioctlv(dispatchCmd);
r = _IPCHandlerIn_TranslateVectorAddresses(dispatchCmd);
if(r < 0)
cemuLog_log(LogType::Force, "Ioctlv error");
else
r = _IPCHandlerIn_IOS_Ioctlv(dispatchCmd);
break;
default:
cemuLog_log(LogType::Force, "Invalid IPC command {}", (uint32)(IPCCommandId)cmd->cmdId);
@@ -547,10 +743,34 @@ namespace iosu
return IOS_ERROR_OK;
}
void Initialize()
class : public ::IOSUModule
{
_IPCInitDispatchablePool();
void SystemLaunch() override
{
_IPCInitDispatchablePool();
// start timer thread
sTimerThreadStop = false;
m_timerThread = std::thread(IOSTimerThread);
}
void SystemExit() override
{
// stop timer thread
sTimerThreadStop = true;
sTimerCV.notify_one();
m_timerThread.join();
// reset resources
// todo
}
std::thread m_timerThread;
}sIOSUModuleKernel;
IOSUModule* GetModule()
{
return static_cast<IOSUModule*>(&sIOSUModuleKernel);
}
}
}
+6 -1
View File
@@ -9,15 +9,20 @@ namespace iosu
using IOSMessage = uint32;
IOSMsgQueueId IOS_CreateMessageQueue(IOSMessage* messageArray, uint32 messageCount);
IOS_ERROR IOS_DestroyMessageQueue(IOSMsgQueueId msgQueueId);
IOS_ERROR IOS_SendMessage(IOSMsgQueueId msgQueueId, IOSMessage message, uint32 flags);
IOS_ERROR IOS_ReceiveMessage(IOSMsgQueueId msgQueueId, IOSMessage* messageOut, uint32 flags);
IOS_ERROR IOS_CreateTimer(uint32 startMicroseconds, uint32 repeatMicroseconds, uint32 queueId, uint32 message);
IOS_ERROR IOS_StopTimer(IOSTimerId timerId);
IOS_ERROR IOS_DestroyTimer(IOSTimerId timerId);
IOS_ERROR IOS_RegisterResourceManager(const char* devicePath, IOSMsgQueueId msgQueueId);
IOS_ERROR IOS_DeviceAssociateId(const char* devicePath, uint32 id);
IOS_ERROR IOS_ResourceReply(IPCCommandBody* cmd, IOS_ERROR result);
void IPCSubmitFromCOS(uint32 ppcCoreIndex, IPCCommandBody* cmd);
void Initialize();
IOSUModule* GetModule();
}
}
+9
View File
@@ -192,6 +192,15 @@ namespace iosu
return true;
}
// returns empty string if invalid
std::string getAccountId2(uint8 slot)
{
sint32 accountIndex = iosuAct_getAccountIndexBySlot(slot);
if (_actAccountData[accountIndex].isValid == false)
return {};
return {_actAccountData[accountIndex].accountId};
}
bool getMii(uint8 slot, FFLData_t* fflData)
{
sint32 accountIndex = iosuAct_getAccountIndexBySlot(slot);
+4
View File
@@ -3,6 +3,8 @@
void iosuAct_init_depr();
bool iosuAct_isInitialized();
#define ACT_ACCOUNTID_LENGTH (17) // includes '\0'
// Mii
#define MII_FFL_STORAGE_SIZE (96)
@@ -48,6 +50,8 @@ namespace iosu
bool getScreenname(uint8 slot, uint16 screenname[ACT_NICKNAME_LENGTH]);
bool getCountryIndex(uint8 slot, uint32* countryIndex);
std::string getAccountId2(uint8 slot);
const uint8 ACT_SLOT_CURRENT = 0xFE;
void Initialize();
File diff suppressed because it is too large Load Diff
+166 -251
View File
@@ -1,10 +1,12 @@
#pragma once
#include "Cafe/IOSU/iosu_types_common.h"
#include "Common/CafeString.h"
namespace iosu
{
namespace fpd
{
typedef struct
struct FPDDate
{
/* +0x0 */ uint16be year;
/* +0x2 */ uint8 month;
@@ -13,13 +15,61 @@ namespace iosu
/* +0x5 */ uint8 minute;
/* +0x6 */ uint8 second;
/* +0x7 */ uint8 padding;
}fpdDate_t;
};
static_assert(sizeof(fpdDate_t) == 8);
static_assert(sizeof(FPDDate) == 8);
typedef struct
struct RecentPlayRecordEx
{
/* +0x000 */ uint8 type; // type(Non-Zero -> Friend, 0 -> Friend request ? )
/* +0x00 */ uint32be pid;
/* +0x04 */ uint8 ukn04;
/* +0x05 */ uint8 ukn05;
/* +0x06 */ uint8 ukn06[0x22];
/* +0x28 */ uint8 ukn28[0x22];
/* +0x4A */ uint8 _uknOrPadding4A[6];
/* +0x50 */ uint32be ukn50;
/* +0x54 */ uint32be ukn54;
/* +0x58 */ uint16be ukn58;
/* +0x5C */ uint8 _padding5C[4];
/* +0x60 */ iosu::fpd::FPDDate date;
};
static_assert(sizeof(RecentPlayRecordEx) == 0x68, "");
static_assert(offsetof(RecentPlayRecordEx, ukn06) == 0x06, "");
static_assert(offsetof(RecentPlayRecordEx, ukn50) == 0x50, "");
struct GameKey
{
/* +0x00 */ uint64be titleId;
/* +0x08 */ uint16be ukn08;
/* +0x0A */ uint8 _padding0A[6];
};
static_assert(sizeof(GameKey) == 0x10);
struct Profile
{
uint8be region;
uint8be regionSubcode;
uint8be platform;
uint8be ukn3;
};
static_assert(sizeof(Profile) == 0x4);
struct GameMode
{
/* +0x00 */ uint32be joinFlagMask;
/* +0x04 */ uint32be matchmakeType;
/* +0x08 */ uint32be joinGameId;
/* +0x0C */ uint32be joinGameMode;
/* +0x10 */ uint32be hostPid;
/* +0x14 */ uint32be groupId;
/* +0x18 */ uint8 appSpecificData[0x14];
};
static_assert(sizeof(GameMode) == 0x2C);
struct FriendData
{
/* +0x000 */ uint8 type; // type (Non-Zero -> Friend, 0 -> Friend request ? )
/* +0x001 */ uint8 _padding1[7];
/* +0x008 */ uint32be pid;
/* +0x00C */ char nnid[0x10 + 1];
@@ -29,43 +79,29 @@ namespace iosu
/* +0x036 */ uint8 ukn036;
/* +0x037 */ uint8 _padding037;
/* +0x038 */ uint8 mii[0x60];
/* +0x098 */ fpdDate_t uknDate;
/* +0x098 */ FPDDate uknDate;
// sub struct (the part above seems to be shared with friend requests)
union
{
struct
{
/* +0x0A0 */ uint8 ukn0A0; // country code?
/* +0x0A1 */ uint8 ukn0A1; // country subcode?
/* +0x0A2 */ uint8 _paddingA2[2];
/* +0x0A0 */ Profile profile; // this is returned for nn_fp.GetFriendProfile
/* +0x0A4 */ uint32be ukn0A4;
/* +0x0A8 */ uint64 gameKeyTitleId;
/* +0x0B0 */ uint16be gameKeyUkn;
/* +0x0B2 */ uint8 _paddingB2[6];
/* +0x0B8 */ uint32 ukn0B8;
/* +0x0BC */ uint32 ukn0BC;
/* +0x0C0 */ uint32 ukn0C0;
/* +0x0C4 */ uint32 ukn0C4;
/* +0x0C8 */ uint32 ukn0C8;
/* +0x0CC */ uint32 ukn0CC;
/* +0x0D0 */ uint8 appSpecificData[0x14];
/* +0x0E4 */ uint8 ukn0E4;
/* +0x0E5 */ uint8 _paddingE5;
/* +0x0E6 */ uint16 uknStr[0x80]; // game mode description (could be larger)
/* +0x1E6 */ uint8 _padding1E6[0x1EC - 0x1E6];
/* +0x0A8 */ GameKey gameKey;
/* +0x0B8 */ GameMode gameMode;
/* +0x0E4 */ CafeWideString<0x82> gameModeDescription;
/* +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 */ uint8 ukn1F0;
/* +0x1F1 */ uint8 _padding1F1;
/* +0x1F2 */ uint16be statusMessage[16 + 1]; // pops up every few seconds in friend list (ingame character name?)
/* +0x214 */ uint8 _padding214[4];
/* +0x218 */ fpdDate_t uknDate218;
/* +0x220 */ fpdDate_t lastOnline;
/* +0x1F0 */ char comment[36]; // pops up every few seconds in friend list
/* +0x214 */ uint32be _padding214;
/* +0x218 */ FPDDate approvalTime;
/* +0x220 */ FPDDate lastOnline;
}friendExtraData;
struct
{
/* +0x0A0 */ uint64 messageId; // guessed
/* +0x0A0 */ uint64be messageId; // guessed. If 0, then relationship is FRIENDSHIP_REQUEST_OUT, otherwise FRIENDSHIP_REQUEST_IN
/* +0x0A8 */ uint8 ukn0A8;
/* +0x0A9 */ uint8 ukn0A9; // comment language? (guessed)
/* +0x0AA */ uint16be comment[0x40];
@@ -75,26 +111,23 @@ namespace iosu
/* +0x150 */ uint64 gameKeyTitleId;
/* +0x158 */ uint16be gameKeyUkn;
/* +0x15A */ uint8 _padding[6];
/* +0x160 */ fpdDate_t uknData0;
/* +0x168 */ fpdDate_t uknData1;
/* +0x160 */ FPDDate uknData0;
/* +0x168 */ FPDDate uknData1;
}requestExtraData;
};
}friendData_t;
static_assert(sizeof(friendData_t) == 0x228, "");
static_assert(offsetof(friendData_t, nnid) == 0x00C, "");
static_assert(offsetof(friendData_t, friendExtraData.gameKeyTitleId) == 0x0A8, "");
static_assert(offsetof(friendData_t, friendExtraData.appSpecificData) == 0x0D0, "");
static_assert(offsetof(friendData_t, friendExtraData.uknStr) == 0x0E6, "");
static_assert(offsetof(friendData_t, friendExtraData.ukn1F0) == 0x1F0, "");
};
static_assert(sizeof(FriendData) == 0x228);
static_assert(offsetof(FriendData, friendExtraData.gameKey) == 0x0A8);
static_assert(offsetof(FriendData, friendExtraData.gameModeDescription) == 0x0E4);
static_assert(offsetof(FriendData, friendExtraData.comment) == 0x1F0);
static_assert(offsetof(friendData_t, requestExtraData.messageId) == 0x0A0, "");
static_assert(offsetof(friendData_t, requestExtraData.comment) == 0x0AA, "");
static_assert(offsetof(friendData_t, requestExtraData.uknMessage) == 0x12C, "");
static_assert(offsetof(friendData_t, requestExtraData.gameKeyTitleId) == 0x150, "");
static_assert(offsetof(friendData_t, requestExtraData.uknData1) == 0x168, "");
static_assert(offsetof(FriendData, requestExtraData.messageId) == 0x0A0);
static_assert(offsetof(FriendData, requestExtraData.comment) == 0x0AA);
static_assert(offsetof(FriendData, requestExtraData.uknMessage) == 0x12C);
static_assert(offsetof(FriendData, requestExtraData.gameKeyTitleId) == 0x150);
static_assert(offsetof(FriendData, requestExtraData.uknData1) == 0x168);
typedef struct
struct FriendBasicInfo
{
/* +0x00 */ uint32be pid;
/* +0x04 */ char nnid[0x11];
@@ -104,17 +137,17 @@ namespace iosu
/* +0x2E */ uint8 ukn2E; // bool option
/* +0x2F */ uint8 ukn2F;
/* +0x30 */ uint8 miiData[0x60];
/* +0x90 */ fpdDate_t uknDate90;
}friendBasicInfo_t; // size is 0x98
/* +0x90 */ FPDDate uknDate90;
};
static_assert(sizeof(friendBasicInfo_t) == 0x98, "");
static_assert(offsetof(friendBasicInfo_t, nnid) == 0x04, "");
static_assert(offsetof(friendBasicInfo_t, ukn15) == 0x15, "");
static_assert(offsetof(friendBasicInfo_t, screenname) == 0x18, "");
static_assert(offsetof(friendBasicInfo_t, ukn2E) == 0x2E, "");
static_assert(offsetof(friendBasicInfo_t, miiData) == 0x30, "");
static_assert(sizeof(FriendBasicInfo) == 0x98);
static_assert(offsetof(FriendBasicInfo, nnid) == 0x04);
static_assert(offsetof(FriendBasicInfo, ukn15) == 0x15);
static_assert(offsetof(FriendBasicInfo, screenname) == 0x18);
static_assert(offsetof(FriendBasicInfo, ukn2E) == 0x2E);
static_assert(offsetof(FriendBasicInfo, miiData) == 0x30);
typedef struct
struct FriendRequest
{
/* +0x000 */ uint32be pid;
/* +0x004 */ uint8 nnid[17]; // guessed type
@@ -125,7 +158,7 @@ namespace iosu
/* +0x02E */ uint8 ukn2E; // bool option
/* +0x02F */ uint8 ukn2F; // ukn
/* +0x030 */ uint8 miiData[0x60];
/* +0x090 */ fpdDate_t uknDate;
/* +0x090 */ FPDDate uknDate;
/* +0x098 */ uint64 ukn98;
/* +0x0A0 */ uint8 isMarkedAsReceived;
/* +0x0A1 */ uint8 uknA1;
@@ -136,216 +169,98 @@ namespace iosu
/* +0x148 */ uint64 gameKeyTitleId;
/* +0x150 */ uint16be gameKeyUkn;
/* +0x152 */ uint8 _padding152[6];
/* +0x158 */ fpdDate_t uknDate2;
/* +0x160 */ fpdDate_t expireDate;
}friendRequest_t;
/* +0x158 */ FPDDate uknDate2;
/* +0x160 */ FPDDate expireDate;
};
static_assert(sizeof(friendRequest_t) == 0x168, "");
static_assert(offsetof(friendRequest_t, uknDate) == 0x090, "");
static_assert(offsetof(friendRequest_t, message) == 0x0A2, "");
static_assert(offsetof(friendRequest_t, uknString2) == 0x124, "");
static_assert(offsetof(friendRequest_t, gameKeyTitleId) == 0x148, "");
static_assert(sizeof(FriendRequest) == 0x168);
static_assert(offsetof(FriendRequest, uknDate) == 0x090);
static_assert(offsetof(FriendRequest, message) == 0x0A2);
static_assert(offsetof(FriendRequest, uknString2) == 0x124);
static_assert(offsetof(FriendRequest, gameKeyTitleId) == 0x148);
typedef struct
struct FriendPresence
{
/* +0x00 */ uint32be joinFlagMask;
/* +0x04 */ uint32be matchmakeType;
/* +0x08 */ uint32be joinGameId;
/* +0x0C */ uint32be joinGameMode;
/* +0x10 */ uint32be hostPid;
/* +0x14 */ uint32be groupId;
/* +0x18 */ uint8 appSpecificData[0x14];
}gameMode_t;
static_assert(sizeof(gameMode_t) == 0x2C, "");
typedef struct
{
gameMode_t gameMode;
/* +0x2C */ uint8 region;
/* +0x2D */ uint8 regionSubcode;
/* +0x2E */ uint8 platform;
/* +0x2F */ uint8 _padding2F;
GameMode gameMode;
/* +0x2C */ Profile profile;
/* +0x30 */ uint8 isOnline;
/* +0x31 */ uint8 isValid;
/* +0x32 */ uint8 padding[2]; // guessed
}friendPresence_t;
};
static_assert(sizeof(FriendPresence) == 0x34);
static_assert(offsetof(FriendPresence, isOnline) == 0x30);
static_assert(sizeof(friendPresence_t) == 0x34, "");
static_assert(offsetof(friendPresence_t, region) == 0x2C, "");
static_assert(offsetof(friendPresence_t, isOnline) == 0x30, "");
struct FPDNotification
{
betype<uint32> type;
betype<uint32> pid;
};
static_assert(sizeof(FPDNotification) == 8);
struct FPDPreference
{
uint8be showOnline; // show online status to others
uint8be showGame; // show played game to others
uint8be blockFriendRequests; // block friend requests
uint8be ukn; // probably padding?
};
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;
typedef struct
static const int GAMEMODE_MAX_MESSAGE_LENGTH = 0x80; // limit includes null-terminator character, so only 0x7F actual characters can be used
enum class FPD_REQUEST_ID
{
uint32 requestCode;
union
{
struct
{
MEMPTR<void> ptr;
}common;
struct
{
MPTR funcPtr;
MPTR custom;
}loginAsync;
struct
{
MEMPTR<uint32be> pidList;
uint32 startIndex;
uint32 maxCount;
}getFriendList;
struct
{
MEMPTR<friendData_t> friendData;
MEMPTR<uint32be> pidList;
uint32 count;
}getFriendListEx;
struct
{
MEMPTR<friendRequest_t> friendRequest;
MEMPTR<uint32be> pidList;
uint32 count;
}getFriendRequestListEx;
struct
{
uint32 pid;
MPTR funcPtr;
MPTR custom;
}addOrRemoveFriend;
struct
{
uint64 messageId;
MPTR funcPtr;
MPTR custom;
}cancelOrAcceptFriendRequest;
struct
{
uint32 pid;
MEMPTR<uint16be> message;
MPTR funcPtr;
MPTR custom;
}addFriendRequest;
struct
{
MEMPTR<uint64> messageIdList;
uint32 count;
MPTR funcPtr;
MPTR custom;
}markFriendRequest;
struct
{
MEMPTR<friendBasicInfo_t> basicInfo;
MEMPTR<uint32be> pidList;
sint32 count;
MPTR funcPtr;
MPTR custom;
}getBasicInfo;
struct
{
uint32 notificationMask;
MPTR funcPtr;
MPTR custom;
}setNotificationHandler;
struct
{
MEMPTR<char> accountIds;
MEMPTR<uint32be> pidList;
sint32 count;
}getFriendAccountId;
struct
{
MEMPTR<uint16be> nameList;
MEMPTR<uint32be> pidList;
sint32 count;
bool replaceNonAscii;
MEMPTR<uint8> languageList;
}getFriendScreenname;
struct
{
uint8* miiList;
MEMPTR<uint32be> pidList;
sint32 count;
}getFriendMii;
struct
{
uint8* presenceList;
MEMPTR<uint32be> pidList;
sint32 count;
}getFriendPresence;
struct
{
uint8* relationshipList;
MEMPTR<uint32be> pidList;
sint32 count;
}getFriendRelationship;
struct
{
MEMPTR<gameMode_t> gameMode;
MEMPTR<uint16be> gameModeMessage;
}updateGameMode;
};
// output
uint32 returnCode; // return value
union
{
struct
{
uint32 numReturnedCount;
}resultGetFriendList;
struct
{
uint32 u32;
}resultU32;
};
}iosuFpdCemuRequest_t;
// custom dev/fpd protocol (Cemu only)
#define IOSU_FPD_REQUEST_CEMU (0xEE)
// FPD request Cemu subcodes
enum
{
_IOSU_FPD_NONE,
IOSU_FPD_INITIALIZE,
IOSU_FPD_SET_NOTIFICATION_HANDLER,
IOSU_FPD_LOGIN_ASYNC,
IOSU_FPD_IS_ONLINE,
IOSU_FPD_IS_PREFERENCE_VALID,
IOSU_FPD_UPDATE_GAMEMODE,
IOSU_FPD_GET_MY_PRINCIPAL_ID,
IOSU_FPD_GET_MY_ACCOUNT_ID,
IOSU_FPD_GET_MY_MII,
IOSU_FPD_GET_MY_SCREENNAME,
IOSU_FPD_GET_FRIEND_ACCOUNT_ID,
IOSU_FPD_GET_FRIEND_SCREENNAME,
IOSU_FPD_GET_FRIEND_MII,
IOSU_FPD_GET_FRIEND_PRESENCE,
IOSU_FPD_GET_FRIEND_RELATIONSHIP,
IOSU_FPD_GET_FRIEND_LIST,
IOSU_FPD_GET_FRIENDREQUEST_LIST,
IOSU_FPD_GET_FRIEND_LIST_ALL,
IOSU_FPD_GET_FRIEND_LIST_EX,
IOSU_FPD_GET_FRIENDREQUEST_LIST_EX,
IOSU_FPD_ADD_FRIEND,
IOSU_FPD_ADD_FRIEND_REQUEST,
IOSU_FPD_REMOVE_FRIEND_ASYNC,
IOSU_FPD_CANCEL_FRIEND_REQUEST_ASYNC,
IOSU_FPD_ACCEPT_FRIEND_REQUEST_ASYNC,
IOSU_FPD_MARK_FRIEND_REQUEST_AS_RECEIVED_ASYNC,
IOSU_FPD_GET_BASIC_INFO_ASYNC,
LoginAsync = 0x2775,
HasLoggedIn = 0x2777,
IsOnline = 0x2778,
GetMyPrincipalId = 0x27D9,
GetMyAccountId = 0x27DA,
GetMyScreenName = 0x27DB,
GetMyMii = 0x27DC,
GetMyProfile = 0x27DD,
GetMyPreference = 0x27DE,
GetMyPresence = 0x27DF,
IsPreferenceValid = 0x27E0,
GetFriendList = 0x283D,
GetFriendListAll = 0x283E,
GetFriendAccountId = 0x283F,
GetFriendScreenName = 0x2840,
GetFriendPresence = 0x2845,
GetFriendRelationship = 0x2846,
GetFriendMii = 0x2841,
GetBlackList = 0x28A1,
GetFriendRequestList = 0x2905,
UpdateGameModeVariation1 = 0x2969, // there seem to be two different requestIds for the 2-param and 3-param version of UpdateGameMode,
UpdateGameModeVariation2 = 0x296A, // but the third parameter is never used and the same handler is used for both
AddFriendAsyncByPid = 0x29CD,
AddFriendAsyncByXXX = 0x29CE, // probably by name?
GetRequestBlockSettingAsync = 0x2B5D,
GetMyComment = 0x4EE9,
GetMyPlayingGame = 0x4EEA,
CheckSettingStatusAsync = 0x7596,
GetFriendListEx = 0x75F9,
GetFriendRequestListEx = 0x76C1,
UpdatePreferenceAsync = 0x7727,
RemoveFriendAsync = 0x7789,
DeleteFriendFlagsAsync = 0x778A,
AddFriendRequestByPlayRecordAsync = 0x778B,
CancelFriendRequestAsync = 0x778C,
AcceptFriendRequestAsync = 0x7851,
DeleteFriendRequestAsync = 0x7852,
MarkFriendRequestsAsReceivedAsync = 0x7854,
GetBasicInfoAsync = 0x7919,
SetLedEventMask = 0x9D0B,
SetNotificationMask = 0x15ff5,
GetNotificationAsync = 0x15FF6,
};
void Initialize();
using FriendPID = uint32;
IOSUModule* GetModule();
}
}
+128 -1
View File
@@ -1,5 +1,6 @@
#include "iosu_nn_service.h"
#include "../kernel/iosu_kernel.h"
#include "util/helpers/helpers.h"
using namespace iosu::kernel;
@@ -7,6 +8,132 @@ namespace iosu
{
namespace nn
{
/* IPCSimpleService */
void IPCSimpleService::Start()
{
if (m_isRunning.exchange(true))
return;
m_threadInitialized = false;
m_requestStop = false;
m_serviceThread = std::thread(&IPCSimpleService::ServiceThread, this);
while (!m_threadInitialized) std::this_thread::sleep_for(std::chrono::milliseconds(10));
StartService();
}
void IPCSimpleService::Stop()
{
if (!m_isRunning.exchange(false))
return;
m_requestStop = true;
StopService();
if(m_timerId != IOSInvalidTimerId)
IOS_DestroyTimer(m_timerId);
m_timerId = IOSInvalidTimerId;
IOS_SendMessage(m_msgQueueId, 0, 0); // wake up thread
m_serviceThread.join();
}
void IPCSimpleService::ServiceThread()
{
if(!GetThreadName().empty())
SetThreadName(GetThreadName().c_str());
m_msgQueueId = IOS_CreateMessageQueue(_m_msgBuffer.GetPtr(), _m_msgBuffer.GetCount());
cemu_assert(!IOS_ResultIsError((IOS_ERROR)m_msgQueueId));
IOS_ERROR r = IOS_RegisterResourceManager(m_devicePath.c_str(), m_msgQueueId);
cemu_assert(!IOS_ResultIsError(r));
m_threadInitialized = true;
while (true)
{
IOSMessage msg;
r = IOS_ReceiveMessage(m_msgQueueId, &msg, 0);
cemu_assert(!IOS_ResultIsError(r));
if (msg == 0)
{
cemu_assert_debug(m_requestStop);
break;
}
else if(msg == 1)
{
TimerUpdate();
continue;
}
IPCCommandBody* cmd = MEMPTR<IPCCommandBody>(msg).GetPtr();
if (cmd->cmdId == IPCCommandId::IOS_OPEN)
{
void* clientObject = CreateClientObject();
if(clientObject == nullptr)
{
cemuLog_log(LogType::Force, "IPCSimpleService[{}]: Maximum handle count reached or handle rejected", m_devicePath);
IOS_ResourceReply(cmd, IOS_ERROR_MAXIMUM_REACHED);
continue;
}
IOSDevHandle newHandle = GetFreeHandle();
m_clientObjects[newHandle] = clientObject;
IOS_ResourceReply(cmd, (IOS_ERROR)newHandle);
continue;
}
else if (cmd->cmdId == IPCCommandId::IOS_CLOSE)
{
void* clientObject = GetClientObjectByHandle(cmd->devHandle);
if (clientObject)
DestroyClientObject(clientObject);
IOS_ResourceReply(cmd, IOS_ERROR_OK);
continue;
}
else if (cmd->cmdId == IPCCommandId::IOS_IOCTLV)
{
void* clientObject = GetClientObjectByHandle(cmd->devHandle);
if (!clientObject)
{
cemuLog_log(LogType::Force, "IPCSimpleService[{}]: Invalid IPC handle", m_devicePath);
IOS_ResourceReply(cmd, IOS_ERROR_INVALID);
continue;
}
uint32 requestId = cmd->args[0];
uint32 numIn = cmd->args[1];
uint32 numOut = cmd->args[2];
IPCIoctlVector* vec = MEMPTR<IPCIoctlVector>{ cmd->args[3] }.GetPtr();
IPCIoctlVector* vecIn = vec + 0; // the ordering of vecIn/vecOut differs from IPCService
IPCIoctlVector* vecOut = vec + numIn;
m_delayResponse = false;
m_activeCmd = cmd;
uint32 result = ServiceCall(clientObject, requestId, vecIn, numIn, vecOut, numOut);
if (!m_delayResponse)
IOS_ResourceReply(cmd, (IOS_ERROR)result);
m_activeCmd = nullptr;
continue;
}
else
{
cemuLog_log(LogType::Force, "IPCSimpleService[{}]: Unsupported IPC cmdId {}", m_devicePath, (uint32)cmd->cmdId.value());
cemu_assert_unimplemented();
IOS_ResourceReply(cmd, IOS_ERROR_INVALID);
}
}
IOS_DestroyMessageQueue(m_msgQueueId);
m_threadInitialized = false;
}
void IPCSimpleService::SetTimerUpdate(uint32 milliseconds)
{
if(m_timerId != IOSInvalidTimerId)
IOS_DestroyTimer(m_timerId);
m_timerId = IOS_CreateTimer(milliseconds * 1000, milliseconds * 1000, m_msgQueueId, 1);
}
IPCCommandBody* IPCSimpleService::ServiceCallDelayCurrentResponse()
{
cemu_assert_debug(m_activeCmd);
m_delayResponse = true;
return m_activeCmd;
}
void IPCSimpleService::ServiceCallAsyncRespond(IPCCommandBody* response, uint32 r)
{
IOS_ResourceReply(response, (IOS_ERROR)r);
}
/* IPCService */
void IPCService::Start()
{
if (m_isRunning.exchange(true))
@@ -83,4 +210,4 @@ namespace iosu
m_threadInitialized = false;
}
};
};
};
+67
View File
@@ -8,6 +8,71 @@ namespace iosu
{
namespace nn
{
// a simple service interface which wraps handle management and Ioctlv/IoctlvAsync
class IPCSimpleService
{
public:
IPCSimpleService(std::string_view devicePath) : m_devicePath(devicePath) {};
virtual ~IPCSimpleService() {};
virtual void StartService() {};
virtual void StopService() {};
virtual std::string GetThreadName() = 0;
virtual void* CreateClientObject() = 0;
virtual void DestroyClientObject(void* clientObject) = 0;
virtual uint32 ServiceCall(void* clientObject, uint32 requestId, IPCIoctlVector* vecIn, uint32 numVecIn, IPCIoctlVector* vecOut, uint32 numVecOut) = 0;
virtual void TimerUpdate() {};
IPCCommandBody* ServiceCallDelayCurrentResponse();
static void ServiceCallAsyncRespond(IPCCommandBody* response, uint32 r);
void Start();
void Stop();
void SetTimerUpdate(uint32 milliseconds);
private:
void ServiceThread();
IOSDevHandle GetFreeHandle()
{
while(m_clientObjects.find(m_nextHandle) != m_clientObjects.end() || m_nextHandle == 0)
{
m_nextHandle++;
m_nextHandle &= 0x7FFFFFFF;
}
IOSDevHandle newHandle = m_nextHandle;
m_nextHandle++;
m_nextHandle &= 0x7FFFFFFF;
return newHandle;
}
void* GetClientObjectByHandle(IOSDevHandle handle) const
{
auto it = m_clientObjects.find(handle);
if(it == m_clientObjects.end())
return nullptr;
return it->second;
}
std::string m_devicePath;
std::thread m_serviceThread;
std::atomic_bool m_requestStop{false};
std::atomic_bool m_isRunning{false};
std::atomic_bool m_threadInitialized{ false };
std::unordered_map<IOSDevHandle, void*> m_clientObjects;
IOSDevHandle m_nextHandle{1};
IOSTimerId m_timerId{IOSInvalidTimerId};
IPCCommandBody* m_activeCmd{nullptr};
bool m_delayResponse{false};
IOSMsgQueueId m_msgQueueId;
SysAllocator<iosu::kernel::IOSMessage, 128> _m_msgBuffer;
};
struct IPCServiceRequest
{
uint32be ukn00;
@@ -23,6 +88,7 @@ namespace iosu
uint32be nnResultCode;
};
// a complex service interface which wraps Ioctlv and adds an additional service channel, used by /dev/act, ?
class IPCService
{
public:
@@ -60,5 +126,6 @@ namespace iosu
IOSMsgQueueId m_msgQueueId;
SysAllocator<iosu::kernel::IOSMessage, 128> _m_msgBuffer;
};
};
};
+1 -1
View File
@@ -724,7 +724,7 @@ uint32 RPLLoader_MakePPCCallable(void(*ppcCallableExport)(PPCInterpreter_t* hCPU
if (it != g_map_callableExports.end())
return it->second;
// get HLE function index
sint32 functionIndex = PPCInterpreter_registerHLECall(ppcCallableExport);
sint32 functionIndex = PPCInterpreter_registerHLECall(ppcCallableExport, fmt::format("PPCCallback{:x}", (uintptr_t)ppcCallableExport));
MPTR codeAddr = memory_getVirtualOffsetFromPointer(RPLLoader_AllocateTrampolineCodeSpace(4));
uint32 opcode = (1 << 26) | functionIndex;
memory_write<uint32>(codeAddr, opcode);
+3 -2
View File
@@ -85,6 +85,7 @@ void osLib_addFunctionInternal(const char* libraryName, const char* functionName
uint32 funcHashA, funcHashB;
osLib_generateHashFromName(libraryName, &libHashA, &libHashB);
osLib_generateHashFromName(functionName, &funcHashA, &funcHashB);
std::string hleName = fmt::format("{}.{}", libraryName, functionName);
// if entry already exists, update it
for (auto& it : *s_osFunctionTable)
{
@@ -93,11 +94,11 @@ void osLib_addFunctionInternal(const char* libraryName, const char* functionName
it.funcHashA == funcHashA &&
it.funcHashB == funcHashB)
{
it.hleFunc = PPCInterpreter_registerHLECall(osFunction);
it.hleFunc = PPCInterpreter_registerHLECall(osFunction, hleName);
return;
}
}
s_osFunctionTable->emplace_back(libHashA, libHashB, funcHashA, funcHashB, fmt::format("{}.{}", libraryName, functionName), PPCInterpreter_registerHLECall(osFunction));
s_osFunctionTable->emplace_back(libHashA, libHashB, funcHashA, funcHashB, hleName, PPCInterpreter_registerHLECall(osFunction, hleName));
}
extern "C" DLLEXPORT void osLib_registerHLEFunction(const char* libraryName, const char* functionName, void(*osFunction)(PPCInterpreter_t * hCPU))
+43 -43
View File
@@ -912,8 +912,8 @@ namespace coreinit
sint32 FSOpenFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, char* mode, FSFileHandleDepr_t* fileHandle, uint32 errHandling)
{
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
sint32 fsAsyncRet = FSOpenFileAsync(fsClient, fsCmdBlock, path, mode, fileHandle, errHandling, asyncParams);
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSOpenFileAsync(fsClient, fsCmdBlock, path, mode, fileHandle, errHandling, &asyncParams);
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errHandling);
}
@@ -941,8 +941,8 @@ namespace coreinit
sint32 FSOpenFileEx(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, char* mode, uint32 createMode, uint32 openFlag, uint32 preallocSize, FSFileHandleDepr_t* fileHandle, uint32 errHandling)
{
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
sint32 fsAsyncRet = FSOpenFileExAsync(fsClient, fsCmdBlock, path, mode, createMode, openFlag, preallocSize, fileHandle, errHandling, asyncParams);
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSOpenFileExAsync(fsClient, fsCmdBlock, path, mode, createMode, openFlag, preallocSize, fileHandle, errHandling, &asyncParams);
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errHandling);
}
@@ -975,8 +975,8 @@ namespace coreinit
sint32 FSCloseFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 errHandling)
{
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
sint32 fsAsyncRet = FSCloseFileAsync(fsClient, fsCmdBlock, fileHandle, errHandling, asyncParams);
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSCloseFileAsync(fsClient, fsCmdBlock, fileHandle, errHandling, &asyncParams);
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errHandling);
}
@@ -1009,8 +1009,8 @@ namespace coreinit
sint32 FSFlushFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 errHandling)
{
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
sint32 fsAsyncRet = FSFlushFileAsync(fsClient, fsCmdBlock, fileHandle, errHandling, asyncParams);
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSFlushFileAsync(fsClient, fsCmdBlock, fileHandle, errHandling, &asyncParams);
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errHandling);
}
@@ -1090,7 +1090,7 @@ namespace coreinit
sint32 FSReadFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* dst, uint32 size, uint32 count, uint32 fileHandle, uint32 flag, uint32 errorMask)
{
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSReadFileAsync(fsClient, fsCmdBlock, dst, size, count, fileHandle, flag, errorMask, asyncParams.GetPointer());
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
}
@@ -1105,7 +1105,7 @@ namespace coreinit
sint32 FSReadFileWithPos(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* dst, uint32 size, uint32 count, uint32 filePos, uint32 fileHandle, uint32 flag, uint32 errorMask)
{
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSReadFileWithPosAsync(fsClient, fsCmdBlock, dst, size, count, filePos, fileHandle, flag, errorMask, asyncParams.GetPointer());
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
}
@@ -1183,7 +1183,7 @@ namespace coreinit
sint32 FSWriteFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* src, uint32 size, uint32 count, uint32 fileHandle, uint32 flag, uint32 errorMask)
{
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSWriteFileAsync(fsClient, fsCmdBlock, src, size, count, fileHandle, flag, errorMask, asyncParams.GetPointer());
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
}
@@ -1196,7 +1196,7 @@ namespace coreinit
sint32 FSWriteFileWithPos(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* src, uint32 size, uint32 count, uint32 filePos, uint32 fileHandle, uint32 flag, uint32 errorMask)
{
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSWriteFileWithPosAsync(fsClient, fsCmdBlock, src, size, count, filePos, fileHandle, flag, errorMask, asyncParams.GetPointer());
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
}
@@ -1228,7 +1228,7 @@ namespace coreinit
{
// used by games: Mario Kart 8
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSSetPosFileAsync(fsClient, fsCmdBlock, fileHandle, filePos, errorMask, asyncParams.GetPointer());
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
}
@@ -1259,7 +1259,7 @@ namespace coreinit
sint32 FSGetPosFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32be* returnedFilePos, uint32 errorMask)
{
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSGetPosFileAsync(fsClient, fsCmdBlock, fileHandle, returnedFilePos, errorMask, asyncParams.GetPointer());
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
}
@@ -1307,8 +1307,8 @@ namespace coreinit
sint32 FSOpenDir(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, FSDirHandlePtr dirHandleOut, uint32 errorMask)
{
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
sint32 fsAsyncRet = FSOpenDirAsync(fsClient, fsCmdBlock, path, dirHandleOut, errorMask, asyncParams);
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSOpenDirAsync(fsClient, fsCmdBlock, path, dirHandleOut, errorMask, &asyncParams);
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
}
@@ -1337,8 +1337,8 @@ namespace coreinit
sint32 FSReadDir(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSDirHandle2 dirHandle, FSDirEntry_t* dirEntryOut, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
{
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
sint32 fsAsyncRet = FSReadDirAsync(fsClient, fsCmdBlock, dirHandle, dirEntryOut, errorMask, asyncParams);
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSReadDirAsync(fsClient, fsCmdBlock, dirHandle, dirEntryOut, errorMask, &asyncParams);
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
}
@@ -1367,8 +1367,8 @@ namespace coreinit
sint32 FSCloseDir(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSDirHandle2 dirHandle, uint32 errorMask)
{
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
sint32 fsAsyncRet = FSCloseDirAsync(fsClient, fsCmdBlock, dirHandle, errorMask, asyncParams);
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSCloseDirAsync(fsClient, fsCmdBlock, dirHandle, errorMask, &asyncParams);
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
}
@@ -1400,8 +1400,8 @@ namespace coreinit
sint32 FSRewindDir(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSDirHandle2 dirHandle, uint32 errorMask)
{
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
sint32 fsAsyncRet = FSRewindDirAsync(fsClient, fsCmdBlock, dirHandle, errorMask, asyncParams);
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSRewindDirAsync(fsClient, fsCmdBlock, dirHandle, errorMask, &asyncParams);
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
}
@@ -1435,7 +1435,7 @@ namespace coreinit
sint32 FSAppendFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 size, uint32 count, uint32 fileHandle, uint32 errorMask)
{
StackAllocator<FSAsyncParamsNew_t> asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSAppendFileAsync(fsClient, fsCmdBlock, size, count, fileHandle, errorMask, asyncParams.GetPointer());
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
}
@@ -1467,7 +1467,7 @@ namespace coreinit
sint32 FSTruncateFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSFileHandle2 fileHandle, uint32 errorMask)
{
StackAllocator<FSAsyncParamsNew_t> asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSTruncateFileAsync(fsClient, fsCmdBlock, fileHandle, errorMask, asyncParams.GetPointer());
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
}
@@ -1531,7 +1531,7 @@ namespace coreinit
sint32 FSRename(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* srcPath, char* dstPath, uint32 errorMask)
{
StackAllocator<FSAsyncParamsNew_t> asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSRenameAsync(fsClient, fsCmdBlock, srcPath, dstPath, errorMask, asyncParams.GetPointer());
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
}
@@ -1582,8 +1582,8 @@ namespace coreinit
sint32 FSRemove(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint8* filePath, uint32 errorMask)
{
StackAllocator<FSAsyncParamsNew_t> asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
sint32 fsAsyncRet = FSRemoveAsync(fsClient, fsCmdBlock, filePath, errorMask, asyncParams);
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSRemoveAsync(fsClient, fsCmdBlock, filePath, errorMask, &asyncParams);
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
}
@@ -1634,8 +1634,8 @@ namespace coreinit
sint32 FSMakeDir(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, const char* path, uint32 errorMask)
{
StackAllocator<FSAsyncParamsNew_t> asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
sint32 fsAsyncRet = FSMakeDirAsync(fsClient, fsCmdBlock, path, errorMask, asyncParams);
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSMakeDirAsync(fsClient, fsCmdBlock, path, errorMask, &asyncParams);
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
}
@@ -1683,8 +1683,8 @@ namespace coreinit
sint32 FSChangeDir(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, uint32 errorMask)
{
StackAllocator<FSAsyncParamsNew_t> asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
sint32 fsAsyncRet = FSChangeDirAsync(fsClient, fsCmdBlock, path, errorMask, asyncParams);
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSChangeDirAsync(fsClient, fsCmdBlock, path, errorMask, &asyncParams);
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
}
@@ -1718,8 +1718,8 @@ namespace coreinit
sint32 FSGetCwd(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* dirPathOut, sint32 dirPathMaxLen, uint32 errorMask)
{
StackAllocator<FSAsyncParamsNew_t> asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
sint32 fsAsyncRet = FSGetCwdAsync(fsClient, fsCmdBlock, dirPathOut, dirPathMaxLen, errorMask, asyncParams);
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSGetCwdAsync(fsClient, fsCmdBlock, dirPathOut, dirPathMaxLen, errorMask, &asyncParams);
auto r = __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
return r;
}
@@ -1763,8 +1763,8 @@ namespace coreinit
sint32 FSFlushQuota(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, uint32 errorMask)
{
StackAllocator<FSAsyncParamsNew_t> asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
sint32 fsAsyncRet = FSFlushQuotaAsync(fsClient, fsCmdBlock, path, errorMask, asyncParams);
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSFlushQuotaAsync(fsClient, fsCmdBlock, path, errorMask, &asyncParams);
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
}
@@ -1821,8 +1821,8 @@ namespace coreinit
sint32 FSGetStat(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, const char* path, FSStat_t* statOut, uint32 errorMask)
{
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
sint32 fsAsyncRet = FSGetStatAsync(fsClient, fsCmdBlock, path, statOut, errorMask, asyncParams);
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSGetStatAsync(fsClient, fsCmdBlock, path, statOut, errorMask, &asyncParams);
sint32 ret = __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
return ret;
}
@@ -1858,8 +1858,8 @@ namespace coreinit
sint32 FSGetStatFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSFileHandle2 fileHandle, FSStat_t* statOut, uint32 errorMask)
{
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
sint32 fsAsyncRet = FSGetStatFileAsync(fsClient, fsCmdBlock, fileHandle, statOut, errorMask, asyncParams);
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSGetStatFileAsync(fsClient, fsCmdBlock, fileHandle, statOut, errorMask, &asyncParams);
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
}
@@ -1873,8 +1873,8 @@ namespace coreinit
sint32 FSGetFreeSpaceSize(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, const char* path, FSLargeSize* returnedFreeSize, uint32 errorMask)
{
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
sint32 fsAsyncRet = FSGetFreeSpaceSizeAsync(fsClient, fsCmdBlock, path, returnedFreeSize, errorMask, asyncParams);
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSGetFreeSpaceSizeAsync(fsClient, fsCmdBlock, path, returnedFreeSize, errorMask, &asyncParams);
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
}
@@ -1908,8 +1908,8 @@ namespace coreinit
sint32 FSIsEof(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 errorMask)
{
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
sint32 fsAsyncRet = FSIsEofAsync(fsClient, fsCmdBlock, fileHandle, errorMask, asyncParams);
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSIsEofAsync(fsClient, fsCmdBlock, fileHandle, errorMask, &asyncParams);
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
}
@@ -355,23 +355,6 @@ namespace coreinit
IOS_ERROR _IPCDriver_SetupCmd_IOSIoctlv(IPCDriver& ipcDriver, IPCResourceBufferDescriptor* requestDescriptor, uint32 requestId, uint32 numIn, uint32 numOut, IPCIoctlVector* vec)
{
IPCCommandBody& cmdBody = requestDescriptor->resourcePtr->commandBody;
// verify input and output vectors
IPCIoctlVector* vecIn = vec;
IPCIoctlVector* vecOut = vec + numIn;
for (uint32 i = 0; i < numIn; i++)
{
if (vecIn[i].baseVirt == nullptr && vecIn[i].size != 0)
return IOS_ERROR_INVALID_ARG;
vecIn[i].basePhys = vecIn[i].baseVirt;
vecIn[i].baseVirt = nullptr;
}
for (uint32 i = 0; i < numOut; i++)
{
if (vecOut[i].baseVirt == nullptr && vecOut[i].size != 0)
return IOS_ERROR_INVALID_ARG;
vecOut[i].basePhys = vecOut[i].baseVirt;
vecOut[i].baseVirt = nullptr;
}
// set args
cmdBody.ppcVirt0 = MEMPTR<void>(vec).GetMPTR();
cmdBody.args[0] = requestId;
+22 -1
View File
@@ -195,7 +195,28 @@ namespace coreinit
else if ((formatStr[0] == 'l' && formatStr[1] == 'l' && (formatStr[2] == 'x' || formatStr[2] == 'X')))
{
formatStr += 3;
// number (64bit)
// double (64bit)
strncpy(tempFormat, formatStart, std::min((std::ptrdiff_t)sizeof(tempFormat) - 1, formatStr - formatStart));
if ((formatStr - formatStart) < sizeof(tempFormat))
tempFormat[(formatStr - formatStart)] = '\0';
else
tempFormat[sizeof(tempFormat) - 1] = '\0';
if (integerParamIndex & 1)
integerParamIndex++;
sint32 tempLen = sprintf(tempStr, tempFormat, PPCInterpreter_getCallParamU64(hCPU, integerParamIndex));
integerParamIndex += 2;
for (sint32 i = 0; i < tempLen; i++)
{
if (writeIndex >= maxLength)
break;
strOut[writeIndex] = tempStr[i];
writeIndex++;
}
}
else if ((formatStr[0] == 'l' && formatStr[1] == 'l' && formatStr[2] == 'd'))
{
formatStr += 3;
// signed integer (64bit)
strncpy(tempFormat, formatStart, std::min((std::ptrdiff_t)sizeof(tempFormat) - 1, formatStr - formatStart));
if ((formatStr - formatStart) < sizeof(tempFormat))
tempFormat[(formatStr - formatStart)] = '\0';
+7 -7
View File
@@ -859,10 +859,10 @@ namespace H264
return H264DEC_STATUS::SUCCESS;
}
StackAllocator<coreinit::OSEvent> executeDoneEvent;
coreinit::OSInitEvent(executeDoneEvent, coreinit::OSEvent::EVENT_STATE::STATE_NOT_SIGNALED, coreinit::OSEvent::EVENT_MODE::MODE_MANUAL);
coreinit::OSInitEvent(&executeDoneEvent, coreinit::OSEvent::EVENT_STATE::STATE_NOT_SIGNALED, coreinit::OSEvent::EVENT_MODE::MODE_MANUAL);
std::vector<H264AVCDecoder::DecodeResult> results;
auto asyncTask = std::async(std::launch::async, _async_H264DECEnd, executeDoneEvent.GetPointer(), session, ctx, &results);
coreinit::OSWaitEvent(executeDoneEvent);
coreinit::OSWaitEvent(&executeDoneEvent);
_ReleaseDecoderSession(session);
if (!results.empty())
{
@@ -977,9 +977,9 @@ namespace H264
StackAllocator<H264DECFrameOutput, 8> stack_decodedFrameResult;
for (sint32 i = 0; i < outputFrameCount; i++)
stack_resultPtrArray[i] = stack_decodedFrameResult + i;
stack_resultPtrArray[i] = &stack_decodedFrameResult + i;
H264DECFrameOutput* frameOutput = stack_decodedFrameResult + 0;
H264DECFrameOutput* frameOutput = &stack_decodedFrameResult + 0;
memset(frameOutput, 0x00, sizeof(H264DECFrameOutput));
frameOutput->imagePtr = (uint8*)decodeResult.imageOutput;
frameOutput->result = 100;
@@ -1022,10 +1022,10 @@ namespace H264
return 0;
}
StackAllocator<coreinit::OSEvent> executeDoneEvent;
coreinit::OSInitEvent(executeDoneEvent, coreinit::OSEvent::EVENT_STATE::STATE_NOT_SIGNALED, coreinit::OSEvent::EVENT_MODE::MODE_MANUAL);
coreinit::OSInitEvent(&executeDoneEvent, coreinit::OSEvent::EVENT_STATE::STATE_NOT_SIGNALED, coreinit::OSEvent::EVENT_MODE::MODE_MANUAL);
H264AVCDecoder::DecodeResult decodeResult;
auto asyncTask = std::async(std::launch::async, _async_H264DECExecute, executeDoneEvent.GetPointer(), session, ctx, imageOutput , &decodeResult);
coreinit::OSWaitEvent(executeDoneEvent);
auto asyncTask = std::async(std::launch::async, _async_H264DECExecute, &executeDoneEvent, session, ctx, imageOutput , &decodeResult);
coreinit::OSWaitEvent(&executeDoneEvent);
_ReleaseDecoderSession(session);
if(decodeResult.frameReady)
H264DoFrameOutputCallback(ctx, decodeResult);
+2 -2
View File
@@ -391,7 +391,7 @@ void nnActExport_GetMiiName(PPCInterpreter_t* hCPU)
StackAllocator<FFLData_t> miiData;
uint32 r = nn::act::GetMiiEx(miiData, iosu::act::ACT_SLOT_CURRENT);
uint32 r = nn::act::GetMiiEx(&miiData, iosu::act::ACT_SLOT_CURRENT);
// extract name
sint32 miiNameLength = 0;
for (sint32 i = 0; i < MII_FFL_NAME_LENGTH; i++)
@@ -414,7 +414,7 @@ void nnActExport_GetMiiNameEx(PPCInterpreter_t* hCPU)
StackAllocator<FFLData_t> miiData;
uint32 r = nn::act::GetMiiEx(miiData, slot);
uint32 r = nn::act::GetMiiEx(&miiData, slot);
// extract name
sint32 miiNameLength = 0;
for (sint32 i = 0; i < MII_FFL_NAME_LENGTH; i++)
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More