Skip to content

Commit b8f2cf4

Browse files
authored
coreinit: Implement Dynload notify callbacks (#2003)
1 parent 50b9e4b commit b8f2cf4

4 files changed

Lines changed: 110 additions & 1 deletion

File tree

src/Cafe/OS/RPL/rpl.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2400,6 +2400,20 @@ RPLModule** RPLLoader_GetModuleList()
24002400
return rplModuleList;
24012401
}
24022402

2403+
RPLModule* RPLLoader_GetModuleByName(std::string_view name)
2404+
{
2405+
std::string normalizedName = _RPLLoader_ExtractModuleNameFromPath(name);
2406+
RPLModule** modules = RPLLoader_GetModuleList();
2407+
2408+
for (uint32 i = 0; i < RPLLoader_GetModuleCount(); i++)
2409+
{
2410+
if (modules[i]->moduleName == normalizedName)
2411+
return modules[i];
2412+
}
2413+
2414+
return nullptr;
2415+
}
2416+
24032417
sint32 RPLLoader_GetModuleCount()
24042418
{
24052419
return rplModuleCount;

src/Cafe/OS/RPL/rpl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ uint32 RPLLoader_GetSDA2Base();
4747

4848
sint32 RPLLoader_GetModuleCount();
4949
RPLModule** RPLLoader_GetModuleList();
50+
RPLModule* RPLLoader_GetModuleByName(std::string_view name);
5051

5152
MEMPTR<void> RPLLoader_AllocateCodeCaveMem(uint32 alignment, uint32 size);
5253
void RPLLoader_ReleaseCodeCaveMem(MEMPTR<void> addr);

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

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ namespace coreinit
1212
MPTR _osDynLoadTLSFuncAlloc = MPTR_NULL;
1313
MPTR _osDynLoadTLSFuncFree = MPTR_NULL;
1414

15+
static std::vector<NotifyCallbackEntry> notifyCallbacks;
16+
1517
uint32 OSDynLoad_SetAllocator(MPTR allocFunc, MPTR freeFunc)
1618
{
1719
_osDynLoadFuncAlloc = allocFunc;
@@ -109,6 +111,34 @@ namespace coreinit
109111
cemuLog_logDebug(LogType::Force, "OSDynLoad_Acquire() failed to load module '{}'", libName);
110112
return 0xFFFCFFE9; // module not found
111113
}
114+
115+
for (const auto& cb : notifyCallbacks)
116+
{
117+
MEMPTR<OSDynLoad_NotifyData> notifyData;
118+
notifyData = (OSDynLoad_NotifyData*)OSDynLoad_AllocatorAlloc(sizeof(OSDynLoad_NotifyData), 4);
119+
RPLModule* module = RPLLoader_GetModuleByName(tempLibName);
120+
121+
if (!module)
122+
break;
123+
124+
notifyData->name = module->ppcName.GetMPTR();
125+
126+
notifyData->textAddr = module->regionMappingBase_text.GetBEValue();
127+
notifyData->textOffset = module->regionMappingBase_text.GetMPTR() - module->regionOrigAddr_text;
128+
notifyData->textSize = module->regionSize_text;
129+
130+
notifyData->dataAddr = module->regionMappingBase_data;
131+
notifyData->dataOffset = module->regionMappingBase_data - module->regionOrigAddr_data;
132+
notifyData->dataSize = module->regionSize_data;
133+
134+
notifyData->readAddr = module->regionMappingBase_data;
135+
notifyData->readOffset = module->regionMappingBase_data - module->regionOrigAddr_data;
136+
notifyData->readSize = module->regionSize_data;
137+
138+
PPCCoreCallback(cb.callback, moduleHandleOut, cb.userContext.GetMPTR(), 1, notifyData.GetMPTR());
139+
OSDynLoad_AllocatorFree(notifyData);
140+
141+
}
112142
return 0;
113143
}
114144

