mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-14 15:00:30 +02:00
Unload the firmware modules we swap in, when the game unloads the library
Tekken 6 never reaches gameplay with the real mpeg.prx: it plays its intro movie, returns to the title screen, starts loading a demo match and loads forever. With the sceMpeg HLE it plays fine. The game unloads its video libraries before the level load and expects the memory back. It gets most of it - scePsmf and scePsmfPlayer do go away - but mpeg.prx stays resident, 33KB of it, sitting in the middle of the region the loader then asks for: 08c64000 - 09e24000 18.6MB taken UserSbrk 09e24000 - 09ed4000 720KB free 09ed4000 - 09edc300 33.5KB taken ELF/sceMpeg_library 09edc300 - 09f44000 425KB free 09f44000 - 09f4c000 32KB taken UtilityModule/302_av_atrac3plus 0x09f44000 - 0x09e24000 is 0x120000, which is exactly the allocation that fails. Without mpeg.prx in the way that span is one free block and the level loads. sceUtility notifies the per-library hooks with state 1 when a utility module is loaded and -1 when it is unloaded. The hooks that swap in a firmware module only ever handled the load, so nothing ever took them back out. That affects sceMpeg, sceMp3, sceMp4 and sceAtrac alike; Tekken is just the game whose memory budget is tight enough to notice. The unload has to take out what we put in and nothing else, so the loaded ids are remembered rather than looked up by name: a game like Death Jr ships its own mpeg.prx and loads it itself, and freeing that would be freeing the game's memory. Verified that Death Jr still decodes its 1033 frames with our loader never touching its module. Savestates from before this have no record of what was swapped in, so they keep the old behaviour of leaving the modules loaded rather than risk freeing something the game owns. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
aeadfb3134
commit
1ad17e10d1
3 files changed
+69
-6
No files matched your search
@@ -2026,6 +2026,17 @@ static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 load
|
||||
return module;
|
||||
}
|
||||
|
||||
bool KernelUnloadModuleByID(SceUID moduleId) {
|
||||
u32 error;
|
||||
PSPModule *module = kernelObjects.Get<PSPModule>(moduleId, error);
|
||||
if (!module) {
|
||||
return false;
|
||||
}
|
||||
module->Cleanup();
|
||||
kernelObjects.Destroy<PSPModule>(moduleId);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool KernelModuleIsLoaded(std::string_view name) {
|
||||
u32 error;
|
||||
for (SceUID moduleId : loadedModules) {
|
||||
|
||||
Reference in new issue
Block a user