mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-09-20 11:27:48 +02:00
Run the real libmp4.prx/mp4msv.prx instead of our sceMp4 HLE, when asked
The MP4 libraries turn out to be the easiest place to hand a game Sony's own code: libmp4.prx needs only sceAudiocodecInit and sceAudiocodecDecode from us plus ordinary kernel calls, and mp4msv.prx - where the 41 functions libmp4 leans on live - imports nothing at all. So with a firmware dump present the pair can be loaded for real and left to decode through our sceAudiocodec. Adds DisableHLEFlags::sceMp4, which loads and starts both modules when the game asks sceUtility for the MP4 module, and a --disable-hle bitmask so a headless run can ask for this without a config file. Two things had to be fixed to make it work at all: - ModuleMgrForUser 0xD2FBC957 was unimplemented, and libmp4 calls it to get the gp of each callback it is handed. Implemented as sceKernelGetModuleGPByAddress. - Headless forced every module to HLE unconditionally, which silently undid the flag, and it did so before ApplyToConfig() had even parsed it. Tested with Speedball 2 - Evolution, which uses sceMp4 for its music: the game goes from 255645 calls into our stubs and 39 unresolved imports, to zero of each and 1943 AAC frames decoded through sceAudiocodec. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
committed by
Henrik Rydgård
co-authored by
Claude Opus 5
parent
d11175bb88
commit
c80f3d33c2
@@ -2713,6 +2713,34 @@ struct GetModuleIdByAddressArg
|
||||
SceUID result;
|
||||
};
|
||||
|
||||
// ModuleMgrForUser_D2FBC957. Looks up the gp value of whichever module contains an address, which
|
||||
// is how a library that is handed function pointers from another module can call them: MIPS code
|
||||
// needs the callee's gp in place. libmp4.prx uses it on the three callbacks it is given.
|
||||
// Named after what it does; the official name isn't known.
|
||||
static u32 sceKernelGetModuleGPByAddress(u32 addr, u32 gpPtr) {
|
||||
if (!Memory::IsValidAddress(gpPtr)) {
|
||||
return hleLogError(Log::sceModule, SCE_KERNEL_ERROR_ILLEGAL_ADDR, "bad gp pointer");
|
||||
}
|
||||
|
||||
u32 gp = 0;
|
||||
bool found = false;
|
||||
kernelObjects.Iterate<PSPModule>([&](int id, PSPModule *module) -> bool {
|
||||
const u32 start = module->memoryBlockAddr, size = module->memoryBlockSize;
|
||||
if (start != 0 && start <= addr && start + size > addr) {
|
||||
gp = module->nm.gp_value;
|
||||
found = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
if (!found) {
|
||||
return hleLogError(Log::sceModule, SCE_KERNEL_ERROR_UNKNOWN_MODULE, "no module at %08x", addr);
|
||||
}
|
||||
Memory::WriteUnchecked_U32(gp, gpPtr);
|
||||
return hleLogDebug(Log::sceModule, 0, "gp=%08x", gp);
|
||||
}
|
||||
|
||||
static u32 sceKernelGetModuleIdByAddress(u32 moduleAddr)
|
||||
{
|
||||
GetModuleIdByAddressArg state;
|
||||
@@ -3028,6 +3056,7 @@ const HLEFunction ModuleMgrForUser[] = {
|
||||
{0XF2D8D1B4, &WrapU_CUU<sceKernelLoadModuleNpDrm>, "sceKernelLoadModuleNpDrm", 'x', "sxx" },
|
||||
{0XE4C4211C, nullptr, "sceKernelLoadModuleWithBlockOffset", '?', "" },
|
||||
{0XFBE27467, nullptr, "sceKernelLoadModuleByIDWithBlockOffset", '?', "" },
|
||||
{0XD2FBC957, &WrapU_UU<sceKernelGetModuleGPByAddress>, "sceKernelGetModuleGPByAddress", 'x', "xx" },
|
||||
};
|
||||
|
||||
const HLEFunction ModuleMgrForKernel[] = {
|
||||
|
||||
Reference in New Issue
Block a user