Merge pull request #21258 from Kethen/adhoc_fixes

Fix Driver 76 not creating adhoc sockets
This commit is contained in:
Henrik Rydgård authored and GitHub committed 2026-02-15 22:55:47 +01:00
commit f5520ccb17
3 files changed
+60 -14

No files matched your search

+35 -14
View File
@@ -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<PSPModule>(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<PSPModule>(moduleId, error);
if (!module->isFake) {
if (!module->isFake || liedAboutThisModule(module)) {
if (resultBufferOffset < resultBufferSize) {
Memory::Write_U32(module->GetUID(), resultBuffer + resultBufferOffset);
resultBufferOffset += 4;
+1
View File
@@ -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);
+24
View File
@@ -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<const char *> 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");
}