diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index e126689afa..82f7b989f8 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -89,19 +89,39 @@ enum : u32 { NID_MODULE_SDK_VERSION = 0x11B97506, }; -// This is a workaround for misbehaving homebrew (like TBL's Suicide Barbie (Final)). -static const char * const lieAboutSuccessModules[] = { - "flash0:/kd/audiocodec.prx", - "flash0:/kd/audiocodec_260.prx", - "flash0:/kd/libatrac3plus.prx", - "disc0:/PSP_GAME/SYSDIR/UPDATE/EBOOT.BIN", - "flash0:/kd/ifhandle.prx", - "flash0:/kd/pspnet.prx", - "flash0:/kd/pspnet_inet.prx", - "flash0:/kd/pspnet_apctl.prx", - "flash0:/kd/pspnet_resolver.prx", +struct LieModuleEntry { + const char *path; + const char *name; }; +// This is a workaround for misbehaving homebrew (like TBL's Suicide Barbie (Final)) and games (like Drive 76). +// In the case of Driver 76, it uses sceKernelGetModuleIdList and sceKernelQueryModuleInfo to check if adhoc modules are loaded +static const struct LieModuleEntry lieAboutSuccessModules[] = { + { "flash0:/kd/audiocodec.prx", "sceAudiocodec_Driver" }, + { "flash0:/kd/audiocodec_260.prx", "sceAudiocodec_Driver" }, + { "flash0:/kd/libatrac3plus.prx", "sceATRAC3plus_Library" }, + { "disc0:/PSP_GAME/SYSDIR/UPDATE/EBOOT.BIN", "" }, + { "flash0:/kd/ifhandle.prx", "sceNet_Service" }, + { "flash0:/kd/pspnet.prx", "sceNet_Library" }, + { "flash0:/kd/pspnet_inet.prx", "sceNetInet_Library" }, + { "flash0:/kd/pspnet_apctl.prx", "sceNetApctl_Library" }, + { "flash0:/kd/pspnet_resolver.prx", "sceNetResolver_Library" }, + { "flash0:/kd/pspnet_adhoc.prx", "sceNetAdhoc_Library" }, + { "flash0:/kd/pspnet_adhocctl.prx", "sceNetAdhocctl_Library" }, + { "flash0:/kd/pspnet_adhoc_matching.prx", "sceNetAdhocMatching_Library" }, + { "flash0:/kd/pspnet_adhoc_download.prx", "sceNetAdhocDownload_Library" }, + { "flash0:/kd/pspnet_adhoc_discover.prx", "sceNetAdhocDiscover_Library" }, +}; + +static const bool liedAboutThisModule(PSPModule *mod) { + for (int i = 0 ; i < ARRAY_SIZE(lieAboutSuccessModules) ; i++) { + if (strcmp(lieAboutSuccessModules[i].name, mod->GetName()) == 0){ + return true; + } + } + return false; +} + const char *NativeModuleStatusToString(NativeModuleStatus status) { switch (status) { case MODULE_STATUS_STARTING: return "STARTING"; @@ -1908,11 +1928,12 @@ u32 sceKernelLoadModule(const char *name, u32 flags, u32 optionAddr) { } for (size_t i = 0; i < ARRAY_SIZE(lieAboutSuccessModules); i++) { - if (!strcmp(name, lieAboutSuccessModules[i])) { + if (!strcmp(name, lieAboutSuccessModules[i].path)) { PSPModule *module = new PSPModule(); kernelObjects.Create(module); loadedModules.insert(module->GetUID()); memset(&module->nm, 0, sizeof(module->nm)); + strcpy(module->nm.name, lieAboutSuccessModules[i].name); module->isFake = true; module->nm.entry_addr = -1; module->nm.gp_value = -1; @@ -2067,7 +2088,7 @@ int __KernelStartModule(SceUID moduleId, u32 argsize, u32 argAddr, u32 returnVal return moduleId; } -static u32 sceKernelStartModule(u32 moduleId, u32 argsize, u32 argAddr, u32 returnValueAddr, u32 optionAddr) { +u32 sceKernelStartModule(u32 moduleId, u32 argsize, u32 argAddr, u32 returnValueAddr, u32 optionAddr) { u32 error; PSPModule *module = kernelObjects.Get(moduleId, error); if (!module) { @@ -2578,7 +2599,7 @@ static u32 sceKernelGetModuleIdList(u32 resultBuffer, u32 resultBufferSize, u32 u32 error; for (SceUID moduleId : loadedModules) { PSPModule *module = kernelObjects.Get(moduleId, error); - if (!module->isFake) { + if (!module->isFake || liedAboutThisModule(module)) { if (resultBufferOffset < resultBufferSize) { Memory::Write_U32(module->GetUID(), resultBuffer + resultBufferOffset); resultBufferOffset += 4; diff --git a/Core/HLE/sceKernelModule.h b/Core/HLE/sceKernelModule.h index 5deb16c5e1..13af5ef5ef 100644 --- a/Core/HLE/sceKernelModule.h +++ b/Core/HLE/sceKernelModule.h @@ -240,3 +240,4 @@ void Register_ModuleMgrForKernel(); // Expose for use by KUBridge. u32 sceKernelLoadModule(const char *name, u32 flags, u32 optionAddr); +u32 sceKernelStartModule(u32 moduleId, u32 argsize, u32 argAddr, u32 returnValueAddr, u32 optionAddr); diff --git a/Core/HLE/sceUtility.cpp b/Core/HLE/sceUtility.cpp index af4984c221..881828be1c 100644 --- a/Core/HLE/sceUtility.cpp +++ b/Core/HLE/sceUtility.cpp @@ -41,6 +41,7 @@ #include "Core/HLE/sceKernelInterrupt.h" #include "Core/HLE/sceKernelMemory.h" #include "Core/HLE/sceKernelThread.h" +#include "Core/HLE/sceKernelModule.h" #include "Core/HLE/scePower.h" #include "Core/HLE/sceAtrac.h" #include "Core/HLE/sceUtility.h" @@ -1303,6 +1304,29 @@ static u32 sceUtilityGetSystemParamInt(u32 id, u32 destaddr) { } static u32 sceUtilityLoadNetModule(u32 module) { + // Driver 76 actually checks using sceKernelGetModuleIdList, so we load the HLE module here for checking + std::vector mod_list; + + if (module == 1) { + // PSP_NET_MODULE_COMMON on pspsdk + mod_list.push_back("flash0:/kd/ifhandle.prx"); + mod_list.push_back("flash0:/kd/pspnet.prx"); + } else if (module == 2) { + // PSP_NET_MODULE_ADHOC on pspsdk + mod_list.push_back("flash0:/kd/pspnet_adhoc.prx"); + mod_list.push_back("flash0:/kd/pspnet_adhocctl.prx"); + mod_list.push_back("flash0:/kd/pspnet_adhoc_matching.prx"); + mod_list.push_back("flash0:/kd/pspnet_adhoc_download.prx"); + mod_list.push_back("flash0:/kd/pspnet_adhoc_discover.prx"); + } + + for (const char *mod_path : mod_list) { + u32 modid = hleCall(ModuleMgrForUser, u32, sceKernelLoadModule, mod_path, 0, 0); + if (modid >= 0) { + hleCall(ModuleMgrForUser, u32, sceKernelStartModule, modid, 0, 0, 0, 0); + } + } + return hleLogInfo(Log::sceUtility, 0, "FAKE"); }