Skip to content

Commit 1c73dc9

Browse files
committed
Implement proc_ui.rpl + stub SYSSwitchToEManual() to avoid softlocks
- Full reimplementation of proc_ui.rpl with all 19 exports - Foreground/Background messages now go to the coreinit system message queue as they should (instead of using a hack where proc_ui receives them directly) - Add missing coreinit API needed by proc_ui: OSGetPFID(), OSGetUPID(), OSGetTitleID(), __OSCreateThreadType() - Use big-endian types in OSMessage - Flesh out the stubs for OSDriver_Register and OSDriver_Unregister a bit more since we need to call it from proc_ui. Similiar small tweaks to other coreinit API - Stub sysapp SYSSwitchToEManual() and _SYSSwitchToEManual() in such a way that they will trigger the expected background/foreground transition, avoiding softlocks in games that call these functions
1 parent c038e75 commit 1c73dc9

21 files changed

+1139
-88
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ bin/sdcard/*
3939
bin/screenshots/*
4040
bin/dump/*
4141
bin/cafeLibs/*
42+
bin/portable/*
4243
bin/keys.txt
4344

4445
!bin/shaderCache/info.txt

src/Cafe/OS/common/OSCommon.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,5 +221,5 @@ void osLib_load()
221221
nsyskbd::nsyskbd_load();
222222
swkbd::load();
223223
camera::load();
224-
procui_load();
224+
proc_ui::load();
225225
}

src/Cafe/OS/libs/coreinit/coreinit.cpp

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -179,27 +179,6 @@ void coreinitExport_OSGetSharedData(PPCInterpreter_t* hCPU)
179179
osLib_returnFromFunction(hCPU, 1);
180180
}
181181

182-
typedef struct
183-
{
184-
MPTR getDriverName;
185-
MPTR ukn04;
186-
MPTR onAcquiredForeground;
187-
MPTR onReleaseForeground;
188-
MPTR ukn10;
189-
}OSDriverCallbacks_t;
190-
191-
void coreinitExport_OSDriver_Register(PPCInterpreter_t* hCPU)
192-
{
193-
#ifdef CEMU_DEBUG_ASSERT
194-
cemuLog_log(LogType::Force, "OSDriver_Register(0x{:08x},0x{:08x},0x{:08x},0x{:08x},0x{:08x},0x{:08x})", hCPU->gpr[3], hCPU->gpr[4], hCPU->gpr[5], hCPU->gpr[6], hCPU->gpr[7], hCPU->gpr[8]);
195-
#endif
196-
OSDriverCallbacks_t* driverCallbacks = (OSDriverCallbacks_t*)memory_getPointerFromVirtualOffset(hCPU->gpr[5]);
197-
198-
// todo
199-
200-
osLib_returnFromFunction(hCPU, 0);
201-
}
202-
203182
namespace coreinit
204183
{
205184
sint32 OSGetCoreId()
@@ -379,7 +358,6 @@ void coreinit_load()
379358
coreinit::miscInit();
380359
osLib_addFunction("coreinit", "OSGetSharedData", coreinitExport_OSGetSharedData);
381360
osLib_addFunction("coreinit", "UCReadSysConfig", coreinitExport_UCReadSysConfig);
382-
osLib_addFunction("coreinit", "OSDriver_Register", coreinitExport_OSDriver_Register);
383361

384362
// async callbacks
385363
InitializeAsyncCallback();

src/Cafe/OS/libs/coreinit/coreinit_DynLoad.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
namespace coreinit
44
{
5+
enum class RplEntryReason
6+
{
7+
Loaded = 1,
8+
Unloaded = 2,
9+
};
10+
511
uint32 OSDynLoad_SetAllocator(MPTR allocFunc, MPTR freeFunc);
612
void OSDynLoad_SetTLSAllocator(MPTR allocFunc, MPTR freeFunc);
713
uint32 OSDynLoad_GetAllocator(betype<MPTR>* funcAlloc, betype<MPTR>* funcFree);

src/Cafe/OS/libs/coreinit/coreinit_FS.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -837,7 +837,7 @@ namespace coreinit
837837

838838
FSAsyncResult* FSGetAsyncResult(OSMessage* msg)
839839
{
840-
return (FSAsyncResult*)memory_getPointerFromVirtualOffset(_swapEndianU32(msg->message));
840+
return (FSAsyncResult*)memory_getPointerFromVirtualOffset(msg->message);
841841
}
842842

843843
sint32 __FSProcessAsyncResult(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, sint32 fsStatus, uint32 errHandling)

src/Cafe/OS/libs/coreinit/coreinit_Memory.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ namespace coreinit
126126
return physicalAddr;
127127
}
128128

129-
void OSMemoryBarrier(PPCInterpreter_t* hCPU)
129+
void OSMemoryBarrier()
130130
{
131131
// no-op
132132
}

src/Cafe/OS/libs/coreinit/coreinit_Memory.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,9 @@ namespace coreinit
55
void InitializeMemory();
66

77
void OSGetMemBound(sint32 memType, MPTR* offsetOutput, uint32* sizeOutput);
8+
9+
void* OSBlockMove(MEMPTR<void> dst, MEMPTR<void> src, uint32 size, bool flushDC);
10+
void* OSBlockSet(MEMPTR<void> dst, uint32 value, uint32 size);
11+
12+
void OSMemoryBarrier();
813
}

src/Cafe/OS/libs/coreinit/coreinit_MessageQueue.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
namespace coreinit
55
{
6+
void UpdateSystemMessageQueue();
7+
void HandleReceivedSystemMessage(OSMessage* msg);
68

79
SysAllocator<OSMessageQueue> g_systemMessageQueue;
810
SysAllocator<OSMessage, 16> _systemMessageQueueArray;
@@ -27,6 +29,9 @@ namespace coreinit
2729

2830
bool OSReceiveMessage(OSMessageQueue* msgQueue, OSMessage* msg, uint32 flags)
2931
{
32+
bool isSystemMessageQueue = (msgQueue == g_systemMessageQueue);
33+
if(isSystemMessageQueue)
34+
UpdateSystemMessageQueue();
3035
__OSLockScheduler(msgQueue);
3136
while (msgQueue->usedCount == (uint32be)0)
3237
{
@@ -50,6 +55,8 @@ namespace coreinit
5055
if (!msgQueue->threadQueueSend.isEmpty())
5156
msgQueue->threadQueueSend.wakeupSingleThreadWaitQueue(true);
5257
__OSUnlockScheduler(msgQueue);
58+
if(isSystemMessageQueue)
59+
HandleReceivedSystemMessage(msg);
5360
return true;
5461
}
5562

src/Cafe/OS/libs/coreinit/coreinit_MessageQueue.h

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,21 @@
33

44
namespace coreinit
55
{
6+
enum class SysMessageId : uint32
7+
{
8+
MsgAcquireForeground = 0xFACEF000,
9+
MsgReleaseForeground = 0xFACEBACC,
10+
MsgExit = 0xD1E0D1E0,
11+
HomeButtonDenied = 0xCCC0FFEE,
12+
NetIoStartOrStop = 0xAAC0FFEE,
13+
};
14+
615
struct OSMessage
716
{
8-
MPTR message;
9-
uint32 data0;
10-
uint32 data1;
11-
uint32 data2;
17+
uint32be message;
18+
uint32be data0;
19+
uint32be data1;
20+
uint32be data2;
1221
};
1322

1423
struct OSMessageQueue
@@ -36,5 +45,7 @@ namespace coreinit
3645
bool OSPeekMessage(OSMessageQueue* msgQueue, OSMessage* msg);
3746
sint32 OSSendMessage(OSMessageQueue* msgQueue, OSMessage* msg, uint32 flags);
3847

48+
OSMessageQueue* OSGetSystemMessageQueue();
49+
3950
void InitializeMessageQueue();
4051
};

src/Cafe/OS/libs/coreinit/coreinit_Misc.cpp

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "Cafe/OS/common/OSCommon.h"
22
#include "Cafe/OS/libs/coreinit/coreinit_Misc.h"
3+
#include "Cafe/OS/libs/coreinit/coreinit_MessageQueue.h"
34
#include "Cafe/CafeSystem.h"
45
#include "Cafe/Filesystem/fsc.h"
56
#include <pugixml.hpp>
@@ -371,6 +372,23 @@ namespace coreinit
371372
return true;
372373
}
373374

375+
uint32 OSGetPFID()
376+
{
377+
return 15; // hardcoded as game
378+
}
379+
380+
uint32 OSGetUPID()
381+
{
382+
return OSGetPFID();
383+
}
384+
385+
uint64 s_currentTitleId;
386+
387+
uint64 OSGetTitleID()
388+
{
389+
return s_currentTitleId;
390+
}
391+
374392
uint32 s_sdkVersion;
375393

376394
uint32 __OSGetProcessSDKVersion()
@@ -470,16 +488,89 @@ namespace coreinit
470488
return 0;
471489
}
472490

491+
void OSReleaseForeground()
492+
{
493+
cemuLog_logDebug(LogType::Force, "OSReleaseForeground not implemented");
494+
}
495+
496+
bool s_transitionToBackground = false;
497+
bool s_transitionToForeground = false;
498+
499+
void StartBackgroundForegroundTransition()
500+
{
501+
s_transitionToBackground = true;
502+
s_transitionToForeground = true;
503+
}
504+
505+
// called at the beginning of OSReceiveMessage if the queue is the system message queue
506+
void UpdateSystemMessageQueue()
507+
{
508+
if(!OSIsInterruptEnabled())
509+
return;
510+
cemu_assert_debug(!__OSHasSchedulerLock());
511+
// normally syscall 0x2E is used to get the next message
512+
// for now we just have some preliminary logic here to allow a fake transition to background & foreground
513+
if(s_transitionToBackground)
514+
{
515+
// add transition to background message
516+
OSMessage msg{};
517+
msg.data0 = stdx::to_underlying(SysMessageId::MsgReleaseForeground);
518+
msg.data1 = 0; // 1 -> System is shutting down 0 -> Begin transitioning to background
519+
OSMessageQueue* systemMessageQueue = coreinit::OSGetSystemMessageQueue();
520+
if(OSSendMessage(systemMessageQueue, &msg, 0))
521+
s_transitionToBackground = false;
522+
return;
523+
}
524+
if(s_transitionToForeground)
525+
{
526+
// add transition to foreground message
527+
OSMessage msg{};
528+
msg.data0 = stdx::to_underlying(SysMessageId::MsgAcquireForeground);
529+
msg.data1 = 1; // ?
530+
msg.data2 = 1; // ?
531+
OSMessageQueue* systemMessageQueue = coreinit::OSGetSystemMessageQueue();
532+
if(OSSendMessage(systemMessageQueue, &msg, 0))
533+
s_transitionToForeground = false;
534+
return;
535+
}
536+
}
537+
538+
// called when OSReceiveMessage returns a message from the system message queue
539+
void HandleReceivedSystemMessage(OSMessage* msg)
540+
{
541+
cemu_assert_debug(!__OSHasSchedulerLock());
542+
cemuLog_log(LogType::Force, "Receiving message: {:08x}", (uint32)msg->data0);
543+
}
544+
545+
uint32 OSDriver_Register(uint32 moduleHandle, sint32 priority, OSDriverInterface* driverCallbacks, sint32 driverId, uint32be* outUkn1, uint32be* outUkn2, uint32be* outUkn3)
546+
{
547+
cemuLog_logDebug(LogType::Force, "OSDriver_Register stubbed");
548+
return 0;
549+
}
550+
551+
uint32 OSDriver_Deregister(uint32 moduleHandle, sint32 driverId)
552+
{
553+
cemuLog_logDebug(LogType::Force, "OSDriver_Deregister stubbed");
554+
return 0;
555+
}
556+
473557
void miscInit()
474558
{
559+
s_currentTitleId = CafeSystem::GetForegroundTitleId();
475560
s_sdkVersion = CafeSystem::GetForegroundTitleSDKVersion();
561+
s_transitionToBackground = false;
562+
s_transitionToForeground = false;
476563

477564
cafeExportRegister("coreinit", __os_snprintf, LogType::Placeholder);
478565
cafeExportRegister("coreinit", OSReport, LogType::Placeholder);
479566
cafeExportRegister("coreinit", OSVReport, LogType::Placeholder);
480567
cafeExportRegister("coreinit", COSWarn, LogType::Placeholder);
481568
cafeExportRegister("coreinit", OSLogPrintf, LogType::Placeholder);
482569
cafeExportRegister("coreinit", OSConsoleWrite, LogType::Placeholder);
570+
571+
cafeExportRegister("coreinit", OSGetPFID, LogType::Placeholder);
572+
cafeExportRegister("coreinit", OSGetUPID, LogType::Placeholder);
573+
cafeExportRegister("coreinit", OSGetTitleID, LogType::Placeholder);
483574
cafeExportRegister("coreinit", __OSGetProcessSDKVersion, LogType::Placeholder);
484575

485576
g_homeButtonMenuEnabled = true; // enabled by default
@@ -489,6 +580,11 @@ namespace coreinit
489580

490581
cafeExportRegister("coreinit", OSLaunchTitleByPathl, LogType::Placeholder);
491582
cafeExportRegister("coreinit", OSRestartGame, LogType::Placeholder);
583+
584+
cafeExportRegister("coreinit", OSReleaseForeground, LogType::Placeholder);
585+
586+
cafeExportRegister("coreinit", OSDriver_Register, LogType::Placeholder);
587+
cafeExportRegister("coreinit", OSDriver_Deregister, LogType::Placeholder);
492588
}
493589

494590
};

src/Cafe/OS/libs/coreinit/coreinit_Misc.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,29 @@
22

33
namespace coreinit
44
{
5+
uint32 OSGetUPID();
6+
uint32 OSGetPFID();
7+
uint64 OSGetTitleID();
58
uint32 __OSGetProcessSDKVersion();
69
uint32 OSLaunchTitleByPathl(const char* path, uint32 pathLength, uint32 argc);
710
uint32 OSRestartGame(uint32 argc, MEMPTR<char>* argv);
811

12+
void OSReleaseForeground();
13+
14+
void StartBackgroundForegroundTransition();
15+
16+
struct OSDriverInterface
17+
{
18+
MEMPTR<void> getDriverName;
19+
MEMPTR<void> init;
20+
MEMPTR<void> onAcquireForeground;
21+
MEMPTR<void> onReleaseForeground;
22+
MEMPTR<void> done;
23+
};
24+
static_assert(sizeof(OSDriverInterface) == 0x14);
25+
26+
uint32 OSDriver_Register(uint32 moduleHandle, sint32 priority, OSDriverInterface* driverCallbacks, sint32 driverId, uint32be* outUkn1, uint32be* outUkn2, uint32be* outUkn3);
27+
uint32 OSDriver_Deregister(uint32 moduleHandle, sint32 driverId);
28+
929
void miscInit();
1030
};

src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -294,9 +294,9 @@ namespace coreinit
294294
__OSUnlockScheduler();
295295
}
296296

297-
bool OSCreateThreadType(OSThread_t* thread, MPTR entryPoint, sint32 numParam, void* ptrParam, void* stackTop2, sint32 stackSize, sint32 priority, uint32 attr, OSThread_t::THREAD_TYPE threadType)
297+
bool OSCreateThreadType(OSThread_t* thread, MPTR entryPoint, sint32 numParam, void* ptrParam, void* stackTop, sint32 stackSize, sint32 priority, uint32 attr, OSThread_t::THREAD_TYPE threadType)
298298
{
299-
OSCreateThreadInternal(thread, entryPoint, memory_getVirtualOffsetFromPointer(stackTop2) - stackSize, stackSize, attr, threadType);
299+
OSCreateThreadInternal(thread, entryPoint, memory_getVirtualOffsetFromPointer(stackTop) - stackSize, stackSize, attr, threadType);
300300
thread->context.gpr[3] = _swapEndianU32(numParam); // num arguments
301301
thread->context.gpr[4] = _swapEndianU32(memory_getVirtualOffsetFromPointer(ptrParam)); // arguments pointer
302302
__OSSetThreadBasePriority(thread, priority);
@@ -317,9 +317,15 @@ namespace coreinit
317317
return true;
318318
}
319319

320-
bool OSCreateThread(OSThread_t* thread, MPTR entryPoint, sint32 numParam, void* ptrParam, void* stackTop2, sint32 stackSize, sint32 priority, uint32 attr)
320+
bool OSCreateThread(OSThread_t* thread, MPTR entryPoint, sint32 numParam, void* ptrParam, void* stackTop, sint32 stackSize, sint32 priority, uint32 attr)
321321
{
322-
return OSCreateThreadType(thread, entryPoint, numParam, ptrParam, stackTop2, stackSize, priority, attr, OSThread_t::THREAD_TYPE::TYPE_APP);
322+
return OSCreateThreadType(thread, entryPoint, numParam, ptrParam, stackTop, stackSize, priority, attr, OSThread_t::THREAD_TYPE::TYPE_APP);
323+
}
324+
325+
// alias to OSCreateThreadType, similar to OSCreateThread, but with an additional parameter for the thread type
326+
bool __OSCreateThreadType(OSThread_t* thread, MPTR entryPoint, sint32 numParam, void* ptrParam, void* stackTop, sint32 stackSize, sint32 priority, uint32 attr, OSThread_t::THREAD_TYPE threadType)
327+
{
328+
return OSCreateThreadType(thread, entryPoint, numParam, ptrParam, stackTop, stackSize, priority, attr, threadType);
323329
}
324330

325331
bool OSRunThread(OSThread_t* thread, MPTR funcAddress, sint32 numParam, void* ptrParam)
@@ -445,12 +451,12 @@ namespace coreinit
445451
return currentThread->specificArray[index].GetPtr();
446452
}
447453

448-
void OSSetThreadName(OSThread_t* thread, char* name)
454+
void OSSetThreadName(OSThread_t* thread, const char* name)
449455
{
450456
thread->threadName = name;
451457
}
452458

453-
char* OSGetThreadName(OSThread_t* thread)
459+
const char* OSGetThreadName(OSThread_t* thread)
454460
{
455461
return thread->threadName.GetPtr();
456462
}
@@ -1371,6 +1377,7 @@ namespace coreinit
13711377
{
13721378
cafeExportRegister("coreinit", OSCreateThreadType, LogType::CoreinitThread);
13731379
cafeExportRegister("coreinit", OSCreateThread, LogType::CoreinitThread);
1380+
cafeExportRegister("coreinit", __OSCreateThreadType, LogType::CoreinitThread);
13741381
cafeExportRegister("coreinit", OSExitThread, LogType::CoreinitThread);
13751382

13761383
cafeExportRegister("coreinit", OSGetCurrentThread, LogType::CoreinitThread);

0 commit comments

Comments
 (0)