mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
Merge pull request #22259 from hrydgard/firmware-modules-load-high
Firmware modules: Load to high memory
This commit is contained in:
5 files changed
+48
-8
No files matched your search
+37
-4
@@ -203,14 +203,23 @@ DisableHLEFlags AlwaysDisableHLEFlags() {
|
||||
return DisableHLEFlags::scePsmf | DisableHLEFlags::scePsmfPlayer | DisableHLEFlags::sceCcc;
|
||||
}
|
||||
|
||||
// Process compat flags.
|
||||
// Which modules we're HLE-ing is part of the machine's state, not a live setting: it's decided
|
||||
// when each module is loaded, and the syscall stubs written into memory then are what a savestate
|
||||
// captures. So latch it on the first use after boot, save it in the state, and restore it on load
|
||||
// - otherwise a state made on one side of the boundary gets its imports re-resolved against the
|
||||
// other, and every call into the module lands on an unresolved stub. Changing the setting takes
|
||||
// effect on the next boot, which is the only point it could have taken effect anyway.
|
||||
static DisableHLEFlags g_effectiveDisableHLE;
|
||||
static bool g_disableHLELatched;
|
||||
|
||||
// Flags the user asked for that we can't honour this boot, because the firmware modules they
|
||||
// need aren't in the NAND directory. Subtracted in GetDisableHLEFlags so that a missing dump
|
||||
// need aren't in the NAND directory. Subtracted in ComputeDisableHLEFlags so that a missing dump
|
||||
// leaves the HLE in place rather than handing the game unresolved imports, which is much worse
|
||||
// than our stubs. Recomputed per boot, since the dump can appear between runs.
|
||||
static DisableHLEFlags g_unavailableDisableFlags = (DisableHLEFlags)0;
|
||||
|
||||
static DisableHLEFlags GetDisableHLEFlags() {
|
||||
// Process compat flags.
|
||||
static DisableHLEFlags ComputeDisableHLEFlags() {
|
||||
DisableHLEFlags flags = (DisableHLEFlags)g_Config.iDisableHLE | AlwaysDisableHLEFlags();
|
||||
if (PSP_CoreParameter().compat.flags().DisableHLESceFont) {
|
||||
flags |= DisableHLEFlags::sceFont;
|
||||
@@ -225,6 +234,18 @@ static DisableHLEFlags GetDisableHLEFlags() {
|
||||
return flags;
|
||||
}
|
||||
|
||||
static DisableHLEFlags GetDisableHLEFlags() {
|
||||
if (!g_disableHLELatched) {
|
||||
g_effectiveDisableHLE = ComputeDisableHLEFlags();
|
||||
g_disableHLELatched = true;
|
||||
}
|
||||
return g_effectiveDisableHLE;
|
||||
}
|
||||
|
||||
DisableHLEFlags GetEffectiveDisableHLEFlags() {
|
||||
return GetDisableHLEFlags();
|
||||
}
|
||||
|
||||
// Note: name is the modname from prx, not the export module name!
|
||||
bool ShouldHLEModule(std::string_view modname, bool *wasDisabledManually) {
|
||||
if (wasDisabledManually) {
|
||||
@@ -296,16 +317,28 @@ static void CheckDisableHLEAvailability() {
|
||||
void HLEInit() {
|
||||
CheckDisableHLEAvailability();
|
||||
RegisterAllModules();
|
||||
// Latched lazily rather than here: the compat flags this depends on aren't loaded yet.
|
||||
g_disableHLELatched = false;
|
||||
g_stackSize = 0;
|
||||
delayedResultEvent = CoreTiming::RegisterEvent("HLEDelayedResult", hleDelayResultFinish);
|
||||
g_idleOp = GetSyscallOp("FakeSysCalls", NID_IDLE);
|
||||
}
|
||||
|
||||
void HLEDoState(PointerWrap &p) {
|
||||
auto s = p.Section("HLE", 1, 2);
|
||||
auto s = p.Section("HLE", 1, 3);
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
if (s >= 3) {
|
||||
int disableHLE = (int)GetDisableHLEFlags();
|
||||
Do(p, disableHLE);
|
||||
if (p.mode == p.MODE_READ) {
|
||||
// Whatever the config says now, this state's modules were loaded under these flags.
|
||||
g_effectiveDisableHLE = (DisableHLEFlags)disableHLE;
|
||||
g_disableHLELatched = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Can't be inside a syscall when saving state, reset this so errors aren't misleading.
|
||||
if (g_stackSize) {
|
||||
ERROR_LOG(Log::HLE, "Can't save state while in a HLE syscall");
|
||||
|
||||
@@ -127,6 +127,9 @@ void RegisterHLEModule(std::string_view name, int numFunctions, const HLEFunctio
|
||||
int GetNumRegisteredHLEModules();
|
||||
const HLEModule *GetHLEModuleByIndex(int index);
|
||||
DisableHLEFlags AlwaysDisableHLEFlags();
|
||||
// The flags actually in effect for this boot - latched at the first module load and restored from
|
||||
// savestates, so it can differ from what g_Config says if the setting changed since.
|
||||
DisableHLEFlags GetEffectiveDisableHLEFlags();
|
||||
|
||||
// Run the current thread's callbacks after the syscall finishes.
|
||||
void hleCheckCurrentCallbacks();
|
||||
|
||||
@@ -1927,14 +1927,14 @@ static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 load
|
||||
return module;
|
||||
}
|
||||
|
||||
SceUID KernelLoadModule(const std::string &filename, std::string *error_string) {
|
||||
SceUID KernelLoadModule(const std::string &filename, std::string *error_string, bool fromTop) {
|
||||
std::vector<uint8_t> buffer;
|
||||
if (pspFileSystem.ReadEntireFile(filename, buffer) < 0)
|
||||
return SCE_KERNEL_ERROR_NOFILE;
|
||||
|
||||
u32 error = SCE_KERNEL_ERROR_ILLEGAL_OBJECT;
|
||||
u32 magic;
|
||||
PSPModule *module = __KernelLoadELFFromPtr(&buffer[0], buffer.size(), 0, false, error_string, &magic, filename, error);
|
||||
PSPModule *module = __KernelLoadELFFromPtr(&buffer[0], buffer.size(), 0, fromTop, error_string, &magic, filename, error);
|
||||
|
||||
if (module == nullptr)
|
||||
return error;
|
||||
|
||||
@@ -247,7 +247,11 @@ bool KernelFindImportByStubAddr(u32 stubAddr, std::string *importModuleName, u32
|
||||
bool DescribeModuleAddress(u32 address, char *buffer, size_t bufferSize);
|
||||
int __KernelGPUReplay();
|
||||
void __KernelReturnFromModuleFunc();
|
||||
SceUID KernelLoadModule(const std::string &filename, std::string *error_string);
|
||||
// fromTop puts the module at the top of the user partition instead of the bottom. Use it for
|
||||
// firmware modules we inject before the game loads - taking the bottom pushes the game's own ELF
|
||||
// up, which shifts every address in it and invalidates cheats and achievements, and outright
|
||||
// fails for a game like Tekken 6 whose EBOOT must load at a fixed low address.
|
||||
SceUID KernelLoadModule(const std::string &filename, std::string *error_string, bool fromTop = false);
|
||||
int __KernelStartModule(SceUID moduleId, u32 argsize, u32 argAddr, u32 returnValueAddr, SceKernelSMOption *smoption, bool *needsWait);
|
||||
u32 __KernelStopUnloadSelfModuleWithOrWithoutStatus(u32 exitCode, u32 argSize, u32 argp, u32 statusAddr, u32 optionAddr, bool WithStatus);
|
||||
u32 sceKernelFindModuleByUID(u32 uid);
|
||||
|
||||
@@ -108,7 +108,7 @@ static void NotifyLoadStatusMp4(int state, u32 loadAddr, u32 totalSize) {
|
||||
continue;
|
||||
}
|
||||
std::string error;
|
||||
SceUID id = KernelLoadModule(paths[i], &error);
|
||||
SceUID id = KernelLoadModule(paths[i], &error, true);
|
||||
if (id < 0) {
|
||||
ERROR_LOG(Log::sceUtility, "sceMp4 HLE is disabled, but %s wouldn't load (%s) - "
|
||||
"the game will get unresolved imports", paths[i], error.c_str());
|
||||
|
||||
Reference in new issue
Block a user