mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-11-29 04:24:17 +01:00
nn_fp: Full rework of friend service
This commit is contained in:
parent
13a50a915e
commit
0d71885c88
@ -526,6 +526,13 @@ namespace CafeSystem
|
|||||||
cemuLog_log(LogType::Force, "Platform: {}", platform);
|
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
|
// initialize all subsystems which are persistent and don't depend on a game running
|
||||||
void Initialize()
|
void Initialize()
|
||||||
{
|
{
|
||||||
@ -550,14 +557,15 @@ namespace CafeSystem
|
|||||||
// allocate memory for all SysAllocators
|
// allocate memory for all SysAllocators
|
||||||
// must happen before COS module init, but also before iosu::kernel::Initialize()
|
// must happen before COS module init, but also before iosu::kernel::Initialize()
|
||||||
SysAllocatorContainer::GetInstance().Initialize();
|
SysAllocatorContainer::GetInstance().Initialize();
|
||||||
// init IOSU
|
// init IOSU modules
|
||||||
|
for(auto& module : s_iosuModules)
|
||||||
|
module->SystemLaunch();
|
||||||
|
// init IOSU (deprecated manual init)
|
||||||
iosuCrypto_init();
|
iosuCrypto_init();
|
||||||
iosu::kernel::Initialize();
|
|
||||||
iosu::fsa::Initialize();
|
iosu::fsa::Initialize();
|
||||||
iosuIoctl_init();
|
iosuIoctl_init();
|
||||||
iosuAct_init_depr();
|
iosuAct_init_depr();
|
||||||
iosu::act::Initialize();
|
iosu::act::Initialize();
|
||||||
iosu::fpd::Initialize();
|
|
||||||
iosu::iosuMcp_init();
|
iosu::iosuMcp_init();
|
||||||
iosu::mcp::Init();
|
iosu::mcp::Init();
|
||||||
iosu::iosuAcp_init();
|
iosu::iosuAcp_init();
|
||||||
@ -593,11 +601,14 @@ namespace CafeSystem
|
|||||||
// if a title is running, shut it down
|
// if a title is running, shut it down
|
||||||
if (sSystemRunning)
|
if (sSystemRunning)
|
||||||
ShutdownTitle();
|
ShutdownTitle();
|
||||||
// shutdown persistent subsystems
|
// shutdown persistent subsystems (deprecated manual shutdown)
|
||||||
iosu::odm::Shutdown();
|
iosu::odm::Shutdown();
|
||||||
iosu::act::Stop();
|
iosu::act::Stop();
|
||||||
iosu::mcp::Shutdown();
|
iosu::mcp::Shutdown();
|
||||||
iosu::fsa::Shutdown();
|
iosu::fsa::Shutdown();
|
||||||
|
// shutdown IOSU modules
|
||||||
|
for(auto it = s_iosuModules.rbegin(); it != s_iosuModules.rend(); ++it)
|
||||||
|
(*it)->SystemExit();
|
||||||
s_initialized = false;
|
s_initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -821,7 +832,8 @@ namespace CafeSystem
|
|||||||
|
|
||||||
void _LaunchTitleThread()
|
void _LaunchTitleThread()
|
||||||
{
|
{
|
||||||
// init
|
for(auto& module : s_iosuModules)
|
||||||
|
module->TitleStart();
|
||||||
cemu_initForGame();
|
cemu_initForGame();
|
||||||
// enter scheduler
|
// enter scheduler
|
||||||
if (ActiveSettings::GetCPUMode() == CPUMode::MulticoreRecompiler)
|
if (ActiveSettings::GetCPUMode() == CPUMode::MulticoreRecompiler)
|
||||||
@ -956,6 +968,8 @@ namespace CafeSystem
|
|||||||
nn::save::ResetToDefaultState();
|
nn::save::ResetToDefaultState();
|
||||||
coreinit::__OSDeleteAllActivePPCThreads();
|
coreinit::__OSDeleteAllActivePPCThreads();
|
||||||
RPLLoader_ResetState();
|
RPLLoader_ResetState();
|
||||||
|
for(auto it = s_iosuModules.rbegin(); it != s_iosuModules.rend(); ++it)
|
||||||
|
(*it)->TitleStop();
|
||||||
// stop time tracking
|
// stop time tracking
|
||||||
iosu::pdm::Stop();
|
iosu::pdm::Stop();
|
||||||
// reset Cemu subsystems
|
// reset Cemu subsystems
|
||||||
|
@ -19,7 +19,7 @@ void PPCInterpreter_handleUnsupportedHLECall(PPCInterpreter_t* hCPU)
|
|||||||
|
|
||||||
std::vector<void(*)(PPCInterpreter_t* hCPU)>* sPPCHLETable{};
|
std::vector<void(*)(PPCInterpreter_t* hCPU)>* sPPCHLETable{};
|
||||||
|
|
||||||
HLEIDX PPCInterpreter_registerHLECall(HLECALL hleCall)
|
HLEIDX PPCInterpreter_registerHLECall(HLECALL hleCall, std::string hleName)
|
||||||
{
|
{
|
||||||
if (!sPPCHLETable)
|
if (!sPPCHLETable)
|
||||||
sPPCHLETable = new std::vector<void(*)(PPCInterpreter_t* hCPU)>();
|
sPPCHLETable = new std::vector<void(*)(PPCInterpreter_t* hCPU)>();
|
||||||
|
@ -230,7 +230,7 @@ static inline float flushDenormalToZero(float f)
|
|||||||
typedef void(*HLECALL)(PPCInterpreter_t* hCPU);
|
typedef void(*HLECALL)(PPCInterpreter_t* hCPU);
|
||||||
|
|
||||||
typedef sint32 HLEIDX;
|
typedef sint32 HLEIDX;
|
||||||
HLEIDX PPCInterpreter_registerHLECall(HLECALL hleCall);
|
HLEIDX PPCInterpreter_registerHLECall(HLECALL hleCall, std::string hleName);
|
||||||
HLECALL PPCInterpreter_getHLECall(HLEIDX funcIndex);
|
HLECALL PPCInterpreter_getHLECall(HLEIDX funcIndex);
|
||||||
|
|
||||||
// HLE scheduler
|
// HLE scheduler
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
using IOSMsgQueueId = uint32;
|
using IOSMsgQueueId = uint32;
|
||||||
|
using IOSTimerId = uint32;
|
||||||
|
|
||||||
|
static constexpr IOSTimerId IOSInvalidTimerId = 0xFFFFFFFF;
|
||||||
|
|
||||||
// returned for syscalls
|
// returned for syscalls
|
||||||
// maybe also shared with IPC?
|
// maybe also shared with IPC?
|
||||||
@ -20,3 +23,12 @@ inline bool IOS_ResultIsError(const IOS_ERROR err)
|
|||||||
{
|
{
|
||||||
return (err & 0x80000000) != 0;
|
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
|
||||||
|
};
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include "iosu_kernel.h"
|
#include "iosu_kernel.h"
|
||||||
#include "util/helpers/fspinlock.h"
|
#include "util/helpers/fspinlock.h"
|
||||||
|
#include "util/helpers/helpers.h"
|
||||||
#include "Cafe/OS/libs/coreinit/coreinit_IPC.h"
|
#include "Cafe/OS/libs/coreinit/coreinit_IPC.h"
|
||||||
|
#include "util/highresolutiontimer/HighResolutionTimer.h"
|
||||||
|
|
||||||
namespace iosu
|
namespace iosu
|
||||||
{
|
{
|
||||||
@ -8,6 +10,9 @@ namespace iosu
|
|||||||
{
|
{
|
||||||
std::mutex sInternalMutex;
|
std::mutex sInternalMutex;
|
||||||
|
|
||||||
|
void IOS_DestroyResourceManagerForQueueId(IOSMsgQueueId msgQueueId);
|
||||||
|
void _IPCDestroyAllHandlesForMsgQueue(IOSMsgQueueId msgQueueId);
|
||||||
|
|
||||||
static void _assume_lock()
|
static void _assume_lock()
|
||||||
{
|
{
|
||||||
#ifdef CEMU_DEBUG_ASSERT
|
#ifdef CEMU_DEBUG_ASSERT
|
||||||
@ -84,6 +89,19 @@ namespace iosu
|
|||||||
return queueHandle;
|
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)
|
IOS_ERROR IOS_SendMessage(IOSMsgQueueId msgQueueId, IOSMessage message, uint32 flags)
|
||||||
{
|
{
|
||||||
std::unique_lock _l(sInternalMutex);
|
std::unique_lock _l(sInternalMutex);
|
||||||
@ -146,6 +164,133 @@ namespace iosu
|
|||||||
return IOS_ERROR_OK;
|
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 */
|
/* devices and IPC */
|
||||||
|
|
||||||
struct IOSResourceManager
|
struct IOSResourceManager
|
||||||
@ -209,6 +354,23 @@ namespace iosu
|
|||||||
return IOS_ERROR_OK;
|
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)
|
IOS_ERROR IOS_DeviceAssociateId(const char* devicePath, uint32 id)
|
||||||
{
|
{
|
||||||
// not yet implemented
|
// not yet implemented
|
||||||
@ -344,6 +506,22 @@ namespace iosu
|
|||||||
return IOS_ERROR_OK;
|
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)
|
IOS_ERROR _IPCAssignDispatchTargetHandle(IOSDevHandle devHandle, IOSDevHandle internalHandle)
|
||||||
{
|
{
|
||||||
std::unique_lock _lock(sInternalMutex);
|
std::unique_lock _lock(sInternalMutex);
|
||||||
@ -453,7 +631,6 @@ namespace iosu
|
|||||||
uint32 numIn = dispatchCmd->body.args[1];
|
uint32 numIn = dispatchCmd->body.args[1];
|
||||||
uint32 numOut = dispatchCmd->body.args[2];
|
uint32 numOut = dispatchCmd->body.args[2];
|
||||||
IPCIoctlVector* vec = MEMPTR<IPCIoctlVector>(cmd.args[3]).GetPtr();
|
IPCIoctlVector* vec = MEMPTR<IPCIoctlVector>(cmd.args[3]).GetPtr();
|
||||||
|
|
||||||
// copy the vector array
|
// copy the vector array
|
||||||
uint32 numVec = numIn + numOut;
|
uint32 numVec = numIn + numOut;
|
||||||
if (numVec <= 8)
|
if (numVec <= 8)
|
||||||
@ -466,8 +643,23 @@ namespace iosu
|
|||||||
// reuse the original vector pointer
|
// reuse the original vector pointer
|
||||||
cemuLog_log(LogType::Force, "Info: Ioctlv command with more than 8 vectors");
|
cemuLog_log(LogType::Force, "Info: Ioctlv command with more than 8 vectors");
|
||||||
}
|
}
|
||||||
IOS_ERROR r = _IPCDispatchToResourceManager(dispatchCmd->body.devHandle, dispatchCmd);
|
return _IPCDispatchToResourceManager(dispatchCmd->body.devHandle, dispatchCmd);
|
||||||
return r;
|
}
|
||||||
|
|
||||||
|
// 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
|
// called by COS directly
|
||||||
@ -494,7 +686,11 @@ namespace iosu
|
|||||||
r = _IPCHandlerIn_IOS_Ioctl(dispatchCmd);
|
r = _IPCHandlerIn_IOS_Ioctl(dispatchCmd);
|
||||||
break;
|
break;
|
||||||
case IPCCommandId::IOS_IOCTLV:
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
cemuLog_log(LogType::Force, "Invalid IPC command {}", (uint32)(IPCCommandId)cmd->cmdId);
|
cemuLog_log(LogType::Force, "Invalid IPC command {}", (uint32)(IPCCommandId)cmd->cmdId);
|
||||||
@ -547,10 +743,34 @@ namespace iosu
|
|||||||
return IOS_ERROR_OK;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -9,15 +9,20 @@ namespace iosu
|
|||||||
using IOSMessage = uint32;
|
using IOSMessage = uint32;
|
||||||
|
|
||||||
IOSMsgQueueId IOS_CreateMessageQueue(IOSMessage* messageArray, uint32 messageCount);
|
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_SendMessage(IOSMsgQueueId msgQueueId, IOSMessage message, uint32 flags);
|
||||||
IOS_ERROR IOS_ReceiveMessage(IOSMsgQueueId msgQueueId, IOSMessage* messageOut, 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_RegisterResourceManager(const char* devicePath, IOSMsgQueueId msgQueueId);
|
||||||
IOS_ERROR IOS_DeviceAssociateId(const char* devicePath, uint32 id);
|
IOS_ERROR IOS_DeviceAssociateId(const char* devicePath, uint32 id);
|
||||||
IOS_ERROR IOS_ResourceReply(IPCCommandBody* cmd, IOS_ERROR result);
|
IOS_ERROR IOS_ResourceReply(IPCCommandBody* cmd, IOS_ERROR result);
|
||||||
|
|
||||||
void IPCSubmitFromCOS(uint32 ppcCoreIndex, IPCCommandBody* cmd);
|
void IPCSubmitFromCOS(uint32 ppcCoreIndex, IPCCommandBody* cmd);
|
||||||
|
|
||||||
void Initialize();
|
IOSUModule* GetModule();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -192,6 +192,15 @@ namespace iosu
|
|||||||
return true;
|
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)
|
bool getMii(uint8 slot, FFLData_t* fflData)
|
||||||
{
|
{
|
||||||
sint32 accountIndex = iosuAct_getAccountIndexBySlot(slot);
|
sint32 accountIndex = iosuAct_getAccountIndexBySlot(slot);
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
void iosuAct_init_depr();
|
void iosuAct_init_depr();
|
||||||
bool iosuAct_isInitialized();
|
bool iosuAct_isInitialized();
|
||||||
|
|
||||||
|
#define ACT_ACCOUNTID_LENGTH (17) // includes '\0'
|
||||||
|
|
||||||
// Mii
|
// Mii
|
||||||
|
|
||||||
#define MII_FFL_STORAGE_SIZE (96)
|
#define MII_FFL_STORAGE_SIZE (96)
|
||||||
@ -48,6 +50,8 @@ namespace iosu
|
|||||||
bool getScreenname(uint8 slot, uint16 screenname[ACT_NICKNAME_LENGTH]);
|
bool getScreenname(uint8 slot, uint16 screenname[ACT_NICKNAME_LENGTH]);
|
||||||
bool getCountryIndex(uint8 slot, uint32* countryIndex);
|
bool getCountryIndex(uint8 slot, uint32* countryIndex);
|
||||||
|
|
||||||
|
std::string getAccountId2(uint8 slot);
|
||||||
|
|
||||||
const uint8 ACT_SLOT_CURRENT = 0xFE;
|
const uint8 ACT_SLOT_CURRENT = 0xFE;
|
||||||
|
|
||||||
void Initialize();
|
void Initialize();
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,10 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "Cafe/IOSU/iosu_types_common.h"
|
||||||
|
#include "Common/CafeString.h"
|
||||||
|
|
||||||
namespace iosu
|
namespace iosu
|
||||||
{
|
{
|
||||||
namespace fpd
|
namespace fpd
|
||||||
{
|
{
|
||||||
typedef struct
|
struct FPDDate
|
||||||
{
|
{
|
||||||
/* +0x0 */ uint16be year;
|
/* +0x0 */ uint16be year;
|
||||||
/* +0x2 */ uint8 month;
|
/* +0x2 */ uint8 month;
|
||||||
@ -13,13 +15,61 @@ namespace iosu
|
|||||||
/* +0x5 */ uint8 minute;
|
/* +0x5 */ uint8 minute;
|
||||||
/* +0x6 */ uint8 second;
|
/* +0x6 */ uint8 second;
|
||||||
/* +0x7 */ uint8 padding;
|
/* +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];
|
/* +0x001 */ uint8 _padding1[7];
|
||||||
/* +0x008 */ uint32be pid;
|
/* +0x008 */ uint32be pid;
|
||||||
/* +0x00C */ char nnid[0x10 + 1];
|
/* +0x00C */ char nnid[0x10 + 1];
|
||||||
@ -29,43 +79,29 @@ namespace iosu
|
|||||||
/* +0x036 */ uint8 ukn036;
|
/* +0x036 */ uint8 ukn036;
|
||||||
/* +0x037 */ uint8 _padding037;
|
/* +0x037 */ uint8 _padding037;
|
||||||
/* +0x038 */ uint8 mii[0x60];
|
/* +0x038 */ uint8 mii[0x60];
|
||||||
/* +0x098 */ fpdDate_t uknDate;
|
/* +0x098 */ FPDDate uknDate;
|
||||||
// sub struct (the part above seems to be shared with friend requests)
|
// sub struct (the part above seems to be shared with friend requests)
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
/* +0x0A0 */ uint8 ukn0A0; // country code?
|
/* +0x0A0 */ Profile profile; // this is returned for nn_fp.GetFriendProfile
|
||||||
/* +0x0A1 */ uint8 ukn0A1; // country subcode?
|
|
||||||
/* +0x0A2 */ uint8 _paddingA2[2];
|
|
||||||
/* +0x0A4 */ uint32be ukn0A4;
|
/* +0x0A4 */ uint32be ukn0A4;
|
||||||
/* +0x0A8 */ uint64 gameKeyTitleId;
|
/* +0x0A8 */ GameKey gameKey;
|
||||||
/* +0x0B0 */ uint16be gameKeyUkn;
|
/* +0x0B8 */ GameMode gameMode;
|
||||||
/* +0x0B2 */ uint8 _paddingB2[6];
|
/* +0x0E4 */ CafeWideString<0x82> gameModeDescription;
|
||||||
/* +0x0B8 */ uint32 ukn0B8;
|
/* +0x1E8 */ Profile profile1E8; // how does it differ from the one at 0xA0? Returned by GetFriendPresence
|
||||||
/* +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];
|
|
||||||
/* +0x1EC */ uint8 isOnline;
|
/* +0x1EC */ uint8 isOnline;
|
||||||
/* +0x1ED */ uint8 _padding1ED[3];
|
/* +0x1ED */ uint8 _padding1ED[3];
|
||||||
// some other sub struct?
|
// some other sub struct?
|
||||||
/* +0x1F0 */ uint8 ukn1F0;
|
/* +0x1F0 */ char comment[36]; // pops up every few seconds in friend list
|
||||||
/* +0x1F1 */ uint8 _padding1F1;
|
/* +0x214 */ uint32be _padding214;
|
||||||
/* +0x1F2 */ uint16be statusMessage[16 + 1]; // pops up every few seconds in friend list (ingame character name?)
|
/* +0x218 */ FPDDate approvalTime;
|
||||||
/* +0x214 */ uint8 _padding214[4];
|
/* +0x220 */ FPDDate lastOnline;
|
||||||
/* +0x218 */ fpdDate_t uknDate218;
|
|
||||||
/* +0x220 */ fpdDate_t lastOnline;
|
|
||||||
}friendExtraData;
|
}friendExtraData;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
/* +0x0A0 */ uint64 messageId; // guessed
|
/* +0x0A0 */ uint64be messageId; // guessed. If 0, then relationship is FRIENDSHIP_REQUEST_OUT, otherwise FRIENDSHIP_REQUEST_IN
|
||||||
/* +0x0A8 */ uint8 ukn0A8;
|
/* +0x0A8 */ uint8 ukn0A8;
|
||||||
/* +0x0A9 */ uint8 ukn0A9; // comment language? (guessed)
|
/* +0x0A9 */ uint8 ukn0A9; // comment language? (guessed)
|
||||||
/* +0x0AA */ uint16be comment[0x40];
|
/* +0x0AA */ uint16be comment[0x40];
|
||||||
@ -75,26 +111,23 @@ namespace iosu
|
|||||||
/* +0x150 */ uint64 gameKeyTitleId;
|
/* +0x150 */ uint64 gameKeyTitleId;
|
||||||
/* +0x158 */ uint16be gameKeyUkn;
|
/* +0x158 */ uint16be gameKeyUkn;
|
||||||
/* +0x15A */ uint8 _padding[6];
|
/* +0x15A */ uint8 _padding[6];
|
||||||
/* +0x160 */ fpdDate_t uknData0;
|
/* +0x160 */ FPDDate uknData0;
|
||||||
/* +0x168 */ fpdDate_t uknData1;
|
/* +0x168 */ FPDDate uknData1;
|
||||||
}requestExtraData;
|
}requestExtraData;
|
||||||
};
|
};
|
||||||
}friendData_t;
|
};
|
||||||
|
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(sizeof(friendData_t) == 0x228, "");
|
static_assert(offsetof(FriendData, requestExtraData.messageId) == 0x0A0);
|
||||||
static_assert(offsetof(friendData_t, nnid) == 0x00C, "");
|
static_assert(offsetof(FriendData, requestExtraData.comment) == 0x0AA);
|
||||||
static_assert(offsetof(friendData_t, friendExtraData.gameKeyTitleId) == 0x0A8, "");
|
static_assert(offsetof(FriendData, requestExtraData.uknMessage) == 0x12C);
|
||||||
static_assert(offsetof(friendData_t, friendExtraData.appSpecificData) == 0x0D0, "");
|
static_assert(offsetof(FriendData, requestExtraData.gameKeyTitleId) == 0x150);
|
||||||
static_assert(offsetof(friendData_t, friendExtraData.uknStr) == 0x0E6, "");
|
static_assert(offsetof(FriendData, requestExtraData.uknData1) == 0x168);
|
||||||
static_assert(offsetof(friendData_t, friendExtraData.ukn1F0) == 0x1F0, "");
|
|
||||||
|
|
||||||
static_assert(offsetof(friendData_t, requestExtraData.messageId) == 0x0A0, "");
|
struct FriendBasicInfo
|
||||||
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, "");
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
{
|
||||||
/* +0x00 */ uint32be pid;
|
/* +0x00 */ uint32be pid;
|
||||||
/* +0x04 */ char nnid[0x11];
|
/* +0x04 */ char nnid[0x11];
|
||||||
@ -104,17 +137,17 @@ namespace iosu
|
|||||||
/* +0x2E */ uint8 ukn2E; // bool option
|
/* +0x2E */ uint8 ukn2E; // bool option
|
||||||
/* +0x2F */ uint8 ukn2F;
|
/* +0x2F */ uint8 ukn2F;
|
||||||
/* +0x30 */ uint8 miiData[0x60];
|
/* +0x30 */ uint8 miiData[0x60];
|
||||||
/* +0x90 */ fpdDate_t uknDate90;
|
/* +0x90 */ FPDDate uknDate90;
|
||||||
}friendBasicInfo_t; // size is 0x98
|
};
|
||||||
|
|
||||||
static_assert(sizeof(friendBasicInfo_t) == 0x98, "");
|
static_assert(sizeof(FriendBasicInfo) == 0x98);
|
||||||
static_assert(offsetof(friendBasicInfo_t, nnid) == 0x04, "");
|
static_assert(offsetof(FriendBasicInfo, nnid) == 0x04);
|
||||||
static_assert(offsetof(friendBasicInfo_t, ukn15) == 0x15, "");
|
static_assert(offsetof(FriendBasicInfo, ukn15) == 0x15);
|
||||||
static_assert(offsetof(friendBasicInfo_t, screenname) == 0x18, "");
|
static_assert(offsetof(FriendBasicInfo, screenname) == 0x18);
|
||||||
static_assert(offsetof(friendBasicInfo_t, ukn2E) == 0x2E, "");
|
static_assert(offsetof(FriendBasicInfo, ukn2E) == 0x2E);
|
||||||
static_assert(offsetof(friendBasicInfo_t, miiData) == 0x30, "");
|
static_assert(offsetof(FriendBasicInfo, miiData) == 0x30);
|
||||||
|
|
||||||
typedef struct
|
struct FriendRequest
|
||||||
{
|
{
|
||||||
/* +0x000 */ uint32be pid;
|
/* +0x000 */ uint32be pid;
|
||||||
/* +0x004 */ uint8 nnid[17]; // guessed type
|
/* +0x004 */ uint8 nnid[17]; // guessed type
|
||||||
@ -125,7 +158,7 @@ namespace iosu
|
|||||||
/* +0x02E */ uint8 ukn2E; // bool option
|
/* +0x02E */ uint8 ukn2E; // bool option
|
||||||
/* +0x02F */ uint8 ukn2F; // ukn
|
/* +0x02F */ uint8 ukn2F; // ukn
|
||||||
/* +0x030 */ uint8 miiData[0x60];
|
/* +0x030 */ uint8 miiData[0x60];
|
||||||
/* +0x090 */ fpdDate_t uknDate;
|
/* +0x090 */ FPDDate uknDate;
|
||||||
/* +0x098 */ uint64 ukn98;
|
/* +0x098 */ uint64 ukn98;
|
||||||
/* +0x0A0 */ uint8 isMarkedAsReceived;
|
/* +0x0A0 */ uint8 isMarkedAsReceived;
|
||||||
/* +0x0A1 */ uint8 uknA1;
|
/* +0x0A1 */ uint8 uknA1;
|
||||||
@ -136,216 +169,98 @@ namespace iosu
|
|||||||
/* +0x148 */ uint64 gameKeyTitleId;
|
/* +0x148 */ uint64 gameKeyTitleId;
|
||||||
/* +0x150 */ uint16be gameKeyUkn;
|
/* +0x150 */ uint16be gameKeyUkn;
|
||||||
/* +0x152 */ uint8 _padding152[6];
|
/* +0x152 */ uint8 _padding152[6];
|
||||||
/* +0x158 */ fpdDate_t uknDate2;
|
/* +0x158 */ FPDDate uknDate2;
|
||||||
/* +0x160 */ fpdDate_t expireDate;
|
/* +0x160 */ FPDDate expireDate;
|
||||||
}friendRequest_t;
|
};
|
||||||
|
|
||||||
static_assert(sizeof(friendRequest_t) == 0x168, "");
|
static_assert(sizeof(FriendRequest) == 0x168);
|
||||||
static_assert(offsetof(friendRequest_t, uknDate) == 0x090, "");
|
static_assert(offsetof(FriendRequest, uknDate) == 0x090);
|
||||||
static_assert(offsetof(friendRequest_t, message) == 0x0A2, "");
|
static_assert(offsetof(FriendRequest, message) == 0x0A2);
|
||||||
static_assert(offsetof(friendRequest_t, uknString2) == 0x124, "");
|
static_assert(offsetof(FriendRequest, uknString2) == 0x124);
|
||||||
static_assert(offsetof(friendRequest_t, gameKeyTitleId) == 0x148, "");
|
static_assert(offsetof(FriendRequest, gameKeyTitleId) == 0x148);
|
||||||
|
|
||||||
typedef struct
|
struct FriendPresence
|
||||||
{
|
{
|
||||||
/* +0x00 */ uint32be joinFlagMask;
|
GameMode gameMode;
|
||||||
/* +0x04 */ uint32be matchmakeType;
|
/* +0x2C */ Profile profile;
|
||||||
/* +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;
|
|
||||||
/* +0x30 */ uint8 isOnline;
|
/* +0x30 */ uint8 isOnline;
|
||||||
/* +0x31 */ uint8 isValid;
|
/* +0x31 */ uint8 isValid;
|
||||||
/* +0x32 */ uint8 padding[2]; // guessed
|
/* +0x32 */ uint8 padding[2]; // guessed
|
||||||
}friendPresence_t;
|
};
|
||||||
|
static_assert(sizeof(FriendPresence) == 0x34);
|
||||||
|
static_assert(offsetof(FriendPresence, isOnline) == 0x30);
|
||||||
|
|
||||||
static_assert(sizeof(friendPresence_t) == 0x34, "");
|
struct FPDNotification
|
||||||
static_assert(offsetof(friendPresence_t, region) == 0x2C, "");
|
{
|
||||||
static_assert(offsetof(friendPresence_t, isOnline) == 0x30, "");
|
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_INVALID = 0;
|
||||||
static const int RELATIONSHIP_FRIENDREQUEST_OUT = 1;
|
static const int RELATIONSHIP_FRIENDREQUEST_OUT = 1;
|
||||||
static const int RELATIONSHIP_FRIENDREQUEST_IN = 2;
|
static const int RELATIONSHIP_FRIENDREQUEST_IN = 2;
|
||||||
static const int RELATIONSHIP_FRIEND = 3;
|
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;
|
LoginAsync = 0x2775,
|
||||||
union
|
HasLoggedIn = 0x2777,
|
||||||
{
|
IsOnline = 0x2778,
|
||||||
struct
|
GetMyPrincipalId = 0x27D9,
|
||||||
{
|
GetMyAccountId = 0x27DA,
|
||||||
MEMPTR<void> ptr;
|
GetMyScreenName = 0x27DB,
|
||||||
}common;
|
GetMyMii = 0x27DC,
|
||||||
struct
|
GetMyProfile = 0x27DD,
|
||||||
{
|
GetMyPreference = 0x27DE,
|
||||||
MPTR funcPtr;
|
GetMyPresence = 0x27DF,
|
||||||
MPTR custom;
|
IsPreferenceValid = 0x27E0,
|
||||||
}loginAsync;
|
GetFriendList = 0x283D,
|
||||||
struct
|
GetFriendListAll = 0x283E,
|
||||||
{
|
GetFriendAccountId = 0x283F,
|
||||||
MEMPTR<uint32be> pidList;
|
GetFriendScreenName = 0x2840,
|
||||||
uint32 startIndex;
|
GetFriendPresence = 0x2845,
|
||||||
uint32 maxCount;
|
GetFriendRelationship = 0x2846,
|
||||||
}getFriendList;
|
GetFriendMii = 0x2841,
|
||||||
struct
|
GetBlackList = 0x28A1,
|
||||||
{
|
GetFriendRequestList = 0x2905,
|
||||||
MEMPTR<friendData_t> friendData;
|
UpdateGameModeVariation1 = 0x2969, // there seem to be two different requestIds for the 2-param and 3-param version of UpdateGameMode,
|
||||||
MEMPTR<uint32be> pidList;
|
UpdateGameModeVariation2 = 0x296A, // but the third parameter is never used and the same handler is used for both
|
||||||
uint32 count;
|
AddFriendAsyncByPid = 0x29CD,
|
||||||
}getFriendListEx;
|
AddFriendAsyncByXXX = 0x29CE, // probably by name?
|
||||||
struct
|
GetRequestBlockSettingAsync = 0x2B5D,
|
||||||
{
|
GetMyComment = 0x4EE9,
|
||||||
MEMPTR<friendRequest_t> friendRequest;
|
GetMyPlayingGame = 0x4EEA,
|
||||||
MEMPTR<uint32be> pidList;
|
CheckSettingStatusAsync = 0x7596,
|
||||||
uint32 count;
|
GetFriendListEx = 0x75F9,
|
||||||
}getFriendRequestListEx;
|
GetFriendRequestListEx = 0x76C1,
|
||||||
struct
|
UpdatePreferenceAsync = 0x7727,
|
||||||
{
|
RemoveFriendAsync = 0x7789,
|
||||||
uint32 pid;
|
DeleteFriendFlagsAsync = 0x778A,
|
||||||
MPTR funcPtr;
|
AddFriendRequestByPlayRecordAsync = 0x778B,
|
||||||
MPTR custom;
|
CancelFriendRequestAsync = 0x778C,
|
||||||
}addOrRemoveFriend;
|
AcceptFriendRequestAsync = 0x7851,
|
||||||
struct
|
DeleteFriendRequestAsync = 0x7852,
|
||||||
{
|
MarkFriendRequestsAsReceivedAsync = 0x7854,
|
||||||
uint64 messageId;
|
GetBasicInfoAsync = 0x7919,
|
||||||
MPTR funcPtr;
|
SetLedEventMask = 0x9D0B,
|
||||||
MPTR custom;
|
SetNotificationMask = 0x15ff5,
|
||||||
}cancelOrAcceptFriendRequest;
|
GetNotificationAsync = 0x15FF6,
|
||||||
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,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void Initialize();
|
using FriendPID = uint32;
|
||||||
|
|
||||||
|
IOSUModule* GetModule();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,6 @@
|
|||||||
#include "iosu_nn_service.h"
|
#include "iosu_nn_service.h"
|
||||||
#include "../kernel/iosu_kernel.h"
|
#include "../kernel/iosu_kernel.h"
|
||||||
|
#include "util/helpers/helpers.h"
|
||||||
|
|
||||||
using namespace iosu::kernel;
|
using namespace iosu::kernel;
|
||||||
|
|
||||||
@ -7,6 +8,132 @@ namespace iosu
|
|||||||
{
|
{
|
||||||
namespace nn
|
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()
|
void IPCService::Start()
|
||||||
{
|
{
|
||||||
if (m_isRunning.exchange(true))
|
if (m_isRunning.exchange(true))
|
||||||
|
@ -8,6 +8,71 @@ namespace iosu
|
|||||||
{
|
{
|
||||||
namespace nn
|
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
|
struct IPCServiceRequest
|
||||||
{
|
{
|
||||||
uint32be ukn00;
|
uint32be ukn00;
|
||||||
@ -23,6 +88,7 @@ namespace iosu
|
|||||||
uint32be nnResultCode;
|
uint32be nnResultCode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// a complex service interface which wraps Ioctlv and adds an additional service channel, used by /dev/act, ?
|
||||||
class IPCService
|
class IPCService
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -60,5 +126,6 @@ namespace iosu
|
|||||||
IOSMsgQueueId m_msgQueueId;
|
IOSMsgQueueId m_msgQueueId;
|
||||||
SysAllocator<iosu::kernel::IOSMessage, 128> _m_msgBuffer;
|
SysAllocator<iosu::kernel::IOSMessage, 128> _m_msgBuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
@ -724,7 +724,7 @@ uint32 RPLLoader_MakePPCCallable(void(*ppcCallableExport)(PPCInterpreter_t* hCPU
|
|||||||
if (it != g_map_callableExports.end())
|
if (it != g_map_callableExports.end())
|
||||||
return it->second;
|
return it->second;
|
||||||
// get HLE function index
|
// 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));
|
MPTR codeAddr = memory_getVirtualOffsetFromPointer(RPLLoader_AllocateTrampolineCodeSpace(4));
|
||||||
uint32 opcode = (1 << 26) | functionIndex;
|
uint32 opcode = (1 << 26) | functionIndex;
|
||||||
memory_write<uint32>(codeAddr, opcode);
|
memory_write<uint32>(codeAddr, opcode);
|
||||||
|
@ -85,6 +85,7 @@ void osLib_addFunctionInternal(const char* libraryName, const char* functionName
|
|||||||
uint32 funcHashA, funcHashB;
|
uint32 funcHashA, funcHashB;
|
||||||
osLib_generateHashFromName(libraryName, &libHashA, &libHashB);
|
osLib_generateHashFromName(libraryName, &libHashA, &libHashB);
|
||||||
osLib_generateHashFromName(functionName, &funcHashA, &funcHashB);
|
osLib_generateHashFromName(functionName, &funcHashA, &funcHashB);
|
||||||
|
std::string hleName = fmt::format("{}.{}", libraryName, functionName);
|
||||||
// if entry already exists, update it
|
// if entry already exists, update it
|
||||||
for (auto& it : *s_osFunctionTable)
|
for (auto& it : *s_osFunctionTable)
|
||||||
{
|
{
|
||||||
@ -93,11 +94,11 @@ void osLib_addFunctionInternal(const char* libraryName, const char* functionName
|
|||||||
it.funcHashA == funcHashA &&
|
it.funcHashA == funcHashA &&
|
||||||
it.funcHashB == funcHashB)
|
it.funcHashB == funcHashB)
|
||||||
{
|
{
|
||||||
it.hleFunc = PPCInterpreter_registerHLECall(osFunction);
|
it.hleFunc = PPCInterpreter_registerHLECall(osFunction, hleName);
|
||||||
return;
|
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))
|
extern "C" DLLEXPORT void osLib_registerHLEFunction(const char* libraryName, const char* functionName, void(*osFunction)(PPCInterpreter_t * hCPU))
|
||||||
|
@ -912,8 +912,8 @@ namespace coreinit
|
|||||||
sint32 FSOpenFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, char* mode, FSFileHandleDepr_t* fileHandle, uint32 errHandling)
|
sint32 FSOpenFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, char* mode, FSFileHandleDepr_t* fileHandle, uint32 errHandling)
|
||||||
{
|
{
|
||||||
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
|
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
|
||||||
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
|
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
|
||||||
sint32 fsAsyncRet = FSOpenFileAsync(fsClient, fsCmdBlock, path, mode, fileHandle, errHandling, asyncParams);
|
sint32 fsAsyncRet = FSOpenFileAsync(fsClient, fsCmdBlock, path, mode, fileHandle, errHandling, &asyncParams);
|
||||||
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errHandling);
|
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)
|
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;
|
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
|
||||||
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
|
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
|
||||||
sint32 fsAsyncRet = FSOpenFileExAsync(fsClient, fsCmdBlock, path, mode, createMode, openFlag, preallocSize, fileHandle, errHandling, asyncParams);
|
sint32 fsAsyncRet = FSOpenFileExAsync(fsClient, fsCmdBlock, path, mode, createMode, openFlag, preallocSize, fileHandle, errHandling, &asyncParams);
|
||||||
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errHandling);
|
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errHandling);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -975,8 +975,8 @@ namespace coreinit
|
|||||||
sint32 FSCloseFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 errHandling)
|
sint32 FSCloseFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 errHandling)
|
||||||
{
|
{
|
||||||
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
|
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
|
||||||
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
|
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
|
||||||
sint32 fsAsyncRet = FSCloseFileAsync(fsClient, fsCmdBlock, fileHandle, errHandling, asyncParams);
|
sint32 fsAsyncRet = FSCloseFileAsync(fsClient, fsCmdBlock, fileHandle, errHandling, &asyncParams);
|
||||||
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errHandling);
|
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errHandling);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1009,8 +1009,8 @@ namespace coreinit
|
|||||||
sint32 FSFlushFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 errHandling)
|
sint32 FSFlushFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 errHandling)
|
||||||
{
|
{
|
||||||
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
|
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
|
||||||
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
|
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
|
||||||
sint32 fsAsyncRet = FSFlushFileAsync(fsClient, fsCmdBlock, fileHandle, errHandling, asyncParams);
|
sint32 fsAsyncRet = FSFlushFileAsync(fsClient, fsCmdBlock, fileHandle, errHandling, &asyncParams);
|
||||||
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errHandling);
|
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)
|
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;
|
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());
|
sint32 fsAsyncRet = FSReadFileAsync(fsClient, fsCmdBlock, dst, size, count, fileHandle, flag, errorMask, asyncParams.GetPointer());
|
||||||
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
|
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)
|
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;
|
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());
|
sint32 fsAsyncRet = FSReadFileWithPosAsync(fsClient, fsCmdBlock, dst, size, count, filePos, fileHandle, flag, errorMask, asyncParams.GetPointer());
|
||||||
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
|
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)
|
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;
|
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());
|
sint32 fsAsyncRet = FSWriteFileAsync(fsClient, fsCmdBlock, src, size, count, fileHandle, flag, errorMask, asyncParams.GetPointer());
|
||||||
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
|
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)
|
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;
|
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());
|
sint32 fsAsyncRet = FSWriteFileWithPosAsync(fsClient, fsCmdBlock, src, size, count, filePos, fileHandle, flag, errorMask, asyncParams.GetPointer());
|
||||||
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
|
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
|
||||||
}
|
}
|
||||||
@ -1228,7 +1228,7 @@ namespace coreinit
|
|||||||
{
|
{
|
||||||
// used by games: Mario Kart 8
|
// used by games: Mario Kart 8
|
||||||
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
|
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
|
||||||
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
|
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
|
||||||
sint32 fsAsyncRet = FSSetPosFileAsync(fsClient, fsCmdBlock, fileHandle, filePos, errorMask, asyncParams.GetPointer());
|
sint32 fsAsyncRet = FSSetPosFileAsync(fsClient, fsCmdBlock, fileHandle, filePos, errorMask, asyncParams.GetPointer());
|
||||||
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
|
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)
|
sint32 FSGetPosFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32be* returnedFilePos, uint32 errorMask)
|
||||||
{
|
{
|
||||||
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
|
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
|
||||||
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
|
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
|
||||||
sint32 fsAsyncRet = FSGetPosFileAsync(fsClient, fsCmdBlock, fileHandle, returnedFilePos, errorMask, asyncParams.GetPointer());
|
sint32 fsAsyncRet = FSGetPosFileAsync(fsClient, fsCmdBlock, fileHandle, returnedFilePos, errorMask, asyncParams.GetPointer());
|
||||||
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
|
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)
|
sint32 FSOpenDir(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, FSDirHandlePtr dirHandleOut, uint32 errorMask)
|
||||||
{
|
{
|
||||||
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
|
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
|
||||||
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
|
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
|
||||||
sint32 fsAsyncRet = FSOpenDirAsync(fsClient, fsCmdBlock, path, dirHandleOut, errorMask, asyncParams);
|
sint32 fsAsyncRet = FSOpenDirAsync(fsClient, fsCmdBlock, path, dirHandleOut, errorMask, &asyncParams);
|
||||||
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
|
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)
|
sint32 FSReadDir(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSDirHandle2 dirHandle, FSDirEntry_t* dirEntryOut, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
|
||||||
{
|
{
|
||||||
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
|
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
|
||||||
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
|
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
|
||||||
sint32 fsAsyncRet = FSReadDirAsync(fsClient, fsCmdBlock, dirHandle, dirEntryOut, errorMask, asyncParams);
|
sint32 fsAsyncRet = FSReadDirAsync(fsClient, fsCmdBlock, dirHandle, dirEntryOut, errorMask, &asyncParams);
|
||||||
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
|
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1367,8 +1367,8 @@ namespace coreinit
|
|||||||
sint32 FSCloseDir(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSDirHandle2 dirHandle, uint32 errorMask)
|
sint32 FSCloseDir(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSDirHandle2 dirHandle, uint32 errorMask)
|
||||||
{
|
{
|
||||||
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
|
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
|
||||||
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
|
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
|
||||||
sint32 fsAsyncRet = FSCloseDirAsync(fsClient, fsCmdBlock, dirHandle, errorMask, asyncParams);
|
sint32 fsAsyncRet = FSCloseDirAsync(fsClient, fsCmdBlock, dirHandle, errorMask, &asyncParams);
|
||||||
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
|
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1400,8 +1400,8 @@ namespace coreinit
|
|||||||
sint32 FSRewindDir(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSDirHandle2 dirHandle, uint32 errorMask)
|
sint32 FSRewindDir(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSDirHandle2 dirHandle, uint32 errorMask)
|
||||||
{
|
{
|
||||||
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
|
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
|
||||||
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
|
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
|
||||||
sint32 fsAsyncRet = FSRewindDirAsync(fsClient, fsCmdBlock, dirHandle, errorMask, asyncParams);
|
sint32 fsAsyncRet = FSRewindDirAsync(fsClient, fsCmdBlock, dirHandle, errorMask, &asyncParams);
|
||||||
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
|
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)
|
sint32 FSAppendFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 size, uint32 count, uint32 fileHandle, uint32 errorMask)
|
||||||
{
|
{
|
||||||
StackAllocator<FSAsyncParamsNew_t> asyncParams;
|
StackAllocator<FSAsyncParamsNew_t> asyncParams;
|
||||||
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
|
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
|
||||||
sint32 fsAsyncRet = FSAppendFileAsync(fsClient, fsCmdBlock, size, count, fileHandle, errorMask, asyncParams.GetPointer());
|
sint32 fsAsyncRet = FSAppendFileAsync(fsClient, fsCmdBlock, size, count, fileHandle, errorMask, asyncParams.GetPointer());
|
||||||
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
|
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
|
||||||
}
|
}
|
||||||
@ -1467,7 +1467,7 @@ namespace coreinit
|
|||||||
sint32 FSTruncateFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSFileHandle2 fileHandle, uint32 errorMask)
|
sint32 FSTruncateFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSFileHandle2 fileHandle, uint32 errorMask)
|
||||||
{
|
{
|
||||||
StackAllocator<FSAsyncParamsNew_t> asyncParams;
|
StackAllocator<FSAsyncParamsNew_t> asyncParams;
|
||||||
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
|
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
|
||||||
sint32 fsAsyncRet = FSTruncateFileAsync(fsClient, fsCmdBlock, fileHandle, errorMask, asyncParams.GetPointer());
|
sint32 fsAsyncRet = FSTruncateFileAsync(fsClient, fsCmdBlock, fileHandle, errorMask, asyncParams.GetPointer());
|
||||||
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
|
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)
|
sint32 FSRename(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* srcPath, char* dstPath, uint32 errorMask)
|
||||||
{
|
{
|
||||||
StackAllocator<FSAsyncParamsNew_t> asyncParams;
|
StackAllocator<FSAsyncParamsNew_t> asyncParams;
|
||||||
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
|
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
|
||||||
sint32 fsAsyncRet = FSRenameAsync(fsClient, fsCmdBlock, srcPath, dstPath, errorMask, asyncParams.GetPointer());
|
sint32 fsAsyncRet = FSRenameAsync(fsClient, fsCmdBlock, srcPath, dstPath, errorMask, asyncParams.GetPointer());
|
||||||
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
|
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
|
||||||
}
|
}
|
||||||
@ -1582,8 +1582,8 @@ namespace coreinit
|
|||||||
sint32 FSRemove(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint8* filePath, uint32 errorMask)
|
sint32 FSRemove(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint8* filePath, uint32 errorMask)
|
||||||
{
|
{
|
||||||
StackAllocator<FSAsyncParamsNew_t> asyncParams;
|
StackAllocator<FSAsyncParamsNew_t> asyncParams;
|
||||||
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
|
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
|
||||||
sint32 fsAsyncRet = FSRemoveAsync(fsClient, fsCmdBlock, filePath, errorMask, asyncParams);
|
sint32 fsAsyncRet = FSRemoveAsync(fsClient, fsCmdBlock, filePath, errorMask, &asyncParams);
|
||||||
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
|
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)
|
sint32 FSMakeDir(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, const char* path, uint32 errorMask)
|
||||||
{
|
{
|
||||||
StackAllocator<FSAsyncParamsNew_t> asyncParams;
|
StackAllocator<FSAsyncParamsNew_t> asyncParams;
|
||||||
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
|
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
|
||||||
sint32 fsAsyncRet = FSMakeDirAsync(fsClient, fsCmdBlock, path, errorMask, asyncParams);
|
sint32 fsAsyncRet = FSMakeDirAsync(fsClient, fsCmdBlock, path, errorMask, &asyncParams);
|
||||||
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
|
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1683,8 +1683,8 @@ namespace coreinit
|
|||||||
sint32 FSChangeDir(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, uint32 errorMask)
|
sint32 FSChangeDir(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, uint32 errorMask)
|
||||||
{
|
{
|
||||||
StackAllocator<FSAsyncParamsNew_t> asyncParams;
|
StackAllocator<FSAsyncParamsNew_t> asyncParams;
|
||||||
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
|
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
|
||||||
sint32 fsAsyncRet = FSChangeDirAsync(fsClient, fsCmdBlock, path, errorMask, asyncParams);
|
sint32 fsAsyncRet = FSChangeDirAsync(fsClient, fsCmdBlock, path, errorMask, &asyncParams);
|
||||||
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
|
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)
|
sint32 FSGetCwd(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* dirPathOut, sint32 dirPathMaxLen, uint32 errorMask)
|
||||||
{
|
{
|
||||||
StackAllocator<FSAsyncParamsNew_t> asyncParams;
|
StackAllocator<FSAsyncParamsNew_t> asyncParams;
|
||||||
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
|
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
|
||||||
sint32 fsAsyncRet = FSGetCwdAsync(fsClient, fsCmdBlock, dirPathOut, dirPathMaxLen, errorMask, asyncParams);
|
sint32 fsAsyncRet = FSGetCwdAsync(fsClient, fsCmdBlock, dirPathOut, dirPathMaxLen, errorMask, &asyncParams);
|
||||||
auto r = __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
|
auto r = __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -1763,8 +1763,8 @@ namespace coreinit
|
|||||||
sint32 FSFlushQuota(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, uint32 errorMask)
|
sint32 FSFlushQuota(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, uint32 errorMask)
|
||||||
{
|
{
|
||||||
StackAllocator<FSAsyncParamsNew_t> asyncParams;
|
StackAllocator<FSAsyncParamsNew_t> asyncParams;
|
||||||
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
|
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
|
||||||
sint32 fsAsyncRet = FSFlushQuotaAsync(fsClient, fsCmdBlock, path, errorMask, asyncParams);
|
sint32 fsAsyncRet = FSFlushQuotaAsync(fsClient, fsCmdBlock, path, errorMask, &asyncParams);
|
||||||
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
|
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)
|
sint32 FSGetStat(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, const char* path, FSStat_t* statOut, uint32 errorMask)
|
||||||
{
|
{
|
||||||
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
|
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
|
||||||
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
|
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
|
||||||
sint32 fsAsyncRet = FSGetStatAsync(fsClient, fsCmdBlock, path, statOut, errorMask, asyncParams);
|
sint32 fsAsyncRet = FSGetStatAsync(fsClient, fsCmdBlock, path, statOut, errorMask, &asyncParams);
|
||||||
sint32 ret = __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
|
sint32 ret = __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1858,8 +1858,8 @@ namespace coreinit
|
|||||||
sint32 FSGetStatFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSFileHandle2 fileHandle, FSStat_t* statOut, uint32 errorMask)
|
sint32 FSGetStatFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSFileHandle2 fileHandle, FSStat_t* statOut, uint32 errorMask)
|
||||||
{
|
{
|
||||||
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
|
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
|
||||||
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
|
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
|
||||||
sint32 fsAsyncRet = FSGetStatFileAsync(fsClient, fsCmdBlock, fileHandle, statOut, errorMask, asyncParams);
|
sint32 fsAsyncRet = FSGetStatFileAsync(fsClient, fsCmdBlock, fileHandle, statOut, errorMask, &asyncParams);
|
||||||
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
|
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)
|
sint32 FSGetFreeSpaceSize(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, const char* path, FSLargeSize* returnedFreeSize, uint32 errorMask)
|
||||||
{
|
{
|
||||||
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
|
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
|
||||||
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
|
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
|
||||||
sint32 fsAsyncRet = FSGetFreeSpaceSizeAsync(fsClient, fsCmdBlock, path, returnedFreeSize, errorMask, asyncParams);
|
sint32 fsAsyncRet = FSGetFreeSpaceSizeAsync(fsClient, fsCmdBlock, path, returnedFreeSize, errorMask, &asyncParams);
|
||||||
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
|
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1908,8 +1908,8 @@ namespace coreinit
|
|||||||
sint32 FSIsEof(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 errorMask)
|
sint32 FSIsEof(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 errorMask)
|
||||||
{
|
{
|
||||||
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
|
StackAllocator<FSAsyncParamsNew_t, 1> asyncParams;
|
||||||
__FSAsyncToSyncInit(fsClient, fsCmdBlock, asyncParams);
|
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
|
||||||
sint32 fsAsyncRet = FSIsEofAsync(fsClient, fsCmdBlock, fileHandle, errorMask, asyncParams);
|
sint32 fsAsyncRet = FSIsEofAsync(fsClient, fsCmdBlock, fileHandle, errorMask, &asyncParams);
|
||||||
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
|
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)
|
IOS_ERROR _IPCDriver_SetupCmd_IOSIoctlv(IPCDriver& ipcDriver, IPCResourceBufferDescriptor* requestDescriptor, uint32 requestId, uint32 numIn, uint32 numOut, IPCIoctlVector* vec)
|
||||||
{
|
{
|
||||||
IPCCommandBody& cmdBody = requestDescriptor->resourcePtr->commandBody;
|
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
|
// set args
|
||||||
cmdBody.ppcVirt0 = MEMPTR<void>(vec).GetMPTR();
|
cmdBody.ppcVirt0 = MEMPTR<void>(vec).GetMPTR();
|
||||||
cmdBody.args[0] = requestId;
|
cmdBody.args[0] = requestId;
|
||||||
|
@ -195,7 +195,28 @@ namespace coreinit
|
|||||||
else if ((formatStr[0] == 'l' && formatStr[1] == 'l' && (formatStr[2] == 'x' || formatStr[2] == 'X')))
|
else if ((formatStr[0] == 'l' && formatStr[1] == 'l' && (formatStr[2] == 'x' || formatStr[2] == 'X')))
|
||||||
{
|
{
|
||||||
formatStr += 3;
|
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));
|
strncpy(tempFormat, formatStart, std::min((std::ptrdiff_t)sizeof(tempFormat) - 1, formatStr - formatStart));
|
||||||
if ((formatStr - formatStart) < sizeof(tempFormat))
|
if ((formatStr - formatStart) < sizeof(tempFormat))
|
||||||
tempFormat[(formatStr - formatStart)] = '\0';
|
tempFormat[(formatStr - formatStart)] = '\0';
|
||||||
|
@ -859,10 +859,10 @@ namespace H264
|
|||||||
return H264DEC_STATUS::SUCCESS;
|
return H264DEC_STATUS::SUCCESS;
|
||||||
}
|
}
|
||||||
StackAllocator<coreinit::OSEvent> executeDoneEvent;
|
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;
|
std::vector<H264AVCDecoder::DecodeResult> results;
|
||||||
auto asyncTask = std::async(std::launch::async, _async_H264DECEnd, executeDoneEvent.GetPointer(), session, ctx, &results);
|
auto asyncTask = std::async(std::launch::async, _async_H264DECEnd, executeDoneEvent.GetPointer(), session, ctx, &results);
|
||||||
coreinit::OSWaitEvent(executeDoneEvent);
|
coreinit::OSWaitEvent(&executeDoneEvent);
|
||||||
_ReleaseDecoderSession(session);
|
_ReleaseDecoderSession(session);
|
||||||
if (!results.empty())
|
if (!results.empty())
|
||||||
{
|
{
|
||||||
@ -977,9 +977,9 @@ namespace H264
|
|||||||
StackAllocator<H264DECFrameOutput, 8> stack_decodedFrameResult;
|
StackAllocator<H264DECFrameOutput, 8> stack_decodedFrameResult;
|
||||||
|
|
||||||
for (sint32 i = 0; i < outputFrameCount; i++)
|
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));
|
memset(frameOutput, 0x00, sizeof(H264DECFrameOutput));
|
||||||
frameOutput->imagePtr = (uint8*)decodeResult.imageOutput;
|
frameOutput->imagePtr = (uint8*)decodeResult.imageOutput;
|
||||||
frameOutput->result = 100;
|
frameOutput->result = 100;
|
||||||
@ -1022,10 +1022,10 @@ namespace H264
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
StackAllocator<coreinit::OSEvent> executeDoneEvent;
|
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;
|
H264AVCDecoder::DecodeResult decodeResult;
|
||||||
auto asyncTask = std::async(std::launch::async, _async_H264DECExecute, executeDoneEvent.GetPointer(), session, ctx, imageOutput , &decodeResult);
|
auto asyncTask = std::async(std::launch::async, _async_H264DECExecute, &executeDoneEvent, session, ctx, imageOutput , &decodeResult);
|
||||||
coreinit::OSWaitEvent(executeDoneEvent);
|
coreinit::OSWaitEvent(&executeDoneEvent);
|
||||||
_ReleaseDecoderSession(session);
|
_ReleaseDecoderSession(session);
|
||||||
if(decodeResult.frameReady)
|
if(decodeResult.frameReady)
|
||||||
H264DoFrameOutputCallback(ctx, decodeResult);
|
H264DoFrameOutputCallback(ctx, decodeResult);
|
||||||
|
@ -391,7 +391,7 @@ void nnActExport_GetMiiName(PPCInterpreter_t* hCPU)
|
|||||||
|
|
||||||
StackAllocator<FFLData_t> miiData;
|
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
|
// extract name
|
||||||
sint32 miiNameLength = 0;
|
sint32 miiNameLength = 0;
|
||||||
for (sint32 i = 0; i < MII_FFL_NAME_LENGTH; i++)
|
for (sint32 i = 0; i < MII_FFL_NAME_LENGTH; i++)
|
||||||
@ -414,7 +414,7 @@ void nnActExport_GetMiiNameEx(PPCInterpreter_t* hCPU)
|
|||||||
|
|
||||||
StackAllocator<FFLData_t> miiData;
|
StackAllocator<FFLData_t> miiData;
|
||||||
|
|
||||||
uint32 r = nn::act::GetMiiEx(miiData, slot);
|
uint32 r = nn::act::GetMiiEx(&miiData, slot);
|
||||||
// extract name
|
// extract name
|
||||||
sint32 miiNameLength = 0;
|
sint32 miiNameLength = 0;
|
||||||
for (sint32 i = 0; i < MII_FFL_NAME_LENGTH; i++)
|
for (sint32 i = 0; i < MII_FFL_NAME_LENGTH; i++)
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -47,10 +47,10 @@ namespace nn
|
|||||||
InitializeOliveRequest(req);
|
InitializeOliveRequest(req);
|
||||||
|
|
||||||
StackAllocator<coreinit::OSEvent> requestDoneEvent;
|
StackAllocator<coreinit::OSEvent> requestDoneEvent;
|
||||||
coreinit::OSInitEvent(requestDoneEvent, coreinit::OSEvent::EVENT_STATE::STATE_NOT_SIGNALED, coreinit::OSEvent::EVENT_MODE::MODE_MANUAL);
|
coreinit::OSInitEvent(&requestDoneEvent, coreinit::OSEvent::EVENT_STATE::STATE_NOT_SIGNALED, coreinit::OSEvent::EVENT_MODE::MODE_MANUAL);
|
||||||
std::future<sint32> requestRes = std::async(std::launch::async, DownloadCommunityDataList_AsyncRequest,
|
std::future<sint32> requestRes = std::async(std::launch::async, DownloadCommunityDataList_AsyncRequest,
|
||||||
std::ref(req), reqUrl, requestDoneEvent.GetPointer(), pOutList, pOutNum, numMaxList, pParam);
|
std::ref(req), reqUrl, requestDoneEvent.GetPointer(), pOutList, pOutNum, numMaxList, pParam);
|
||||||
coreinit::OSWaitEvent(requestDoneEvent);
|
coreinit::OSWaitEvent(&requestDoneEvent);
|
||||||
|
|
||||||
return requestRes.get();
|
return requestRes.get();
|
||||||
}
|
}
|
||||||
|
@ -199,9 +199,9 @@ namespace nn
|
|||||||
InitializeOliveRequest(req);
|
InitializeOliveRequest(req);
|
||||||
|
|
||||||
StackAllocator<coreinit::OSEvent> requestDoneEvent;
|
StackAllocator<coreinit::OSEvent> requestDoneEvent;
|
||||||
coreinit::OSInitEvent(requestDoneEvent, coreinit::OSEvent::EVENT_STATE::STATE_NOT_SIGNALED, coreinit::OSEvent::EVENT_MODE::MODE_MANUAL);
|
coreinit::OSInitEvent(&requestDoneEvent, coreinit::OSEvent::EVENT_STATE::STATE_NOT_SIGNALED, coreinit::OSEvent::EVENT_MODE::MODE_MANUAL);
|
||||||
std::future<sint32> requestRes = std::async(std::launch::async, MakeDiscoveryRequest_AsyncRequest, std::ref(req), requestUrl.c_str(), requestDoneEvent.GetPointer());
|
std::future<sint32> requestRes = std::async(std::launch::async, MakeDiscoveryRequest_AsyncRequest, std::ref(req), requestUrl.c_str(), requestDoneEvent.GetPointer());
|
||||||
coreinit::OSWaitEvent(requestDoneEvent);
|
coreinit::OSWaitEvent(&requestDoneEvent);
|
||||||
|
|
||||||
return requestRes.get();
|
return requestRes.get();
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ namespace nn
|
|||||||
// open archive
|
// open archive
|
||||||
g_offlineDBArchive = ZArchiveReader::OpenFromFile(ActiveSettings::GetUserDataPath("resources/miiverse/OfflineDB.zar"));
|
g_offlineDBArchive = ZArchiveReader::OpenFromFile(ActiveSettings::GetUserDataPath("resources/miiverse/OfflineDB.zar"));
|
||||||
if(!g_offlineDBArchive)
|
if(!g_offlineDBArchive)
|
||||||
cemuLog_log(LogType::Force, "Failed to open resources/miiverse/OfflineDB.zar. Miiverse posts will not be available");
|
cemuLog_log(LogType::Force, "Offline miiverse posts are not available");
|
||||||
g_offlineDBInitialized = true;
|
g_offlineDBInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,9 +175,9 @@ namespace nn
|
|||||||
return OLV_RESULT_SUCCESS; // the offlineDB doesn't contain any self posts
|
return OLV_RESULT_SUCCESS; // the offlineDB doesn't contain any self posts
|
||||||
|
|
||||||
StackAllocator<coreinit::OSEvent> doneEvent;
|
StackAllocator<coreinit::OSEvent> doneEvent;
|
||||||
coreinit::OSInitEvent(doneEvent, coreinit::OSEvent::EVENT_STATE::STATE_NOT_SIGNALED, coreinit::OSEvent::EVENT_MODE::MODE_MANUAL);
|
coreinit::OSInitEvent(&doneEvent, coreinit::OSEvent::EVENT_STATE::STATE_NOT_SIGNALED, coreinit::OSEvent::EVENT_MODE::MODE_MANUAL);
|
||||||
auto asyncTask = std::async(std::launch::async, _Async_OfflineDB_DownloadPostDataListParam_DownloadPostDataList, doneEvent.GetPointer(), downloadedTopicData, downloadedPostData, postCountOut, maxCount, param);
|
auto asyncTask = std::async(std::launch::async, _Async_OfflineDB_DownloadPostDataListParam_DownloadPostDataList, doneEvent.GetPointer(), downloadedTopicData, downloadedPostData, postCountOut, maxCount, param);
|
||||||
coreinit::OSWaitEvent(doneEvent);
|
coreinit::OSWaitEvent(&doneEvent);
|
||||||
nnResult r = asyncTask.get();
|
nnResult r = asyncTask.get();
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -204,9 +204,9 @@ namespace nn
|
|||||||
nnResult OfflineDB_DownloadPostDataListParam_DownloadExternalImageData(DownloadedDataBase* _this, void* imageDataOut, uint32be* imageSizeOut, uint32 maxSize)
|
nnResult OfflineDB_DownloadPostDataListParam_DownloadExternalImageData(DownloadedDataBase* _this, void* imageDataOut, uint32be* imageSizeOut, uint32 maxSize)
|
||||||
{
|
{
|
||||||
StackAllocator<coreinit::OSEvent> doneEvent;
|
StackAllocator<coreinit::OSEvent> doneEvent;
|
||||||
coreinit::OSInitEvent(doneEvent, coreinit::OSEvent::EVENT_STATE::STATE_NOT_SIGNALED, coreinit::OSEvent::EVENT_MODE::MODE_MANUAL);
|
coreinit::OSInitEvent(&doneEvent, coreinit::OSEvent::EVENT_STATE::STATE_NOT_SIGNALED, coreinit::OSEvent::EVENT_MODE::MODE_MANUAL);
|
||||||
auto asyncTask = std::async(std::launch::async, _Async_OfflineDB_DownloadPostDataListParam_DownloadExternalImageData, doneEvent.GetPointer(), _this, imageDataOut, imageSizeOut, maxSize);
|
auto asyncTask = std::async(std::launch::async, _Async_OfflineDB_DownloadPostDataListParam_DownloadExternalImageData, doneEvent.GetPointer(), _this, imageDataOut, imageSizeOut, maxSize);
|
||||||
coreinit::OSWaitEvent(doneEvent);
|
coreinit::OSWaitEvent(&doneEvent);
|
||||||
nnResult r = asyncTask.get();
|
nnResult r = asyncTask.get();
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -54,9 +54,9 @@ namespace nn
|
|||||||
InitializeOliveRequest(req);
|
InitializeOliveRequest(req);
|
||||||
|
|
||||||
StackAllocator<coreinit::OSEvent> requestDoneEvent;
|
StackAllocator<coreinit::OSEvent> requestDoneEvent;
|
||||||
coreinit::OSInitEvent(requestDoneEvent, coreinit::OSEvent::EVENT_STATE::STATE_NOT_SIGNALED, coreinit::OSEvent::EVENT_MODE::MODE_MANUAL);
|
coreinit::OSInitEvent(&requestDoneEvent, coreinit::OSEvent::EVENT_STATE::STATE_NOT_SIGNALED, coreinit::OSEvent::EVENT_MODE::MODE_MANUAL);
|
||||||
std::future<sint32> requestRes = std::async(std::launch::async, UploadCommunityData_AsyncRequest, std::ref(req), requestUrl, requestDoneEvent.GetPointer(), pOutData, pParam);
|
std::future<sint32> requestRes = std::async(std::launch::async, UploadCommunityData_AsyncRequest, std::ref(req), requestUrl, requestDoneEvent.GetPointer(), pOutData, pParam);
|
||||||
coreinit::OSWaitEvent(requestDoneEvent);
|
coreinit::OSWaitEvent(&requestDoneEvent);
|
||||||
|
|
||||||
return requestRes.get();
|
return requestRes.get();
|
||||||
}
|
}
|
||||||
|
@ -44,9 +44,9 @@ namespace nn
|
|||||||
InitializeOliveRequest(req);
|
InitializeOliveRequest(req);
|
||||||
|
|
||||||
StackAllocator<coreinit::OSEvent> requestDoneEvent;
|
StackAllocator<coreinit::OSEvent> requestDoneEvent;
|
||||||
coreinit::OSInitEvent(requestDoneEvent, coreinit::OSEvent::EVENT_STATE::STATE_NOT_SIGNALED, coreinit::OSEvent::EVENT_MODE::MODE_MANUAL);
|
coreinit::OSInitEvent(&requestDoneEvent, coreinit::OSEvent::EVENT_STATE::STATE_NOT_SIGNALED, coreinit::OSEvent::EVENT_MODE::MODE_MANUAL);
|
||||||
std::future<sint32> requestRes = std::async(std::launch::async, UploadFavoriteToCommunityData_AsyncRequest, std::ref(req), requestUrl, requestDoneEvent.GetPointer(), pOutData, pParam);
|
std::future<sint32> requestRes = std::async(std::launch::async, UploadFavoriteToCommunityData_AsyncRequest, std::ref(req), requestUrl, requestDoneEvent.GetPointer(), pOutData, pParam);
|
||||||
coreinit::OSWaitEvent(requestDoneEvent);
|
coreinit::OSWaitEvent(&requestDoneEvent);
|
||||||
|
|
||||||
return requestRes.get();
|
return requestRes.get();
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@ const std::map<LogType, std::string> g_logging_window_mapping
|
|||||||
{LogType::CoreinitMP, "Coreinit MP"},
|
{LogType::CoreinitMP, "Coreinit MP"},
|
||||||
{LogType::CoreinitThread, "Coreinit Thread"},
|
{LogType::CoreinitThread, "Coreinit Thread"},
|
||||||
{LogType::NN_NFP, "nn::nfp"},
|
{LogType::NN_NFP, "nn::nfp"},
|
||||||
|
{LogType::NN_FP, "nn::fp"},
|
||||||
{LogType::GX2, "GX2"},
|
{LogType::GX2, "GX2"},
|
||||||
{LogType::SoundAPI, "Audio"},
|
{LogType::SoundAPI, "Audio"},
|
||||||
{LogType::InputAPI, "Input"},
|
{LogType::InputAPI, "Input"},
|
||||||
|
@ -34,6 +34,7 @@ enum class LogType : sint32
|
|||||||
NN_PDM = 21,
|
NN_PDM = 21,
|
||||||
NN_OLV = 23,
|
NN_OLV = 23,
|
||||||
NN_NFP = 13,
|
NN_NFP = 13,
|
||||||
|
NN_FP = 24,
|
||||||
|
|
||||||
TextureReadback = 29,
|
TextureReadback = 29,
|
||||||
|
|
||||||
|
@ -358,7 +358,7 @@ namespace NAPI
|
|||||||
std::string_view port = tokenNode.child_value("port");
|
std::string_view port = tokenNode.child_value("port");
|
||||||
std::string_view token = tokenNode.child_value("token");
|
std::string_view token = tokenNode.child_value("token");
|
||||||
|
|
||||||
std::memset(&result.nexToken, 0, sizeof(result.nexToken));
|
memset(&result.nexToken, 0, sizeof(ACTNexToken));
|
||||||
if (host.size() > 15)
|
if (host.size() > 15)
|
||||||
cemuLog_log(LogType::Force, "NexToken response: host field too long");
|
cemuLog_log(LogType::Force, "NexToken response: host field too long");
|
||||||
if (nex_password.size() > 64)
|
if (nex_password.size() > 64)
|
||||||
|
@ -160,11 +160,10 @@ bool nexService::isMarkedForDestruction()
|
|||||||
|
|
||||||
void nexService::callMethod(uint8 protocolId, uint32 methodId, nexPacketBuffer* parameter, void(*nexServiceResponse)(nexService* nex, nexServiceResponse_t* serviceResponse), void* custom, bool callHandlerIfError)
|
void nexService::callMethod(uint8 protocolId, uint32 methodId, nexPacketBuffer* parameter, void(*nexServiceResponse)(nexService* nex, nexServiceResponse_t* serviceResponse), void* custom, bool callHandlerIfError)
|
||||||
{
|
{
|
||||||
// add to queue
|
|
||||||
queuedRequest_t queueRequest = { 0 };
|
queuedRequest_t queueRequest = { 0 };
|
||||||
queueRequest.protocolId = protocolId;
|
queueRequest.protocolId = protocolId;
|
||||||
queueRequest.methodId = methodId;
|
queueRequest.methodId = methodId;
|
||||||
queueRequest.parameterData = std::vector<uint8>(parameter->getDataPtr(), parameter->getDataPtr() + parameter->getWriteIndex());
|
queueRequest.parameterData.assign(parameter->getDataPtr(), parameter->getDataPtr() + parameter->getWriteIndex());
|
||||||
queueRequest.nexServiceResponse = nexServiceResponse;
|
queueRequest.nexServiceResponse = nexServiceResponse;
|
||||||
queueRequest.custom = custom;
|
queueRequest.custom = custom;
|
||||||
queueRequest.callHandlerIfError = callHandlerIfError;
|
queueRequest.callHandlerIfError = callHandlerIfError;
|
||||||
@ -175,11 +174,10 @@ void nexService::callMethod(uint8 protocolId, uint32 methodId, nexPacketBuffer*
|
|||||||
|
|
||||||
void nexService::callMethod(uint8 protocolId, uint32 methodId, nexPacketBuffer* parameter, std::function<void(nexServiceResponse_t*)> cb, bool callHandlerIfError)
|
void nexService::callMethod(uint8 protocolId, uint32 methodId, nexPacketBuffer* parameter, std::function<void(nexServiceResponse_t*)> cb, bool callHandlerIfError)
|
||||||
{
|
{
|
||||||
// add to queue
|
|
||||||
queuedRequest_t queueRequest = { 0 };
|
queuedRequest_t queueRequest = { 0 };
|
||||||
queueRequest.protocolId = protocolId;
|
queueRequest.protocolId = protocolId;
|
||||||
queueRequest.methodId = methodId;
|
queueRequest.methodId = methodId;
|
||||||
queueRequest.parameterData = std::vector<uint8>(parameter->getDataPtr(), parameter->getDataPtr() + parameter->getWriteIndex());
|
queueRequest.parameterData.assign(parameter->getDataPtr(), parameter->getDataPtr() + parameter->getWriteIndex());
|
||||||
queueRequest.nexServiceResponse = nullptr;
|
queueRequest.nexServiceResponse = nullptr;
|
||||||
queueRequest.cb2 = cb;
|
queueRequest.cb2 = cb;
|
||||||
queueRequest.callHandlerIfError = callHandlerIfError;
|
queueRequest.callHandlerIfError = callHandlerIfError;
|
||||||
|
@ -274,8 +274,7 @@ void NexFriends::handleResponse_getAllInformation(nexServiceResponse_t* response
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
NexFriends* session = (NexFriends*)nexFriends;
|
NexFriends* session = (NexFriends*)nexFriends;
|
||||||
|
session->myPreference = nexPrincipalPreference(&response->data);
|
||||||
nexPrincipalPreference preference(&response->data);
|
|
||||||
nexComment comment(&response->data);
|
nexComment comment(&response->data);
|
||||||
if (response->data.hasReadOutOfBounds())
|
if (response->data.hasReadOutOfBounds())
|
||||||
return;
|
return;
|
||||||
@ -290,29 +289,21 @@ void NexFriends::handleResponse_getAllInformation(nexServiceResponse_t* response
|
|||||||
uint32 friendCount = response->data.readU32();
|
uint32 friendCount = response->data.readU32();
|
||||||
session->list_friends.resize(friendCount);
|
session->list_friends.resize(friendCount);
|
||||||
for (uint32 i = 0; i < friendCount; i++)
|
for (uint32 i = 0; i < friendCount; i++)
|
||||||
{
|
|
||||||
session->list_friends[i].readData(&response->data);
|
session->list_friends[i].readData(&response->data);
|
||||||
}
|
|
||||||
// friend requests (outgoing)
|
// friend requests (outgoing)
|
||||||
uint32 friendRequestsOutCount = response->data.readU32();
|
uint32 friendRequestsOutCount = response->data.readU32();
|
||||||
if (response->data.hasReadOutOfBounds())
|
if (response->data.hasReadOutOfBounds())
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
session->list_friendReqOutgoing.resize(friendRequestsOutCount);
|
session->list_friendReqOutgoing.resize(friendRequestsOutCount);
|
||||||
for (uint32 i = 0; i < friendRequestsOutCount; i++)
|
for (uint32 i = 0; i < friendRequestsOutCount; i++)
|
||||||
{
|
|
||||||
session->list_friendReqOutgoing[i].readData(&response->data);
|
session->list_friendReqOutgoing[i].readData(&response->data);
|
||||||
}
|
|
||||||
// friend requests (incoming)
|
// friend requests (incoming)
|
||||||
uint32 friendRequestsInCount = response->data.readU32();
|
uint32 friendRequestsInCount = response->data.readU32();
|
||||||
if (response->data.hasReadOutOfBounds())
|
if (response->data.hasReadOutOfBounds())
|
||||||
return;
|
return;
|
||||||
session->list_friendReqIncoming.resize(friendRequestsInCount);
|
session->list_friendReqIncoming.resize(friendRequestsInCount);
|
||||||
for (uint32 i = 0; i < friendRequestsInCount; i++)
|
for (uint32 i = 0; i < friendRequestsInCount; i++)
|
||||||
{
|
|
||||||
session->list_friendReqIncoming[i].readData(&response->data);
|
session->list_friendReqIncoming[i].readData(&response->data);
|
||||||
}
|
|
||||||
if (response->data.hasReadOutOfBounds())
|
if (response->data.hasReadOutOfBounds())
|
||||||
return;
|
return;
|
||||||
// blacklist
|
// blacklist
|
||||||
@ -336,7 +327,7 @@ void NexFriends::handleResponse_getAllInformation(nexServiceResponse_t* response
|
|||||||
if (isPreferenceInvalid)
|
if (isPreferenceInvalid)
|
||||||
{
|
{
|
||||||
cemuLog_log(LogType::Force, "NEX: First time login into friend account, setting up default preferences");
|
cemuLog_log(LogType::Force, "NEX: First time login into friend account, setting up default preferences");
|
||||||
session->updatePreferences(nexPrincipalPreference(1, 1, 0));
|
session->updatePreferencesAsync(nexPrincipalPreference(1, 1, 0), [](RpcErrorCode err){});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session->firstInformationRequest == false)
|
if (session->firstInformationRequest == false)
|
||||||
@ -377,20 +368,27 @@ bool NexFriends::requestGetAllInformation(std::function<void(uint32)> cb)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NexFriends::handleResponse_updatePreferences(nexServiceResponse_t* response, NexFriends* nexFriends, std::function<void(uint32)> cb)
|
bool NexFriends::updatePreferencesAsync(nexPrincipalPreference newPreferences, std::function<void(RpcErrorCode)> cb)
|
||||||
{
|
|
||||||
// todo
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NexFriends::updatePreferences(const nexPrincipalPreference& newPreferences)
|
|
||||||
{
|
{
|
||||||
uint8 tempNexBufferArray[1024];
|
uint8 tempNexBufferArray[1024];
|
||||||
nexPacketBuffer packetBuffer(tempNexBufferArray, sizeof(tempNexBufferArray), true);
|
nexPacketBuffer packetBuffer(tempNexBufferArray, sizeof(tempNexBufferArray), true);
|
||||||
newPreferences.writeData(&packetBuffer);
|
newPreferences.writeData(&packetBuffer);
|
||||||
nexCon->callMethod(NEX_PROTOCOL_FRIENDS_WIIU, 16, &packetBuffer, std::bind(handleResponse_updatePreferences, std::placeholders::_1, this, nullptr), true);
|
nexCon->callMethod(NEX_PROTOCOL_FRIENDS_WIIU, 16, &packetBuffer, [this, cb, newPreferences](nexServiceResponse_t* response) -> void
|
||||||
|
{
|
||||||
|
if (!response->isSuccessful)
|
||||||
|
return cb(NexFriends::ERR_RPC_FAILED);
|
||||||
|
this->myPreference = newPreferences;
|
||||||
|
return cb(NexFriends::ERR_NONE);
|
||||||
|
}, true);
|
||||||
|
// TEST
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NexFriends::getMyPreference(nexPrincipalPreference& preference)
|
||||||
|
{
|
||||||
|
preference = myPreference;
|
||||||
|
}
|
||||||
|
|
||||||
bool NexFriends::addProvisionalFriendByPidGuessed(uint32 principalId)
|
bool NexFriends::addProvisionalFriendByPidGuessed(uint32 principalId)
|
||||||
{
|
{
|
||||||
uint8 tempNexBufferArray[512];
|
uint8 tempNexBufferArray[512];
|
||||||
@ -401,6 +399,7 @@ bool NexFriends::addProvisionalFriendByPidGuessed(uint32 principalId)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// returns true once connection is established and friend list data is available
|
||||||
bool NexFriends::isOnline()
|
bool NexFriends::isOnline()
|
||||||
{
|
{
|
||||||
return isCurrentlyConnected && hasData;
|
return isCurrentlyConnected && hasData;
|
||||||
@ -683,7 +682,7 @@ bool NexFriends::getFriendRequestByPID(nexFriendRequest& friendRequestData, bool
|
|||||||
{
|
{
|
||||||
friendRequestData = it;
|
friendRequestData = it;
|
||||||
if (isIncoming)
|
if (isIncoming)
|
||||||
*isIncoming = false;
|
*isIncoming = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -731,7 +730,7 @@ void addProvisionalFriendHandler(nexServiceResponse_t* nexResponse, std::functio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NexFriends::addProvisionalFriend(char* name, std::function<void(uint32)> cb)
|
bool NexFriends::addProvisionalFriend(char* name, std::function<void(RpcErrorCode)> cb)
|
||||||
{
|
{
|
||||||
if (nexCon == nullptr || nexCon->getState() != nexService::STATE_CONNECTED)
|
if (nexCon == nullptr || nexCon->getState() != nexService::STATE_CONNECTED)
|
||||||
{
|
{
|
||||||
@ -754,12 +753,11 @@ void addFriendRequestHandler(nexServiceResponse_t* nexResponse, NexFriends* nexF
|
|||||||
{
|
{
|
||||||
// todo: Properly handle returned error code
|
// todo: Properly handle returned error code
|
||||||
cb(NexFriends::ERR_RPC_FAILED);
|
cb(NexFriends::ERR_RPC_FAILED);
|
||||||
// refresh the list
|
nexFriends->requestGetAllInformation(); // refresh friend list and send add/remove notifications
|
||||||
nexFriends->requestGetAllInformation();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NexFriends::addFriendRequest(uint32 pid, const char* comment, std::function<void(uint32)> cb)
|
void NexFriends::addFriendRequest(uint32 pid, const char* comment, std::function<void(RpcErrorCode)> cb)
|
||||||
{
|
{
|
||||||
if (nexCon == nullptr || nexCon->getState() != nexService::STATE_CONNECTED)
|
if (nexCon == nullptr || nexCon->getState() != nexService::STATE_CONNECTED)
|
||||||
{
|
{
|
||||||
@ -779,72 +777,31 @@ void NexFriends::addFriendRequest(uint32 pid, const char* comment, std::function
|
|||||||
nexCon->callMethod(NEX_PROTOCOL_FRIENDS_WIIU, 5, &packetBuffer, std::bind(addFriendRequestHandler, std::placeholders::_1, this, cb), true);
|
nexCon->callMethod(NEX_PROTOCOL_FRIENDS_WIIU, 5, &packetBuffer, std::bind(addFriendRequestHandler, std::placeholders::_1, this, cb), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct
|
void NexFriends::requestPrincipleBaseInfoByPID(uint32* pidList, sint32 count, const std::function<void(RpcErrorCode result, std::span<nexPrincipalBasicInfo> basicInfo)>& cb)
|
||||||
{
|
|
||||||
NEXFRIENDS_CALLBACK cb;
|
|
||||||
void* customParam;
|
|
||||||
NexFriends* nexFriends;
|
|
||||||
// command specific
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
nexPrincipalBasicInfo* basicInfo;
|
|
||||||
sint32 count;
|
|
||||||
}principalBaseInfo;
|
|
||||||
}nexFriendsCallInfo_t;
|
|
||||||
|
|
||||||
void NexFriends_handleResponse_requestPrincipleBaseInfoByPID(nexService* nex, nexServiceResponse_t* response)
|
|
||||||
{
|
|
||||||
nexFriendsCallInfo_t* callInfo = (nexFriendsCallInfo_t*)response->custom;
|
|
||||||
if (response->isSuccessful == false)
|
|
||||||
{
|
|
||||||
// handle error case
|
|
||||||
callInfo->cb(callInfo->nexFriends, NexFriends::ERR_RPC_FAILED, callInfo->customParam);
|
|
||||||
free(callInfo);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// process result
|
|
||||||
uint32 count = response->data.readU32();
|
|
||||||
if (count != callInfo->principalBaseInfo.count)
|
|
||||||
{
|
|
||||||
callInfo->cb(callInfo->nexFriends, NexFriends::ERR_UNEXPECTED_RESULT, callInfo->customParam);
|
|
||||||
free(callInfo);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (uint32 i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
callInfo->principalBaseInfo.basicInfo[i].readData(&response->data);
|
|
||||||
}
|
|
||||||
if (response->data.hasReadOutOfBounds())
|
|
||||||
{
|
|
||||||
callInfo->cb(callInfo->nexFriends, NexFriends::ERR_UNEXPECTED_RESULT, callInfo->customParam);
|
|
||||||
free(callInfo);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// callback
|
|
||||||
callInfo->cb(callInfo->nexFriends, NexFriends::ERR_NONE, callInfo->customParam);
|
|
||||||
free(callInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NexFriends::requestPrincipleBaseInfoByPID(nexPrincipalBasicInfo* basicInfo, uint32* pidList, sint32 count, NEXFRIENDS_CALLBACK cb, void* customParam)
|
|
||||||
{
|
{
|
||||||
if (nexCon == nullptr || nexCon->getState() != nexService::STATE_CONNECTED)
|
if (nexCon == nullptr || nexCon->getState() != nexService::STATE_CONNECTED)
|
||||||
{
|
return cb(ERR_NOT_CONNECTED, {});
|
||||||
// not connected
|
|
||||||
cb(this, ERR_NOT_CONNECTED, customParam);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
uint8 tempNexBufferArray[512];
|
uint8 tempNexBufferArray[512];
|
||||||
nexPacketBuffer packetBuffer(tempNexBufferArray, sizeof(tempNexBufferArray), true);
|
nexPacketBuffer packetBuffer(tempNexBufferArray, sizeof(tempNexBufferArray), true);
|
||||||
packetBuffer.writeU32(count);
|
packetBuffer.writeU32(count);
|
||||||
for(sint32 i=0; i<count; i++)
|
for(sint32 i=0; i<count; i++)
|
||||||
packetBuffer.writeU32(pidList[i]);
|
packetBuffer.writeU32(pidList[i]);
|
||||||
nexFriendsCallInfo_t* callInfo = (nexFriendsCallInfo_t*)malloc(sizeof(nexFriendsCallInfo_t));
|
nexCon->callMethod(NEX_PROTOCOL_FRIENDS_WIIU, 17, &packetBuffer, [cb, count](nexServiceResponse_t* response)
|
||||||
callInfo->principalBaseInfo.basicInfo = basicInfo;
|
{
|
||||||
callInfo->principalBaseInfo.count = count;
|
if (!response->isSuccessful)
|
||||||
callInfo->cb = cb;
|
return cb(NexFriends::ERR_RPC_FAILED, {});
|
||||||
callInfo->customParam = customParam;
|
// process result
|
||||||
callInfo->nexFriends = this;
|
uint32 resultCount = response->data.readU32();
|
||||||
nexCon->callMethod(NEX_PROTOCOL_FRIENDS_WIIU, 17, &packetBuffer, NexFriends_handleResponse_requestPrincipleBaseInfoByPID, callInfo, true);
|
if (resultCount != count)
|
||||||
|
return cb(NexFriends::ERR_UNEXPECTED_RESULT, {});
|
||||||
|
std::vector<nexPrincipalBasicInfo> nexBasicInfo;
|
||||||
|
nexBasicInfo.resize(count);
|
||||||
|
for (uint32 i = 0; i < resultCount; i++)
|
||||||
|
nexBasicInfo[i].readData(&response->data);
|
||||||
|
if (response->data.hasReadOutOfBounds())
|
||||||
|
return cb(NexFriends::ERR_UNEXPECTED_RESULT, {});
|
||||||
|
return cb(NexFriends::ERR_NONE, nexBasicInfo);
|
||||||
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void genericFriendServiceNoResponseHandler(nexServiceResponse_t* nexResponse, std::function<void(uint32)> cb)
|
void genericFriendServiceNoResponseHandler(nexServiceResponse_t* nexResponse, std::function<void(uint32)> cb)
|
||||||
@ -858,7 +815,7 @@ void genericFriendServiceNoResponseHandler(nexServiceResponse_t* nexResponse, st
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NexFriends::removeFriend(uint32 pid, std::function<void(uint32)> cb)
|
void NexFriends::removeFriend(uint32 pid, std::function<void(RpcErrorCode)> cb)
|
||||||
{
|
{
|
||||||
if (nexCon == nullptr || nexCon->getState() != nexService::STATE_CONNECTED)
|
if (nexCon == nullptr || nexCon->getState() != nexService::STATE_CONNECTED)
|
||||||
{
|
{
|
||||||
@ -869,10 +826,20 @@ void NexFriends::removeFriend(uint32 pid, std::function<void(uint32)> cb)
|
|||||||
uint8 tempNexBufferArray[512];
|
uint8 tempNexBufferArray[512];
|
||||||
nexPacketBuffer packetBuffer(tempNexBufferArray, sizeof(tempNexBufferArray), true);
|
nexPacketBuffer packetBuffer(tempNexBufferArray, sizeof(tempNexBufferArray), true);
|
||||||
packetBuffer.writeU32(pid);
|
packetBuffer.writeU32(pid);
|
||||||
nexCon->callMethod(NEX_PROTOCOL_FRIENDS_WIIU, 4, &packetBuffer, std::bind(genericFriendServiceNoResponseHandler, std::placeholders::_1, cb), true);
|
nexCon->callMethod(NEX_PROTOCOL_FRIENDS_WIIU, 4, &packetBuffer, [this, cb](nexServiceResponse_t* response) -> void
|
||||||
|
{
|
||||||
|
if (!response->isSuccessful)
|
||||||
|
return cb(NexFriends::ERR_RPC_FAILED);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cb(NexFriends::ERR_NONE);
|
||||||
|
this->requestGetAllInformation(); // refresh friend list and send add/remove notifications
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NexFriends::cancelOutgoingProvisionalFriendRequest(uint32 pid, std::function<void(uint32)> cb)
|
void NexFriends::cancelOutgoingProvisionalFriendRequest(uint32 pid, std::function<void(RpcErrorCode)> cb)
|
||||||
{
|
{
|
||||||
if (nexCon == nullptr || nexCon->getState() != nexService::STATE_CONNECTED)
|
if (nexCon == nullptr || nexCon->getState() != nexService::STATE_CONNECTED)
|
||||||
{
|
{
|
||||||
@ -883,53 +850,63 @@ void NexFriends::cancelOutgoingProvisionalFriendRequest(uint32 pid, std::functio
|
|||||||
uint8 tempNexBufferArray[512];
|
uint8 tempNexBufferArray[512];
|
||||||
nexPacketBuffer packetBuffer(tempNexBufferArray, sizeof(tempNexBufferArray), true);
|
nexPacketBuffer packetBuffer(tempNexBufferArray, sizeof(tempNexBufferArray), true);
|
||||||
packetBuffer.writeU32(pid);
|
packetBuffer.writeU32(pid);
|
||||||
nexCon->callMethod(NEX_PROTOCOL_FRIENDS_WIIU, 4, &packetBuffer, std::bind(genericFriendServiceNoResponseHandler, std::placeholders::_1, cb), true);
|
nexCon->callMethod(NEX_PROTOCOL_FRIENDS_WIIU, 4, &packetBuffer, [cb](nexServiceResponse_t* response) -> void
|
||||||
|
{
|
||||||
|
if (!response->isSuccessful)
|
||||||
|
return cb(NexFriends::ERR_RPC_FAILED);
|
||||||
|
else
|
||||||
|
return cb(NexFriends::ERR_NONE);
|
||||||
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NexFriends::acceptFriendRequest(uint64 messageId, std::function<void(uint32)> cb)
|
void NexFriends::acceptFriendRequest(uint64 messageId, std::function<void(RpcErrorCode)> cb)
|
||||||
{
|
{
|
||||||
if (nexCon == nullptr || nexCon->getState() != nexService::STATE_CONNECTED)
|
if (nexCon == nullptr || nexCon->getState() != nexService::STATE_CONNECTED)
|
||||||
{
|
return cb(ERR_NOT_CONNECTED);
|
||||||
// not connected
|
|
||||||
cb(ERR_NOT_CONNECTED);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
uint8 tempNexBufferArray[128];
|
uint8 tempNexBufferArray[128];
|
||||||
nexPacketBuffer packetBuffer(tempNexBufferArray, sizeof(tempNexBufferArray), true);
|
nexPacketBuffer packetBuffer(tempNexBufferArray, sizeof(tempNexBufferArray), true);
|
||||||
packetBuffer.writeU64(messageId);
|
packetBuffer.writeU64(messageId);
|
||||||
nexCon->callMethod(NEX_PROTOCOL_FRIENDS_WIIU, 7, &packetBuffer, std::bind(genericFriendServiceNoResponseHandler, std::placeholders::_1, cb), true);
|
nexCon->callMethod(NEX_PROTOCOL_FRIENDS_WIIU, 7, &packetBuffer, [cb](nexServiceResponse_t* response) -> void
|
||||||
|
{
|
||||||
|
if (!response->isSuccessful)
|
||||||
|
return cb(NexFriends::ERR_RPC_FAILED);
|
||||||
|
else
|
||||||
|
return cb(NexFriends::ERR_NONE);
|
||||||
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void markFriendRequestsAsReceivedHandler(nexServiceResponse_t* nexResponse, std::function<void(uint32)> cb)
|
void NexFriends::deleteFriendRequest(uint64 messageId, std::function<void(RpcErrorCode)> cb)
|
||||||
{
|
|
||||||
if (nexResponse->isSuccessful)
|
|
||||||
cb(0);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// todo: Properly handle returned error code
|
|
||||||
cb(NexFriends::ERR_RPC_FAILED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void NexFriends::markFriendRequestsAsReceived(uint64* messageIdList, sint32 count, std::function<void(uint32)> cb)
|
|
||||||
{
|
{
|
||||||
if (nexCon == nullptr || nexCon->getState() != nexService::STATE_CONNECTED)
|
if (nexCon == nullptr || nexCon->getState() != nexService::STATE_CONNECTED)
|
||||||
{
|
return cb(ERR_NOT_CONNECTED);
|
||||||
// not connected
|
uint8 tempNexBufferArray[128];
|
||||||
cb(ERR_NOT_CONNECTED);
|
nexPacketBuffer packetBuffer(tempNexBufferArray, sizeof(tempNexBufferArray), true);
|
||||||
return;
|
packetBuffer.writeU64(messageId);
|
||||||
}
|
nexCon->callMethod(NEX_PROTOCOL_FRIENDS_WIIU, 8, &packetBuffer, [this, cb](nexServiceResponse_t* response) -> void
|
||||||
|
{
|
||||||
|
if (!response->isSuccessful)
|
||||||
|
return cb(NexFriends::ERR_RPC_FAILED);
|
||||||
|
cb(NexFriends::ERR_NONE);
|
||||||
|
this->requestGetAllInformation(); // refresh friend list and send add/remove notifications
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NexFriends::markFriendRequestsAsReceived(uint64* messageIdList, sint32 count, std::function<void(RpcErrorCode)> cb)
|
||||||
|
{
|
||||||
|
if (nexCon == nullptr || nexCon->getState() != nexService::STATE_CONNECTED)
|
||||||
|
return cb(ERR_NOT_CONNECTED);
|
||||||
uint8 tempNexBufferArray[1024];
|
uint8 tempNexBufferArray[1024];
|
||||||
nexPacketBuffer packetBuffer(tempNexBufferArray, sizeof(tempNexBufferArray), true);
|
nexPacketBuffer packetBuffer(tempNexBufferArray, sizeof(tempNexBufferArray), true);
|
||||||
packetBuffer.writeU32(count);
|
packetBuffer.writeU32(count);
|
||||||
for(sint32 i=0; i<count; i++)
|
for(sint32 i=0; i<count; i++)
|
||||||
packetBuffer.writeU64(messageIdList[i]);
|
packetBuffer.writeU64(messageIdList[i]);
|
||||||
nexCon->callMethod(NEX_PROTOCOL_FRIENDS_WIIU, 10, &packetBuffer, std::bind(markFriendRequestsAsReceivedHandler, std::placeholders::_1, cb), true);
|
nexCon->callMethod(NEX_PROTOCOL_FRIENDS_WIIU, 10, &packetBuffer, [cb](nexServiceResponse_t* response) -> void
|
||||||
}
|
{
|
||||||
|
if (!response->isSuccessful)
|
||||||
void genericFriendServiceNoResponseHandlerWithoutCB(nexServiceResponse_t* nexResponse)
|
return cb(NexFriends::ERR_RPC_FAILED);
|
||||||
{
|
else
|
||||||
|
return cb(NexFriends::ERR_NONE);
|
||||||
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NexFriends::updateMyPresence(nexPresenceV2& myPresence)
|
void NexFriends::updateMyPresence(nexPresenceV2& myPresence)
|
||||||
@ -943,7 +920,7 @@ void NexFriends::updateMyPresence(nexPresenceV2& myPresence)
|
|||||||
uint8 tempNexBufferArray[1024];
|
uint8 tempNexBufferArray[1024];
|
||||||
nexPacketBuffer packetBuffer(tempNexBufferArray, sizeof(tempNexBufferArray), true);
|
nexPacketBuffer packetBuffer(tempNexBufferArray, sizeof(tempNexBufferArray), true);
|
||||||
myPresence.writeData(&packetBuffer);
|
myPresence.writeData(&packetBuffer);
|
||||||
nexCon->callMethod(NEX_PROTOCOL_FRIENDS_WIIU, 13, &packetBuffer, std::bind(genericFriendServiceNoResponseHandlerWithoutCB, std::placeholders::_1), false);
|
nexCon->callMethod(NEX_PROTOCOL_FRIENDS_WIIU, 13, &packetBuffer, +[](nexServiceResponse_t* nexResponse){}, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NexFriends::update()
|
void NexFriends::update()
|
||||||
|
@ -248,9 +248,9 @@ public:
|
|||||||
|
|
||||||
nexPrincipalPreference(uint8 ukn0, uint8 ukn1, uint8 ukn2)
|
nexPrincipalPreference(uint8 ukn0, uint8 ukn1, uint8 ukn2)
|
||||||
{
|
{
|
||||||
this->ukn0 = ukn0;
|
this->showOnline = ukn0;
|
||||||
this->ukn1 = ukn1;
|
this->showGame = ukn1;
|
||||||
this->ukn2 = ukn2;
|
this->blockFriendRequests = ukn2;
|
||||||
}
|
}
|
||||||
|
|
||||||
nexPrincipalPreference(nexPacketBuffer* pb)
|
nexPrincipalPreference(nexPacketBuffer* pb)
|
||||||
@ -260,21 +260,21 @@ public:
|
|||||||
|
|
||||||
void writeData(nexPacketBuffer* pb) const override
|
void writeData(nexPacketBuffer* pb) const override
|
||||||
{
|
{
|
||||||
pb->writeU8(ukn0);
|
pb->writeU8(showOnline);
|
||||||
pb->writeU8(ukn1);
|
pb->writeU8(showGame);
|
||||||
pb->writeU8(ukn2);
|
pb->writeU8(blockFriendRequests);
|
||||||
}
|
}
|
||||||
|
|
||||||
void readData(nexPacketBuffer* pb) override
|
void readData(nexPacketBuffer* pb) override
|
||||||
{
|
{
|
||||||
ukn0 = pb->readU8();
|
showOnline = pb->readU8();
|
||||||
ukn1 = pb->readU8();
|
showGame = pb->readU8();
|
||||||
ukn2 = pb->readU8();
|
blockFriendRequests = pb->readU8();
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
uint8 ukn0;
|
uint8 showOnline;
|
||||||
uint8 ukn1;
|
uint8 showGame;
|
||||||
uint8 ukn2;
|
uint8 blockFriendRequests;
|
||||||
};
|
};
|
||||||
|
|
||||||
class nexComment : public nexType
|
class nexComment : public nexType
|
||||||
@ -505,13 +505,12 @@ public:
|
|||||||
uint32 type;
|
uint32 type;
|
||||||
std::string msg;
|
std::string msg;
|
||||||
};
|
};
|
||||||
class NexFriends;
|
|
||||||
|
|
||||||
typedef void (*NEXFRIENDS_CALLBACK)(NexFriends* nexFriends, uint32 result, void* custom);
|
|
||||||
|
|
||||||
class NexFriends
|
class NexFriends
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using RpcErrorCode = int; // replace with enum class later
|
||||||
|
|
||||||
static const int ERR_NONE = 0;
|
static const int ERR_NONE = 0;
|
||||||
static const int ERR_RPC_FAILED = 1;
|
static const int ERR_RPC_FAILED = 1;
|
||||||
static const int ERR_UNEXPECTED_RESULT = 2;
|
static const int ERR_UNEXPECTED_RESULT = 2;
|
||||||
@ -544,27 +543,29 @@ public:
|
|||||||
int getPendingFriendRequestCount();
|
int getPendingFriendRequestCount();
|
||||||
|
|
||||||
bool requestGetAllInformation();
|
bool requestGetAllInformation();
|
||||||
bool requestGetAllInformation(std::function<void(uint32)> cb);
|
|
||||||
bool addProvisionalFriendByPidGuessed(uint32 principalId);
|
bool addProvisionalFriendByPidGuessed(uint32 principalId);
|
||||||
void acceptFriendRequest(uint64 messageId, std::function<void(uint32)> cb);
|
|
||||||
bool isOnline();
|
|
||||||
|
|
||||||
|
// synchronous API (returns immediately)
|
||||||
|
bool requestGetAllInformation(std::function<void(uint32)> cb);
|
||||||
void getFriendPIDs(uint32* pidList, uint32* pidCount, sint32 offset, sint32 count, bool includeFriendRequests);
|
void getFriendPIDs(uint32* pidList, uint32* pidCount, sint32 offset, sint32 count, bool includeFriendRequests);
|
||||||
void getFriendRequestPIDs(uint32* pidList, uint32* pidCount, sint32 offset, sint32 count, bool includeIncoming, bool includeOutgoing);
|
void getFriendRequestPIDs(uint32* pidList, uint32* pidCount, sint32 offset, sint32 count, bool includeIncoming, bool includeOutgoing);
|
||||||
bool getFriendByPID(nexFriend& friendData, uint32 pid);
|
bool getFriendByPID(nexFriend& friendData, uint32 pid);
|
||||||
bool getFriendRequestByPID(nexFriendRequest& friendRequestData, bool* isIncoming, uint32 searchedPid);
|
bool getFriendRequestByPID(nexFriendRequest& friendRequestData, bool* isIncoming, uint32 searchedPid);
|
||||||
bool getFriendRequestByMessageId(nexFriendRequest& friendRequestData, bool* isIncoming, uint64 messageId);
|
bool getFriendRequestByMessageId(nexFriendRequest& friendRequestData, bool* isIncoming, uint64 messageId);
|
||||||
|
bool isOnline();
|
||||||
|
void getMyPreference(nexPrincipalPreference& preference);
|
||||||
|
|
||||||
bool addProvisionalFriend(char* name, std::function<void(uint32)> cb);
|
// asynchronous API (data has to be requested)
|
||||||
void addFriendRequest(uint32 pid, const char* comment, std::function<void(uint32)> cb);
|
bool addProvisionalFriend(char* name, std::function<void(RpcErrorCode)> cb);
|
||||||
|
void addFriendRequest(uint32 pid, const char* comment, std::function<void(RpcErrorCode)> cb);
|
||||||
void requestPrincipleBaseInfoByPID(nexPrincipalBasicInfo* basicInfo, uint32* pidList, sint32 count, NEXFRIENDS_CALLBACK cb, void* customParam);
|
void requestPrincipleBaseInfoByPID(uint32* pidList, sint32 count, const std::function<void(RpcErrorCode result, std::span<nexPrincipalBasicInfo> basicInfo)>& cb);
|
||||||
void removeFriend(uint32 pid, std::function<void(uint32)> cb);
|
void removeFriend(uint32 pid, std::function<void(RpcErrorCode)> cb);
|
||||||
void cancelOutgoingProvisionalFriendRequest(uint32 pid, std::function<void(uint32)> cb);
|
void cancelOutgoingProvisionalFriendRequest(uint32 pid, std::function<void(RpcErrorCode)> cb);
|
||||||
void markFriendRequestsAsReceived(uint64* messageIdList, sint32 count, std::function<void(uint32)> cb);
|
void markFriendRequestsAsReceived(uint64* messageIdList, sint32 count, 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)
|
||||||
|
bool updatePreferencesAsync(const nexPrincipalPreference newPreferences, std::function<void(RpcErrorCode)> cb);
|
||||||
void updateMyPresence(nexPresenceV2& myPresence);
|
void updateMyPresence(nexPresenceV2& myPresence);
|
||||||
bool updatePreferences(const nexPrincipalPreference& newPreferences);
|
|
||||||
|
|
||||||
void setNotificationHandler(void(*notificationHandler)(NOTIFICATION_TYPE notificationType, uint32 pid));
|
void setNotificationHandler(void(*notificationHandler)(NOTIFICATION_TYPE notificationType, uint32 pid));
|
||||||
|
|
||||||
@ -578,7 +579,6 @@ private:
|
|||||||
|
|
||||||
static void handleResponse_acceptFriendRequest(nexService* nex, nexServiceResponse_t* response);
|
static void handleResponse_acceptFriendRequest(nexService* nex, nexServiceResponse_t* response);
|
||||||
static void handleResponse_getAllInformation(nexServiceResponse_t* response, NexFriends* nexFriends, std::function<void(uint32)> cb);
|
static void handleResponse_getAllInformation(nexServiceResponse_t* response, NexFriends* nexFriends, std::function<void(uint32)> cb);
|
||||||
static void handleResponse_updatePreferences(nexServiceResponse_t* response, NexFriends* nexFriends, std::function<void(uint32)> cb);
|
|
||||||
|
|
||||||
void generateNotification(NOTIFICATION_TYPE notificationType, uint32 pid);
|
void generateNotification(NOTIFICATION_TYPE notificationType, uint32 pid);
|
||||||
void trackNotifications();
|
void trackNotifications();
|
||||||
@ -618,6 +618,7 @@ private:
|
|||||||
}auth;
|
}auth;
|
||||||
// local friend state
|
// local friend state
|
||||||
nexPresenceV2 myPresence;
|
nexPresenceV2 myPresence;
|
||||||
|
nexPrincipalPreference myPreference;
|
||||||
|
|
||||||
std::recursive_mutex mtx_lists;
|
std::recursive_mutex mtx_lists;
|
||||||
std::vector<nexFriend> list_friends;
|
std::vector<nexFriend> list_friends;
|
||||||
|
@ -20,6 +20,7 @@ add_library(CemuCommon
|
|||||||
StackAllocator.h
|
StackAllocator.h
|
||||||
SysAllocator.cpp
|
SysAllocator.cpp
|
||||||
SysAllocator.h
|
SysAllocator.h
|
||||||
|
CafeString.h
|
||||||
version.h
|
version.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
73
src/Common/CafeString.h
Normal file
73
src/Common/CafeString.h
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "betype.h"
|
||||||
|
#include "util/helpers/StringHelpers.h"
|
||||||
|
|
||||||
|
/* Helper classes to represent CafeOS strings in emulated memory */
|
||||||
|
template <size_t N>
|
||||||
|
class CafeString // fixed buffer size, null-terminated, PPC char
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool assign(std::string_view sv)
|
||||||
|
{
|
||||||
|
if (sv.size()+1 >= N)
|
||||||
|
{
|
||||||
|
memcpy(data, sv.data(), sv.size()-1);
|
||||||
|
data[sv.size()-1] = '\0';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
memcpy(data, sv.data(), sv.size());
|
||||||
|
data[sv.size()] = '\0';
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8be data[N];
|
||||||
|
};
|
||||||
|
|
||||||
|
template <size_t N>
|
||||||
|
class CafeWideString // fixed buffer size, null-terminated, PPC wchar_t (16bit big-endian)
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool assign(const uint16be* input)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
while(input[i])
|
||||||
|
{
|
||||||
|
if(i >= N-1)
|
||||||
|
{
|
||||||
|
data[N-1] = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
data[i] = input[i];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
data[i] = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool assignFromUTF8(std::string_view sv)
|
||||||
|
{
|
||||||
|
std::basic_string<uint16be> beStr = StringHelpers::FromUtf8(sv);
|
||||||
|
if(beStr.length() > N-1)
|
||||||
|
{
|
||||||
|
memcpy(data, beStr.data(), (N-1)*sizeof(uint16be));
|
||||||
|
data[N-1] = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
memcpy(data, beStr.data(), beStr.length()*sizeof(uint16be));
|
||||||
|
data[beStr.length()] = '\0';
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16be data[N];
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace CafeStringHelpers
|
||||||
|
{
|
||||||
|
static uint32 Length(const uint16be* input, uint32 maxLength)
|
||||||
|
{
|
||||||
|
uint32 i = 0;
|
||||||
|
while(input[i] && i < maxLength)
|
||||||
|
i++;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
};
|
@ -30,8 +30,35 @@ public:
|
|||||||
uint32 GetMPTR() const { return MEMPTR<T>(m_ptr).GetMPTR(); }
|
uint32 GetMPTR() const { return MEMPTR<T>(m_ptr).GetMPTR(); }
|
||||||
uint32 GetMPTRBE() const { return MEMPTR<T>(m_ptr).GetMPTRBE(); }
|
uint32 GetMPTRBE() const { return MEMPTR<T>(m_ptr).GetMPTRBE(); }
|
||||||
|
|
||||||
operator T*() const { return GetPointer(); }
|
T* operator&() { return GetPointer(); }
|
||||||
|
explicit operator T*() const { return GetPointer(); }
|
||||||
explicit operator uint32() const { return GetMPTR(); }
|
explicit operator uint32() const { return GetMPTR(); }
|
||||||
|
explicit operator bool() const { return *m_ptr != 0; }
|
||||||
|
|
||||||
|
// for arrays (count > 1) allow direct access via [] operator
|
||||||
|
template<int c = count>
|
||||||
|
requires (c > 1)
|
||||||
|
T& operator[](const uint32 index)
|
||||||
|
{
|
||||||
|
return m_ptr[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
// if count is 1, then allow direct value assignment via = operator
|
||||||
|
template<int c = count>
|
||||||
|
requires (c == 1)
|
||||||
|
T& operator=(const T& rhs)
|
||||||
|
{
|
||||||
|
*m_ptr = rhs;
|
||||||
|
return *m_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if count is 1, then allow == and != operators
|
||||||
|
template<int c = count>
|
||||||
|
requires (c == 1)
|
||||||
|
bool operator==(const T& rhs) const
|
||||||
|
{
|
||||||
|
return *m_ptr == rhs;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const uint32 kStaticMemOffset = 64;
|
static const uint32 kStaticMemOffset = 64;
|
||||||
|
@ -2198,6 +2198,7 @@ void MainWindow::RecreateMenu()
|
|||||||
debugLoggingMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_LOGGING0 + stdx::to_underlying(LogType::CoreinitMP), _("&Coreinit MP API"), wxEmptyString)->Check(cemuLog_isLoggingEnabled(LogType::CoreinitMP));
|
debugLoggingMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_LOGGING0 + stdx::to_underlying(LogType::CoreinitMP), _("&Coreinit MP API"), wxEmptyString)->Check(cemuLog_isLoggingEnabled(LogType::CoreinitMP));
|
||||||
debugLoggingMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_LOGGING0 + stdx::to_underlying(LogType::CoreinitThread), _("&Coreinit Thread API"), wxEmptyString)->Check(cemuLog_isLoggingEnabled(LogType::CoreinitThread));
|
debugLoggingMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_LOGGING0 + stdx::to_underlying(LogType::CoreinitThread), _("&Coreinit Thread API"), wxEmptyString)->Check(cemuLog_isLoggingEnabled(LogType::CoreinitThread));
|
||||||
debugLoggingMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_LOGGING0 + stdx::to_underlying(LogType::NN_NFP), _("&NN NFP"), wxEmptyString)->Check(cemuLog_isLoggingEnabled(LogType::NN_NFP));
|
debugLoggingMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_LOGGING0 + stdx::to_underlying(LogType::NN_NFP), _("&NN NFP"), wxEmptyString)->Check(cemuLog_isLoggingEnabled(LogType::NN_NFP));
|
||||||
|
debugLoggingMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_LOGGING0 + stdx::to_underlying(LogType::NN_FP), _("&NN FP"), wxEmptyString)->Check(cemuLog_isLoggingEnabled(LogType::NN_FP));
|
||||||
debugLoggingMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_LOGGING0 + stdx::to_underlying(LogType::GX2), _("&GX2 API"), wxEmptyString)->Check(cemuLog_isLoggingEnabled(LogType::GX2));
|
debugLoggingMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_LOGGING0 + stdx::to_underlying(LogType::GX2), _("&GX2 API"), wxEmptyString)->Check(cemuLog_isLoggingEnabled(LogType::GX2));
|
||||||
debugLoggingMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_LOGGING0 + stdx::to_underlying(LogType::SoundAPI), _("&Audio API"), wxEmptyString)->Check(cemuLog_isLoggingEnabled(LogType::SoundAPI));
|
debugLoggingMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_LOGGING0 + stdx::to_underlying(LogType::SoundAPI), _("&Audio API"), wxEmptyString)->Check(cemuLog_isLoggingEnabled(LogType::SoundAPI));
|
||||||
debugLoggingMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_LOGGING0 + stdx::to_underlying(LogType::InputAPI), _("&Input API"), wxEmptyString)->Check(cemuLog_isLoggingEnabled(LogType::InputAPI));
|
debugLoggingMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_LOGGING0 + stdx::to_underlying(LogType::InputAPI), _("&Input API"), wxEmptyString)->Check(cemuLog_isLoggingEnabled(LogType::InputAPI));
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "boost/nowide/convert.hpp"
|
#include "boost/nowide/convert.hpp"
|
||||||
#include <charconv>
|
#include <charconv>
|
||||||
|
|
||||||
|
// todo - move the Cafe/PPC specific parts to CafeString.h eventually
|
||||||
namespace StringHelpers
|
namespace StringHelpers
|
||||||
{
|
{
|
||||||
// convert Wii U big-endian wchar_t string to utf8 string
|
// convert Wii U big-endian wchar_t string to utf8 string
|
||||||
|
@ -36,6 +36,16 @@ public:
|
|||||||
static HighResolutionTimer now();
|
static HighResolutionTimer now();
|
||||||
static HRTick getFrequency();
|
static HRTick getFrequency();
|
||||||
|
|
||||||
|
static HRTick microsecondsToTicks(uint64 microseconds)
|
||||||
|
{
|
||||||
|
return microseconds * m_freq / 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64 ticksToMicroseconds(HRTick ticks)
|
||||||
|
{
|
||||||
|
return ticks * 1000000 / m_freq;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HighResolutionTimer(uint64 timePoint) : m_timePoint(timePoint) {};
|
HighResolutionTimer(uint64 timePoint) : m_timePoint(timePoint) {};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user