@@ -121,6 +151,35 @@ namespace coreinit
121151
{
122152
if (moduleHandle == RPL_INVALID_HANDLE)
123153
return;
154+
155+
for (const auto& cb : notifyCallbacks)
156+
{
157+
MEMPTR<OSDynLoad_NotifyData> notifyData;
158+
notifyData = (OSDynLoad_NotifyData*)OSDynLoad_AllocatorAlloc(sizeof(OSDynLoad_NotifyData), 4);
159+
RPLModule* module = RPLLoader_GetModuleByName(RPLLoader_GetModuleNameByHandle(moduleHandle));
160+
161+
if (!module)
162+
break;
163+
164+
notifyData->name = module->ppcName.GetMPTR();
165+
166+
notifyData->textAddr = module->regionMappingBase_text.GetBEValue();
167+
notifyData->textOffset = module->regionMappingBase_text.GetMPTR() - module->regionOrigAddr_text;
168+
notifyData->textSize = module->regionSize_text;
169+
170+
notifyData->dataAddr = module->regionMappingBase_data;
171+
notifyData->dataOffset = module->regionMappingBase_data - module->regionOrigAddr_data;
172+
notifyData->dataSize = module->regionSize_data;
173+
174+
notifyData->readAddr = module->regionMappingBase_data;
175+
notifyData->readOffset = module->regionMappingBase_data - module->regionOrigAddr_data;
176+
notifyData->readSize = module->regionSize_data;
177+
178+
PPCCoreCallback(cb.callback, moduleHandle, cb.userContext.GetMPTR(), 2, notifyData.GetMPTR());
179+
OSDynLoad_AllocatorFree(notifyData);
180+
181+
}
182+
124183
RPLLoader_RemoveDependency(moduleHandle);
125184
RPLLoader_UpdateDependencies();
126185
}
@@ -195,6 +254,25 @@ namespace coreinit
195254
return 1;
196255
}
197256

257+
uint32 OSDynLoad_AddNotifyCallback(MEMPTR<OSDynLoadNotifyFunc> notifyFn, MEMPTR<void> userContext)
258+
{
259+
if (!notifyFn)
260+
return 0xBAD1000E; // notify function pointer is null
261+
262+
notifyCallbacks.emplace_back(notifyFn, userContext);
263+
return 0;
264+
}
265+
266+
uint32 OSDynLoad_DelNotifyCallback(MEMPTR<OSDynLoadNotifyFunc> notifyFn, MEMPTR<void> userContext)
267+
{
268+
std::erase_if(notifyCallbacks, [&](const NotifyCallbackEntry& entry)
269+
{
270+
return entry.callback.GetMPTR() == notifyFn.GetMPTR() && entry.userContext == userContext;
271+
});
272+
273+
return 0;
274+
}
275+
198276
void InitializeDynLoad()
199277
{
200278
cafeExportRegister("coreinit", OSDynLoad_SetAllocator, LogType::Placeholder);
@@ -209,5 +287,8 @@ namespace coreinit
209287
cafeExportRegister("coreinit", OSDynLoad_GetModuleName, LogType::Placeholder);
210288
cafeExportRegister("coreinit", OSDynLoad_GetNumberOfRPLs, LogType::Placeholder);
211289
cafeExportRegister("coreinit", OSDynLoad_GetRPLInfo, LogType::Placeholder);
290+
291+
cafeExportRegister("coreinit", OSDynLoad_AddNotifyCallback, LogType::Placeholder);
292+
cafeExportRegister("coreinit", OSDynLoad_DelNotifyCallback, LogType::Placeholder);
212293
}
213294
}

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,16 @@ namespace coreinit
1919
uint32be readSize;
2020
};
2121

22+
using OSDynLoadNotifyFunc = void (*)(uint32be* module, void *userContext, sint32 notifyReason, OSDynLoad_NotifyData *infos);
23+
24+
struct NotifyCallbackEntry
25+
{
26+
MEMPTR<OSDynLoadNotifyFunc> callback;
27+
MEMPTR<void> userContext;
28+
29+
NotifyCallbackEntry(MEMPTR<OSDynLoadNotifyFunc> func, MEMPTR<void> context) : callback(func), userContext(context) {}
30+
};
31+
2232
uint32 OSDynLoad_SetAllocator(MPTR allocFunc, MPTR freeFunc);
2333
void OSDynLoad_SetTLSAllocator(MPTR allocFunc, MPTR freeFunc);
2434
uint32 OSDynLoad_GetAllocator(betype<MPTR>* funcAlloc, betype<MPTR>* funcFree);
@@ -35,5 +45,8 @@ namespace coreinit
3545
sint32 OSDynLoad_GetNumberOfRPLs();
3646
uint32 OSDynLoad_GetRPLInfo(uint32 first, uint32 count, OSDynLoad_NotifyData* outInfos);
3747

48+
uint32 OSDynLoad_AddNotifyCallback(MEMPTR<OSDynLoadNotifyFunc> notifyFn, MEMPTR<void> userContext);
49+
uint32 OSDynLoad_DelNotifyCallback(MEMPTR<OSDynLoadNotifyFunc> notifyFn, MEMPTR<void> userContext);
50+
3851
void InitializeDynLoad();
39-
}
52+
}

0 commit comments

Comments
 (0)