coreinit: Handle non-existing modules in OSDynLoad_Acquire

Fixes Togabito crashing on boot

coreinit: Handle non-existing modules in OSDynLoad_Acquire
This commit is contained in:
Exzap 2023-09-09 14:33:31 +02:00
parent c168cf536a
commit f04c7575d7
7 changed files with 102 additions and 75 deletions

View File

@ -165,7 +165,7 @@ void LoadMainExecutable()
{ {
// RPX // RPX
RPLLoader_AddDependency(_pathToExecutable.c_str()); RPLLoader_AddDependency(_pathToExecutable.c_str());
applicationRPX = rpl_loadFromMem(rpxData, rpxSize, (char*)_pathToExecutable.c_str()); applicationRPX = RPLLoader_LoadFromMemory(rpxData, rpxSize, (char*)_pathToExecutable.c_str());
if (!applicationRPX) if (!applicationRPX)
{ {
wxMessageBox(_("Failed to run this title because the executable is damaged")); wxMessageBox(_("Failed to run this title because the executable is damaged"));

View File

@ -325,6 +325,8 @@ void PPCRecompiler_thread()
PPCRecompilerState.recompilerSpinlock.unlock(); PPCRecompilerState.recompilerSpinlock.unlock();
PPCRecompiler_recompileAtAddress(enterAddress); PPCRecompiler_recompileAtAddress(enterAddress);
if(s_recompilerThreadStopSignal)
return;
} }
} }
} }

View File

