sceUtility: load the firmware's module for a disabled HLE library

Doing this was written once, for sceMp4, remembering the two UIDs it had
loaded in a static. That static was the only thing stopping a second copy
being loaded on top of the first, and it didn't survive a savestate: resuming
in a fresh process left it at zero while the restored module list already had
the modules in it. Ask the module list instead, which needs no state of its
own and is right after a savestate load and across games.

With the mechanism shared, sceMp3 and sceAtrac get it too. libmp3.prx and
libatrac3plus.prx each import nothing but the kernel and sceAudiocodec, so
both run against what we already have. The sceAtrac checkbox previously led
to an error log and a debug assert saying it wouldn't work, with a note that
we could go and find the file - which is what this does.

This is only ever the path for a game that ships no copy of the library. One
that does loads it directly and never asks sceUtility for it.

Also:
 - a module we're really loading no longer reserves its stand-in block as
   well. That block only stands in for memory we aren't otherwise taking, so
   reserving both charges the game twice, at the top of user memory where
   thread stacks come from.
 - the module loads at the bottom of the user partition. fromTop is for a
   module injected before the game's executable is placed; by the time a game
   calls sceUtility nothing moves either way, and the firmware's utility.prx
   allocates AV module memory as PSP_SMEM_Low.
 - NotifyLoadStatusAtrac read the raw setting rather than the effective
   flags, so it could fire for a flag that wasn't in effect.
 - the missing-firmware case now says so on screen, naming the library and
   pointing at installing a firmware, rather than only logging.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Henrik Rydgård
2026-09-12 11:11:41 -06:00
co-authored by Claude Opus 5
parent 3ddde0fdfe
commit 4df01fd990
4 changed files with 140 additions and 51 deletions
+15
View File
@@ -2026,6 +2026,21 @@ static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 load
return module;
}
bool KernelModuleIsLoaded(std::string_view name) {
u32 error;
for (SceUID moduleId : loadedModules) {
PSPModule *module = kernelObjects.Get<PSPModule>(moduleId, error);
// A fake module is our own HLE stand-in, which isn't the real library being asked about.
if (!module || module->isFake) {
continue;
}
if (equals(name, module->nm.name)) {
return true;
}
}
return false;
}
SceUID KernelLoadModule(const std::string &filename, std::string *error_string, bool fromTop) {
std::vector<uint8_t> buffer;
if (pspFileSystem.ReadEntireFile(filename, buffer) < 0)