From 482d17c6e155ffc0cb15dfbc180c56facb206150 Mon Sep 17 00:00:00 2001 From: Connor Harrison <37246828+connorh315@users.noreply.github.com> Date: Sun, 17 May 2026 19:11:21 +0100 Subject: [PATCH] Load custom modules stored in custom_modules/ (#4440) * Load custom modules stored in custom_modules/ * Fix formatting --- src/common/path_util.cpp | 1 + src/common/path_util.h | 36 +++++++++++++++++++----------------- src/core/linker.cpp | 19 +++++++++++++++++++ 3 files changed, 39 insertions(+), 17 deletions(-) diff --git a/src/common/path_util.cpp b/src/common/path_util.cpp index 6e70aa202..dc9043006 100644 --- a/src/common/path_util.cpp +++ b/src/common/path_util.cpp @@ -131,6 +131,7 @@ static auto UserPaths = [] { create_path(PathType::CacheDir, user_dir / CACHE_DIR); create_path(PathType::FontsDir, user_dir / FONTS_DIR); create_path(PathType::HomeDir, user_dir / HOME_DIR); + create_path(PathType::CustomModulesDir, user_dir / CUSTOM_MODULES_DIR); std::ofstream notice_file(user_dir / CUSTOM_TROPHY / "Notice.txt"); if (notice_file.is_open()) { diff --git a/src/common/path_util.h b/src/common/path_util.h index 485c72270..130d3d4fc 100644 --- a/src/common/path_util.h +++ b/src/common/path_util.h @@ -10,23 +10,24 @@ namespace Common::FS { enum class PathType { - UserDir, // Where shadPS4 stores its data. - LogDir, // Where log files are stored. - ScreenshotsDir, // Where screenshots are stored. - ShaderDir, // Where shaders are stored. - TempDataDir, // Where game temp data is stored. - GameDataDir, // Where game data is stored. - SysModuleDir, // Where system modules are stored. - DownloadDir, // Where downloads/temp files are stored. - CapturesDir, // Where rdoc captures are stored. - CheatsDir, // Where cheats are stored. - PatchesDir, // Where patches are stored. - MetaDataDir, // Where game metadata (e.g. trophies and menu backgrounds) is stored. - CustomTrophy, // Where custom files for trophies are stored. - CustomConfigs, // Where custom files for different games are stored. - CacheDir, // Where pipeline and shader cache is stored. - FontsDir, // Where dumped system fonts are stored. - HomeDir, // PS4 home directory + UserDir, // Where shadPS4 stores its data. + LogDir, // Where log files are stored. + ScreenshotsDir, // Where screenshots are stored. + ShaderDir, // Where shaders are stored. + TempDataDir, // Where game temp data is stored. + GameDataDir, // Where game data is stored. + SysModuleDir, // Where system modules are stored. + DownloadDir, // Where downloads/temp files are stored. + CapturesDir, // Where rdoc captures are stored. + CheatsDir, // Where cheats are stored. + PatchesDir, // Where patches are stored. + MetaDataDir, // Where game metadata (e.g. trophies and menu backgrounds) is stored. + CustomTrophy, // Where custom files for trophies are stored. + CustomConfigs, // Where custom files for different games are stored. + CacheDir, // Where pipeline and shader cache is stored. + FontsDir, // Where dumped system fonts are stored. + HomeDir, // PS4 home directory + CustomModulesDir // Where custom modules are stored. }; constexpr auto PORTABLE_DIR = "user"; @@ -48,6 +49,7 @@ constexpr auto CUSTOM_CONFIGS = "custom_configs"; constexpr auto CACHE_DIR = "cache"; constexpr auto FONTS_DIR = "fonts"; constexpr auto HOME_DIR = "home"; +constexpr auto CUSTOM_MODULES_DIR = "custom_modules"; // Filenames constexpr auto LOG_FILE = "shad_log.txt"; diff --git a/src/core/linker.cpp b/src/core/linker.cpp index 912a1cfa0..d82c5806a 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -5,6 +5,7 @@ #include "common/arch.h" #include "common/assert.h" #include "common/elf_info.h" +#include "common/logging/formatter.h" #include "common/logging/log.h" #include "common/path_util.h" #include "common/string_util.h" @@ -125,6 +126,24 @@ void Linker::Execute(const std::vector& args) { // Have libSceSysmodule preload our libraries. Libraries::SysModule::sceSysmodulePreloadModuleForLibkernel(); + // Load and start custom modules from the user directory. + std::string_view id = Common::ElfInfo::Instance().GameSerial(); + const auto& custom_mod_directory = + Common::FS::GetUserPath(Common::FS::PathType::CustomModulesDir) / id; + if (!std::filesystem::exists(custom_mod_directory)) { + std::filesystem::create_directory(custom_mod_directory); + } + for (const auto& entry : std::filesystem::directory_iterator(custom_mod_directory)) { + if (entry.is_regular_file()) { + LOG_INFO(Core_Linker, "Loading custom module: {}", + fmt::UTF(entry.path().u8string())); + if (LoadAndStartModule(entry.path(), 0, nullptr, nullptr) == -1) { + LOG_ERROR(Core_Linker, "Failed to load custom module: {}", + fmt::UTF(entry.path().u8string())); + } + } + } + // Simulate libSceGnmDriver initialization, which maps a chunk of direct memory. // Some games fail without accurately emulating this behavior. s64 phys_addr{};