Make sceUtilityLoadAvModule work correctly

This commit is contained in:
Henrik Rydgård committed 2025-03-15 17:40:24 +01:00
1 parent 143641b1cf
commit 17d7dcdd6c
4 files changed
+73 -37

No files matched your search

+11 -2
View File
@@ -95,7 +95,11 @@ const AtracBase *__AtracGetCtx(int i, u32 *type) {
void __AtracInit() {
_assert_(sizeof(SceAtracContext) == 256);
atracInited = true;
atracLibVersion = 0;
atracLibCrc = 0;
atracInited = true; // TODO: This should probably only happen in __AtracNotifyLoadModule.
memset(atracContexts, 0, sizeof(atracContexts));
// Start with 2 of each in this order.
@@ -114,13 +118,18 @@ void __AtracShutdown() {
}
}
void __AtracLoadModule(int version, u32 crc, u32 bssAddr, int bssSize) {
void __AtracNotifyLoadModule(int version, u32 crc, u32 bssAddr, int bssSize) {
atracLibVersion = version;
atracLibCrc = crc;
INFO_LOG(Log::ME, "Atrac module loaded: atracLibVersion 0x%0x, atracLibcrc %x, bss: %x (%x bytes)", atracLibVersion, atracLibCrc, bssAddr, bssSize);
// Later, save bssAddr/bssSize and use them to return context addresses.
}
void __AtracNotifyUnloadModule() {
atracLibVersion = 0;
atracLibCrc = 0;
}
void __AtracDoState(PointerWrap &p) {
auto s = p.Section("sceAtrac", 1, 2);
if (!s)
+3 -1
View File
@@ -25,7 +25,9 @@ void Register_sceAtrac3plus();
void __AtracInit();
void __AtracDoState(PointerWrap &p);
void __AtracShutdown();
void __AtracLoadModule(int version, u32 crc, u32 bssAddr, int bssSize);
void __AtracNotifyLoadModule(int version, u32 crc, u32 bssAddr, int bssSize);
void __AtracNotifyUnloadModule();
enum AtracStatus : u8 {
ATRAC_STATUS_NO_DATA = 1,
+8 -5
View File
@@ -277,8 +277,9 @@ public:
const char *GetTypeName() override { return GetStaticTypeName(); }
static const char *GetStaticTypeName() { return "Module"; }
void GetQuickInfo(char *ptr, int size) override {
snprintf(ptr, size, "%sname=%s gp=%08x entry=%08x",
snprintf(ptr, size, "%s %d.%d name=%s gp=%08x entry=%08x",
isFake ? "faked " : "",
nm.version[0], nm.version[1],
nm.name,
nm.gp_value,
nm.entry_addr);
@@ -480,7 +481,8 @@ public:
void PSPModule::GetLongInfo(char *ptr, int bufSize) const {
StringWriter w(ptr, bufSize);
w.F("%s: Version %d.%d. %d segments", nm.name, nm.version[0], nm.version[1], nm.nsegment).endl();
w.F("%s: Version %d.%d. %d segments", nm.name, nm.version[1], nm.version[0], nm.nsegment).endl();
w.F("Memory block: %08x (%08x/%d bytes)", memoryBlockAddr, memoryBlockSize, memoryBlockSize).endl();
for (int i = 0; i < nm.nsegment; i++) {
w.F(" %08x (%08x bytes)\n", nm.segmentaddr[i], nm.segmentsize[i]);
}
@@ -1340,7 +1342,6 @@ static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 load
strncpy(module->nm.name, head->modname, ARRAY_SIZE(module->nm.name));
module->nm.entry_addr = -1;
module->nm.gp_value = -1;
module->nm.bss_size = head->bss_size;
// Let's still try to allocate it. It may use user memory.
u32 totalSize = 0;
@@ -1367,6 +1368,8 @@ static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 load
module->memoryBlockAddr = addr;
module->memoryBlockSize = totalSize;
module->nm.text_addr = addr;
module->nm.bss_size = head->bss_size;
module->nm.nsegment = head->nsegments;
module->nm.version[0] = head->module_ver_hi;
module->nm.version[1] = head->module_ver_lo;
@@ -1389,7 +1392,7 @@ static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 load
__PsmfPlayerLoadModule(devkitVersion, module->crc);
}
if (!strcmp(head->modname, "sceATRAC3plus_Library")) {
__AtracLoadModule(ver, module->crc, module->GetBSSAddr(), head->bss_size);
__AtracNotifyLoadModule(ver, module->crc, module->GetBSSAddr(), head->bss_size);
}
return module;
@@ -1775,7 +1778,7 @@ static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 load
__PsmfPlayerLoadModule(devkitVersion, module->crc);
}
if (!strcmp(modinfo->name, "sceATRAC3plus_Library")) {
__AtracLoadModule(modinfo->moduleVersion, module->crc, module->GetBSSAddr(), module->nm.bss_size);
__AtracNotifyLoadModule(modinfo->moduleVersion, module->crc, module->GetBSSAddr(), module->nm.bss_size);
}
}
+51 -29
View File
@@ -87,7 +87,10 @@ static void NotifyLoadStatusAtrac(int state, u32 loadAddr, u32 totalSize) {
constexpr int version = 0x103;
constexpr int bssSize = 0x67C;
_dbg_assert_(bssSize <= totalSize);
__AtracLoadModule(version, 0, loadAddr, bssSize);
__AtracNotifyLoadModule(version, 0, loadAddr, bssSize);
} else if (state == -1) {
// Unload.
__AtracNotifyUnloadModule();
}
}
@@ -508,6 +511,9 @@ bool __UtilityModuleGetMemoryRange(int moduleID, u32 *startPtr, u32 *sizePtr) {
return true;
}
static int LoadModuleInternal(u32 module);
static int UnloadModuleInternal(u32 module);
// Same as sceUtilityLoadModule, just limited in categories.
// It seems this just loads module 0x300 + module & 0xFF..
static u32 sceUtilityLoadAvModule(u32 module) {
@@ -516,30 +522,54 @@ static u32 sceUtilityLoadAvModule(u32 module) {
return hleLogError(Log::sceUtility, SCE_ERROR_AV_MODULE_BAD_ID);
}
if (module == 0)
JpegNotifyLoadStatus(1);
return hleDelayResult(hleLogInfo(Log::sceUtility, 0), "utility av module loaded", 25000);
int result = LoadModuleInternal(0x300 | module);
return hleDelayResult(hleLogDebugOrError(Log::sceUtility, result), "utility av module loaded", 25000);
}
static u32 sceUtilityUnloadAvModule(u32 module) {
if (module == 0)
JpegNotifyLoadStatus(-1);
return hleDelayResult(hleLogInfo(Log::sceUtility, 0), "utility av module unloaded", 800);
if (module > 7) {
ERROR_LOG_REPORT(Log::sceUtility, "sceUtilityLoadAvModule(%i): invalid module id", module);
return hleLogError(Log::sceUtility, SCE_ERROR_AV_MODULE_BAD_ID);
}
int result = UnloadModuleInternal(0x300 | module);
return hleDelayResult(hleLogDebugOrError(Log::sceUtility, result), "utility av module unloaded", 800);
}
static u32 sceUtilityLoadModule(u32 module) {
int result = LoadModuleInternal(module);
// TODO: Each module has its own timing, technically, but this is a low-end.
if (module == 0x3FF) {
return hleDelayResult(hleLogDebugOrError(Log::sceUtility, result), "utility module loaded", 130);
} else {
return hleDelayResult(hleLogDebugOrError(Log::sceUtility, result), "utility module loaded", 25000);
}
}
static u32 sceUtilityUnloadModule(u32 module) {
int result = UnloadModuleInternal(module);
// TODO: Each module has its own timing, technically, but this is a low-end.
if (module == 0x3FF) {
return hleDelayResult(hleLogDebugOrError(Log::sceUtility, result), "utility module unloaded", 110);
} else {
return hleDelayResult(hleLogDebugOrError(Log::sceUtility, result), "utility module unloaded", 400);
}
}
static int LoadModuleInternal(u32 module) {
const ModuleLoadInfo *info = __UtilityModuleInfo(module);
if (!info) {
return hleReportError(Log::sceUtility, SCE_ERROR_MODULE_BAD_ID, "invalid module id");
return SCE_ERROR_MODULE_BAD_ID;
}
if (currentlyLoadedModules.find(module) != currentlyLoadedModules.end()) {
return hleLogError(Log::sceUtility, SCE_ERROR_MODULE_ALREADY_LOADED, "already loaded");
return SCE_ERROR_MODULE_ALREADY_LOADED;
}
// Some games, like Kamen Rider Climax Heroes OOO, require an error if dependencies aren't loaded yet.
for (const int *dep = info->dependencies; *dep != 0; ++dep) {
if (currentlyLoadedModules.find(*dep) == currentlyLoadedModules.end()) {
return hleDelayResult(hleLogError(Log::sceUtility, SCE_KERNEL_ERROR_LIBRARY_NOTFOUND, "dependent module %04x not loaded", *dep), "utility module load attempt", 25000);
return SCE_KERNEL_ERROR_LIBRARY_NOTFOUND;
}
}
@@ -554,36 +584,28 @@ static u32 sceUtilityLoadModule(u32 module) {
if (info->notify) {
info->notify(1, address, allocSize);
}
// TODO: Each module has its own timing, technically, but this is a low-end.
if (module == 0x3FF)
return hleDelayResult(hleLogInfo(Log::sceUtility, 0), "utility module loaded", 130);
else
return hleDelayResult(hleLogInfo(Log::sceUtility, 0), "utility module loaded", 25000);
return 0;
}
static u32 sceUtilityUnloadModule(u32 module) {
static int UnloadModuleInternal(u32 module) {
const ModuleLoadInfo *info = __UtilityModuleInfo(module);
if (!info) {
return hleReportError(Log::sceUtility, SCE_ERROR_MODULE_BAD_ID, "invalid module id");
return SCE_ERROR_MODULE_BAD_ID;
}
if (currentlyLoadedModules.find(module) == currentlyLoadedModules.end()) {
return hleLogWarning(Log::sceUtility, SCE_ERROR_MODULE_NOT_LOADED, "not yet loaded");
auto iter = currentlyLoadedModules.find(module);
if (iter == currentlyLoadedModules.end()) {
return SCE_ERROR_MODULE_NOT_LOADED;
}
if (currentlyLoadedModules[module] != 0) {
userMemory.Free(currentlyLoadedModules[module]);
if (iter->second != 0) {
userMemory.Free(iter->second);
}
currentlyLoadedModules.erase(module);
if (info->notify)
if (info->notify) {
info->notify(-1, 0, 0);
// TODO: Each module has its own timing, technically, but this is a low-end.
if (module == 0x3FF)
return hleDelayResult(hleLogInfo(Log::sceUtility, 0), "utility module unloaded", 110);
else
return hleDelayResult(hleLogInfo(Log::sceUtility, 0), "utility module unloaded", 400);
}
return 0;
}
static int sceUtilityMsgDialogInitStart(u32 paramAddr) {