@ -39,20 +39,22 @@ VHeap rplLoaderHeap_workarea(nullptr, MEMORY_RPLLOADER_AREA_SIZE);
PPCCodeHeap rplLoaderHeap_lowerAreaCodeMem2(nullptr, MEMORY_CODE_TRAMPOLINE_AREA_SIZE); PPCCodeHeap rplLoaderHeap_lowerAreaCodeMem2(nullptr, MEMORY_CODE_TRAMPOLINE_AREA_SIZE);
PPCCodeHeap rplLoaderHeap_codeArea2(nullptr, MEMORY_CODEAREA_SIZE); PPCCodeHeap rplLoaderHeap_codeArea2(nullptr, MEMORY_CODEAREA_SIZE);
bool rplLoader_applicationHasMemoryControl = false;
uint32 rplLoader_maxCodeAddress = 0; // highest used code address
ChunkedFlatAllocator<64 * 1024> g_heapTrampolineArea; ChunkedFlatAllocator<64 * 1024> g_heapTrampolineArea;
std::vector<rplDependency_t*> rplDependencyList = std::vector<rplDependency_t*>(); std::vector<RPLDependency*> rplDependencyList;
RPLModule* rplModuleList[256]; RPLModule* rplModuleList[256];
sint32 rplModuleCount = 0; sint32 rplModuleCount = 0;
uint32 _currentTLSModuleIndex = 1; // value 0 is reserved bool rplLoader_applicationHasMemoryControl = false;
uint32 rplLoader_maxCodeAddress = 0; // highest used code address
uint32 rplLoader_currentTLSModuleIndex = 1; // value 0 is reserved
uint32 rplLoader_currentHandleCounter = 0x00001000;
sint16 rplLoader_currentTlsModuleIndex = 0x0001;
RPLModule* rplLoader_mainModule = nullptr;
uint32 rplLoader_sdataAddr = MPTR_NULL; // r13 uint32 rplLoader_sdataAddr = MPTR_NULL; // r13
uint32 rplLoader_sdata2Addr = MPTR_NULL; // r2 uint32 rplLoader_sdata2Addr = MPTR_NULL; // r2
uint32 rplLoader_currentDataAllocatorAddr = 0x10000000;
std::map<void(*)(PPCInterpreter_t* hCPU), uint32> g_map_callableExports; std::map<void(*)(PPCInterpreter_t* hCPU), uint32> g_map_callableExports;
@ -110,8 +112,6 @@ MPTR RPLLoader_AllocateCodeSpace(uint32 size, uint32 alignment)
return codeAddr; return codeAddr;
} }
uint32 rpl3_currentDataAllocatorAddr = 0x10000000;
uint32 RPLLoader_AllocateDataSpace(RPLModule* rpl, uint32 size, uint32 alignment) uint32 RPLLoader_AllocateDataSpace(RPLModule* rpl, uint32 size, uint32 alignment)
{ {
if (rplLoader_applicationHasMemoryControl) if (rplLoader_applicationHasMemoryControl)
@ -121,9 +121,9 @@ uint32 RPLLoader_AllocateDataSpace(RPLModule* rpl, uint32 size, uint32 alignment
PPCCoreCallback(rpl->funcAlloc.value(), size, alignment, memPtr.GetPointer()); PPCCoreCallback(rpl->funcAlloc.value(), size, alignment, memPtr.GetPointer());
return (uint32)*(memPtr.GetPointer()); return (uint32)*(memPtr.GetPointer());
} }
rpl3_currentDataAllocatorAddr = (rpl3_currentDataAllocatorAddr + alignment - 1)&~(alignment-1); rplLoader_currentDataAllocatorAddr = (rplLoader_currentDataAllocatorAddr + alignment - 1) & ~(alignment - 1);
uint32 mem = rpl3_currentDataAllocatorAddr; uint32 mem = rplLoader_currentDataAllocatorAddr;
rpl3_currentDataAllocatorAddr += size; rplLoader_currentDataAllocatorAddr += size;
return mem; return mem;
} }
@ -134,7 +134,7 @@ void RPLLoader_FreeData(RPLModule* rpl, void* ptr)
uint32 RPLLoader_GetDataAllocatorAddr() uint32 RPLLoader_GetDataAllocatorAddr()
{ {
return (rpl3_currentDataAllocatorAddr + 0xFFF)&(~0xFFF); return (rplLoader_currentDataAllocatorAddr + 0xFFF) & (~0xFFF);
} }
uint32 RPLLoader_GetMaxCodeOffset() uint32 RPLLoader_GetMaxCodeOffset()
@ -1385,12 +1385,11 @@ bool RPLLoader_HandleRelocs(RPLModule* rplLoaderContext, std::span<RPLSharedImpo
return true; return true;
} }
void _RPLLoader_ExtractModuleNameFromPath(char* output, const char* input) void _RPLLoader_ExtractModuleNameFromPath(char* output, std::string_view input)
{ {
// scan to last '/' // scan to last '/'
sint32 inputLen = (sint32)strlen(input); cemu_assert(!input.empty());
cemu_assert(inputLen > 0); size_t startIndex = input.size() - 1;
sint32 startIndex = inputLen - 1;
while (startIndex > 0) while (startIndex > 0)
{ {
if (input[startIndex] == '/') if (input[startIndex] == '/')
@ -1401,23 +1400,20 @@ void _RPLLoader_ExtractModuleNameFromPath(char* output, const char* input)
startIndex--; startIndex--;
} }
// cut off after '.' // cut off after '.'
sint32 endIndex = startIndex; size_t endIndex = startIndex;
while (endIndex <= inputLen) while (endIndex < input.size())
{ {
if (input[endIndex] == '.') if (input[endIndex] == '.')
break; break;
endIndex++; endIndex++;
} }
sint32 nameLen = endIndex - startIndex; size_t nameLen = endIndex - startIndex;
cemu_assert(nameLen != 0); cemu_assert(nameLen != 0);
nameLen = std::min(nameLen, RPL_MODULE_NAME_LENGTH-1); nameLen = std::min<size_t>(nameLen, RPL_MODULE_NAME_LENGTH-1);
memcpy(output, input + startIndex, nameLen); memcpy(output, input.data() + startIndex, nameLen);
output[nameLen] = '\0'; output[nameLen] = '\0';
// convert to lower case // convert to lower case
for (sint32 i = 0; i < nameLen; i++) std::for_each(output, output + nameLen, [](char& c) {c = _ansiToLower(c);});
{
output[i] = _ansiToLower(output[i]);
}
} }
void RPLLoader_InitState() void RPLLoader_InitState()
@ -1432,27 +1428,6 @@ void RPLLoader_InitState()
RPLLoader_ResetState(); RPLLoader_ResetState();
} }
void RPLLoader_ResetState()
{
// unload all RPL modules
while (rplModuleCount > 0)
RPLLoader_UnloadModule(rplModuleList[0]);
rplDependencyList.clear();
// unload all remaining symbols
rplSymbolStorage_unloadAll();
// free all code imports
g_heapTrampolineArea.releaseAll();
list_mappedFunctionImports.clear();
g_map_callableExports.clear();
rplLoader_applicationHasMemoryControl = false;
rplLoader_maxCodeAddress = 0;
rpl3_currentDataAllocatorAddr = 0x10000000;
_currentTLSModuleIndex = 1;
rplLoader_sdataAddr = MPTR_NULL;
rplLoader_sdata2Addr = MPTR_NULL;
}
void RPLLoader_BeginCemuhookCRC(RPLModule* rpl) void RPLLoader_BeginCemuhookCRC(RPLModule* rpl)
{ {
// calculate some values required for CRC // calculate some values required for CRC
@ -1610,7 +1585,7 @@ void RPLLoader_InitModuleAllocator(RPLModule* rpl)
} }
// map rpl into memory, but do not resolve relocs and imports yet // map rpl into memory, but do not resolve relocs and imports yet
RPLModule* rpl_loadFromMem(uint8* rplData, sint32 size, char* name) RPLModule* RPLLoader_LoadFromMemory(uint8* rplData, sint32 size, char* name)
{ {
char moduleName[RPL_MODULE_NAME_LENGTH]; char moduleName[RPL_MODULE_NAME_LENGTH];
_RPLLoader_ExtractModuleNameFromPath(moduleName, name); _RPLLoader_ExtractModuleNameFromPath(moduleName, name);
@ -1699,7 +1674,7 @@ RPLModule* rpl_loadFromMem(uint8* rplData, sint32 size, char* name)
return rpl; return rpl;
} }
void RPLLoader_flushMemory(RPLModule* rpl) void RPLLoader_FlushMemory(RPLModule* rpl)
{ {
// invalidate recompiler cache // invalidate recompiler cache
PPCRecompiler_invalidateRange(rpl->regionMappingBase_text.GetMPTR(), rpl->regionMappingBase_text.GetMPTR() + rpl->regionSize_text); PPCRecompiler_invalidateRange(rpl->regionMappingBase_text.GetMPTR(), rpl->regionMappingBase_text.GetMPTR() + rpl->regionSize_text);
@ -1755,7 +1730,7 @@ void RPLLoader_LinkSingleModule(RPLModule* rplLoaderContext, bool resolveOnlyExp
else else
RPLLoader_HandleRelocs(rplLoaderContext, sharedImportTracking, 0); RPLLoader_HandleRelocs(rplLoaderContext, sharedImportTracking, 0);
RPLLoader_flushMemory(rplLoaderContext); RPLLoader_FlushMemory(rplLoaderContext);
} }
void RPLLoader_LoadSectionDebugSymbols(RPLModule* rplLoaderContext, rplSectionEntryNew_t* section, int symtabSectionIndex) void RPLLoader_LoadSectionDebugSymbols(RPLModule* rplLoaderContext, rplSectionEntryNew_t* section, int symtabSectionIndex)
@ -1919,8 +1894,24 @@ uint32 RPLLoader_GetModuleEntrypoint(RPLModule* rplLoaderContext)
return rplLoaderContext->entrypoint; return rplLoaderContext->entrypoint;
} }
uint32 rplLoader_currentHandleCounter = 0x00001000; // takes a module name without extension, returns true if the RPL module is a known Cafe OS module
sint16 rplLoader_currentTlsModuleIndex = 0x0001; bool RPLLoader_IsKnownCafeOSModule(std::string_view name)
{
static std::unordered_set<std::string> s_systemModules556 = {
"avm","camera","coreinit","dc","dmae","drmapp","erreula",
"gx2","h264","lzma920","mic","nfc","nio_prof","nlibcurl",
"nlibnss","nlibnss2","nn_ac","nn_acp","nn_act","nn_aoc","nn_boss",
"nn_ccr","nn_cmpt","nn_dlp","nn_ec","nn_fp","nn_hai","nn_hpad",
"nn_idbe","nn_ndm","nn_nets2","nn_nfp","nn_nim","nn_olv","nn_pdm",
"nn_save","nn_sl","nn_spm","nn_temp","nn_uds","nn_vctl","nsysccr",
"nsyshid","nsyskbd","nsysnet","nsysuhs","nsysuvd","ntag","padscore",
"proc_ui","sndcore2","snduser2","snd_core","snd_user","swkbd","sysapp",
"tcl","tve","uac","uac_rpl","usb_mic","uvc","uvd","vpad","vpadbase",
"zlib125"};
std::string nameLower{name};
std::transform(nameLower.begin(), nameLower.end(), nameLower.begin(), _ansiToLower);
return s_systemModules556.contains(nameLower);
}
// increment reference counter for module // increment reference counter for module
void RPLLoader_AddDependency(const char* name) void RPLLoader_AddDependency(const char* name)
@ -1946,18 +1937,18 @@ void RPLLoader_AddDependency(const char* name)
{ {
if (strcmp(moduleName, dep->modulename) == 0) if (strcmp(moduleName, dep->modulename) == 0)
{ {
// entry already exists, increment reference counter
dep->referenceCount++; dep->referenceCount++;
return; return;
} }
} }
// add new entry // add new entry
rplDependency_t* newDependency = new rplDependency_t(); RPLDependency* newDependency = new RPLDependency();
strcpy(newDependency->modulename, moduleName); strcpy(newDependency->modulename, moduleName);
newDependency->referenceCount = 1; newDependency->referenceCount = 1;
newDependency->coreinitHandle = rplLoader_currentHandleCounter; newDependency->coreinitHandle = rplLoader_currentHandleCounter;
newDependency->tlsModuleIndex = rplLoader_currentTlsModuleIndex; newDependency->tlsModuleIndex = rplLoader_currentTlsModuleIndex;
rplLoader_currentTlsModuleIndex++; newDependency->isCafeOSModule = RPLLoader_IsKnownCafeOSModule(moduleName);
rplLoader_currentTlsModuleIndex++; // todo - delay handle and tls allocation until the module is actually loaded. It may not exist
rplLoader_currentHandleCounter++; rplLoader_currentHandleCounter++;
if (rplLoader_currentTlsModuleIndex == 0x7FFF) if (rplLoader_currentTlsModuleIndex == 0x7FFF)
cemuLog_log(LogType::Force, "RPLLoader: Exhausted TLS module indices pool"); cemuLog_log(LogType::Force, "RPLLoader: Exhausted TLS module indices pool");
@ -2005,6 +1996,18 @@ void RPLLoader_RemoveDependency(const char* name)
} }
} }
bool RPLLoader_HasDependency(std::string_view name)
{
char moduleName[RPL_MODULE_NAME_LENGTH];
_RPLLoader_ExtractModuleNameFromPath(moduleName, name);
for (const auto& dep : rplDependencyList)
{
if (strcmp(moduleName, dep->modulename) == 0)
return true;
}
return false;
}
// decrement reference counter for dependency by module handle // decrement reference counter for dependency by module handle
void RPLLoader_RemoveDependency(uint32 handle) void RPLLoader_RemoveDependency(uint32 handle)
{ {
@ -2030,6 +2033,9 @@ uint32 RPLLoader_GetHandleByModuleName(const char* name)
{ {
if (strcmp(moduleName, dep->modulename) == 0) if (strcmp(moduleName, dep->modulename) == 0)
{ {
cemu_assert_debug(dep->loadAttempted);
if (!dep->isCafeOSModule && !dep->rplLoaderContext)
return RPL_INVALID_HANDLE; // module not found
return dep->coreinitHandle; return dep->coreinitHandle;
} }
} }
@ -2062,21 +2068,21 @@ bool RPLLoader_GetTLSDataByTLSIndex(sint16 tlsModuleIndex, uint8** tlsData, sint
return true; return true;
} }
bool RPLLoader_LoadFromVirtualPath(rplDependency_t* dependency, char* filePath) bool RPLLoader_LoadFromVirtualPath(RPLDependency* dependency, char* filePath)
{ {
uint32 rplSize = 0; uint32 rplSize = 0;
uint8* rplData = fsc_extractFile(filePath, &rplSize); uint8* rplData = fsc_extractFile(filePath, &rplSize);
if (rplData) if (rplData)
{ {
cemuLog_logDebug(LogType::Force, "Loading: {}", filePath); cemuLog_logDebug(LogType::Force, "Loading: {}", filePath);
dependency->rplLoaderContext = rpl_loadFromMem(rplData, rplSize, filePath); dependency->rplLoaderContext = RPLLoader_LoadFromMemory(rplData, rplSize, filePath);
free(rplData); free(rplData);
return true; return true;
} }
return false; return false;
} }
void RPLLoader_LoadDependency(rplDependency_t* dependency) void RPLLoader_LoadDependency(RPLDependency* dependency)
{ {
dependency->loadAttempted = true; dependency->loadAttempted = true;
// check if module is already loaded // check if module is already loaded
@ -2084,11 +2090,9 @@ void RPLLoader_LoadDependency(rplDependency_t* dependency)
{ {
if(!boost::iequals(rplModuleList[i]->moduleName2, dependency->modulename)) if(!boost::iequals(rplModuleList[i]->moduleName2, dependency->modulename))
continue; continue;
// already loaded
dependency->rplLoaderContext = rplModuleList[i]; dependency->rplLoaderContext = rplModuleList[i];
return; return;
} }
// attempt to load rpl from various locations
char filePath[RPL_MODULE_PATH_LENGTH]; char filePath[RPL_MODULE_PATH_LENGTH];
// check if path is absolute // check if path is absolute
if (dependency->filepath[0] == '/') if (dependency->filepath[0] == '/')
@ -2097,7 +2101,7 @@ void RPLLoader_LoadDependency(rplDependency_t* dependency)
RPLLoader_LoadFromVirtualPath(dependency, filePath); RPLLoader_LoadFromVirtualPath(dependency, filePath);
return; return;
} }
// attempt to load rpl from internal folder // attempt to load rpl from code directory of current title
strcpy_s(filePath, "/internal/current_title/code/"); strcpy_s(filePath, "/internal/current_title/code/");
strcat_s(filePath, dependency->filepath); strcat_s(filePath, dependency->filepath);
// except if it is blacklisted // except if it is blacklisted
@ -2119,7 +2123,8 @@ void RPLLoader_LoadDependency(rplDependency_t* dependency)
if (fileData) if (fileData)
{ {
cemuLog_log(LogType::Force, "Loading RPL: /cafeLibs/{}", dependency->filepath); cemuLog_log(LogType::Force, "Loading RPL: /cafeLibs/{}", dependency->filepath);
dependency->rplLoaderContext = rpl_loadFromMem(fileData->data(), fileData->size(), dependency->filepath); dependency->rplLoaderContext = RPLLoader_LoadFromMemory(fileData->data(), fileData->size(),
dependency->filepath);
return; return;
} }
} }
@ -2168,8 +2173,6 @@ void RPLLoader_UpdateDependencies()
RPLLoader_Link(); RPLLoader_Link();
} }
RPLModule* rplLoader_mainModule = nullptr;
void RPLLoader_SetMainModule(RPLModule* rplLoaderContext) void RPLLoader_SetMainModule(RPLModule* rplLoaderContext)
{ {
rplLoaderContext->entrypointCalled = true; rplLoaderContext->entrypointCalled = true;
@ -2250,7 +2253,7 @@ uint32 RPLLoader_FindModuleOrHLEExport(uint32 moduleHandle, bool isData, const c
{ {
// find dependency from handle // find dependency from handle
RPLModule* rplLoaderContext = nullptr; RPLModule* rplLoaderContext = nullptr;
rplDependency_t* dependency = nullptr; RPLDependency* dependency = nullptr;
for (auto& dep : rplDependencyList) for (auto& dep : rplDependencyList)
{ {
if (dep->coreinitHandle == moduleHandle) if (dep->coreinitHandle == moduleHandle)
@ -2379,3 +2382,24 @@ void RPLLoader_ReleaseCodeCaveMem(MEMPTR<void> addr)
{ {
heapCodeCaveArea.free(addr.GetMPTR()); heapCodeCaveArea.free(addr.GetMPTR());
} }
void RPLLoader_ResetState()
{
// unload all RPL modules
while (rplModuleCount > 0)
RPLLoader_UnloadModule(rplModuleList[0]);
rplDependencyList.clear();
// unload all remaining symbols
rplSymbolStorage_unloadAll();
// free all code imports
g_heapTrampolineArea.releaseAll();
list_mappedFunctionImports.clear();
g_map_callableExports.clear();
rplLoader_applicationHasMemoryControl = false;
rplLoader_maxCodeAddress = 0;
rplLoader_currentDataAllocatorAddr = 0x10000000;
rplLoader_currentTLSModuleIndex = 1;
rplLoader_sdataAddr = MPTR_NULL;
rplLoader_sdata2Addr = MPTR_NULL;
rplLoader_mainModule = nullptr;
}

View File

@ -2,7 +2,7 @@
struct RPLModule; struct RPLModule;
#define RPL_INVALID_HANDLE (0xFFFFFFFF) #define RPL_INVALID_HANDLE 0xFFFFFFFF
void RPLLoader_InitState(); void RPLLoader_InitState();
void RPLLoader_ResetState(); void RPLLoader_ResetState();
@ -14,7 +14,7 @@ MPTR RPLLoader_AllocateCodeSpace(uint32 size, uint32 alignment);
uint32 RPLLoader_GetMaxCodeOffset(); uint32 RPLLoader_GetMaxCodeOffset();
uint32 RPLLoader_GetDataAllocatorAddr(); uint32 RPLLoader_GetDataAllocatorAddr();
RPLModule* rpl_loadFromMem(uint8* rplData, sint32 size, char* name); RPLModule* RPLLoader_LoadFromMemory(uint8* rplData, sint32 size, char* name);
uint32 rpl_mapHLEImport(RPLModule* rplLoaderContext, const char* rplName, const char* funcName, bool functionMustExist); uint32 rpl_mapHLEImport(RPLModule* rplLoaderContext, const char* rplName, const char* funcName, bool functionMustExist);
void RPLLoader_Link(); void RPLLoader_Link();
@ -29,6 +29,7 @@ void RPLLoader_NotifyControlPassedToApplication();
void RPLLoader_AddDependency(const char* name); void RPLLoader_AddDependency(const char* name);
void RPLLoader_RemoveDependency(uint32 handle); void RPLLoader_RemoveDependency(uint32 handle);
bool RPLLoader_HasDependency(std::string_view name);
void RPLLoader_UpdateDependencies(); void RPLLoader_UpdateDependencies();
uint32 RPLLoader_GetHandleByModuleName(const char* name); uint32 RPLLoader_GetHandleByModuleName(const char* name);

View File

@ -225,17 +225,17 @@ struct RPLModule
}; };
typedef struct struct RPLDependency
{ {
char modulename[RPL_MODULE_NAME_LENGTH]; char modulename[RPL_MODULE_NAME_LENGTH];
char filepath[RPL_MODULE_PATH_LENGTH]; char filepath[RPL_MODULE_PATH_LENGTH];
bool loadAttempted; bool loadAttempted;
//bool isHLEModule; // determined to be a HLE module bool isCafeOSModule; // name is a known Cafe OS RPL
RPLModule* rplLoaderContext; // context of loaded module RPLModule* rplLoaderContext; // context of loaded module, can be nullptr for HLE COS modules
sint32 referenceCount; sint32 referenceCount;
uint32 coreinitHandle; // fake handle for coreinit uint32 coreinitHandle; // fake handle for coreinit
sint16 tlsModuleIndex; // tls module index assigned to this dependency sint16 tlsModuleIndex; // tls module index assigned to this dependency
}rplDependency_t; };
RPLModule* RPLLoader_FindModuleByCodeAddr(uint32 addr); RPLModule* RPLLoader_FindModuleByCodeAddr(uint32 addr);
RPLModule* RPLLoader_FindModuleByDataAddr(uint32 addr); RPLModule* RPLLoader_FindModuleByDataAddr(uint32 addr);

View File

@ -86,8 +86,7 @@ namespace coreinit
} }
// search for loaded modules with matching name // search for loaded modules with matching name
uint32 rplHandle = RPLLoader_GetHandleByModuleName(libName); uint32 rplHandle = RPLLoader_GetHandleByModuleName(libName);
if (rplHandle == RPL_INVALID_HANDLE && !RPLLoader_HasDependency(libName))
if (rplHandle == RPL_INVALID_HANDLE)
{ {
RPLLoader_AddDependency(libName); RPLLoader_AddDependency(libName);
RPLLoader_UpdateDependencies(); RPLLoader_UpdateDependencies();
@ -100,7 +99,10 @@ namespace coreinit
else else
*moduleHandleOut = rplHandle; *moduleHandleOut = rplHandle;
if (rplHandle == RPL_INVALID_HANDLE) if (rplHandle == RPL_INVALID_HANDLE)
{
cemuLog_logDebug(LogType::Force, "OSDynLoad_Acquire() failed to load module '{}'", libName);
return 0xFFFCFFE9; // module not found return 0xFFFCFFE9; // module not found
}
return 0; return 0;
} }

View File

@ -276,7 +276,6 @@ void swkbdExport_SwkbdDisappearKeyboard(PPCInterpreter_t* hCPU)
void swkbdExport_SwkbdGetInputFormString(PPCInterpreter_t* hCPU) void swkbdExport_SwkbdGetInputFormString(PPCInterpreter_t* hCPU)
{ {
debug_printf("SwkbdGetInputFormString__3RplFv LR: %08x\n", hCPU->spr.LR);
for(sint32 i=0; i<swkbdInternalState->formStringLength; i++) for(sint32 i=0; i<swkbdInternalState->formStringLength; i++)
{ {
swkbdInternalState->formStringBufferBE[i] = _swapEndianU16(swkbdInternalState->formStringBuffer[i]); swkbdInternalState->formStringBufferBE[i] = _swapEndianU16(swkbdInternalState->formStringBuffer[i]);
@ -287,7 +286,6 @@ void swkbdExport_SwkbdGetInputFormString(PPCInterpreter_t* hCPU)
void swkbdExport_SwkbdIsDecideOkButton(PPCInterpreter_t* hCPU) void swkbdExport_SwkbdIsDecideOkButton(PPCInterpreter_t* hCPU)
{ {
debug_printf("SwkbdIsDecideOkButton__3RplFPb LR: %08x\n", hCPU->spr.LR);
if (swkbdInternalState->decideButtonWasPressed) if (swkbdInternalState->decideButtonWasPressed)
osLib_returnFromFunction(hCPU, 1); osLib_returnFromFunction(hCPU, 1);
else else