diff --git a/Core/CmdLine.h b/Core/CmdLine.h index db58067838..b5c32ad835 100644 --- a/Core/CmdLine.h +++ b/Core/CmdLine.h @@ -89,8 +89,7 @@ struct CommandLineOptions { std::optional unpackUpdaterModel; std::optional unpackUpdaterFilter; // Headless: install the firmware bundled on the disc being booted into a scratch NAND, and - // boot against that. Lets a run exercise the paths that need real firmware modules without - // having to install one first. + // boot against that. std::optional firmwareFromDisc; // Bitmask of DisableHLEFlags: run the real firmware module instead of our HLE for those diff --git a/Core/ConfigValues.h b/Core/ConfigValues.h index e1caa22745..3fd223cf02 100644 --- a/Core/ConfigValues.h +++ b/Core/ConfigValues.h @@ -154,7 +154,7 @@ enum class RestoreSettingsBits : int { }; ENUM_CLASS_BITOPS(RestoreSettingsBits); -// Modules that are candidates for disabling HLE of. +// Modules that are candidates for disabling HLE of, and just running the modules directly. enum class DisableHLEFlags : int { sceFont = (1 << 0), sceAtrac = (1 << 1), @@ -167,8 +167,7 @@ enum class DisableHLEFlags : int { // Swaps in flash0:/kd/libmp4.prx and mp4msv.prx, which then decode through our sceAudiocodec. sceMp4 = (1 << 8), // Small leaf libraries games carry on the disc themselves - see AlwaysDisableHLEFlags. None of - // them is in any firmware dump, so the game's own copy is the only one there is, and none - // imports anything we don't already have. + // them is provided in any firmware version. sceDeflt = (1 << 9), sceAdler = (1 << 10), sceMd5 = (1 << 11), diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index ec60ecf29a..4633f3ddcd 100644 --- a/Core/HLE/HLE.cpp +++ b/Core/HLE/HLE.cpp @@ -161,15 +161,14 @@ static const HLEModuleMeta g_moduleMeta[] = { {"mp4msv_module", "mp4msv", DisableHLEFlags::sceMp4}, {"SceParseHTTPheader_Library", "sceParseHttp", DisableHLEFlags::sceParseHttp}, {"SceParseURI_Library", "sceParseUri", DisableHLEFlags::sceParseUri}, - // Leaf libraries games carry on the disc. Module names and export library names read off the - // copies on real discs with --re-module disc0:/...; all but sceHeap import nothing at all, and - // sceHeap only Kernel_Library and ThreadManForUser. + // Dependency-free libraries games carry on the disc (never loaded from firmware). {"sceDEFLATE_Library", "sceDeflt", DisableHLEFlags::sceDeflt}, {"sceADLER32_Library", "sceAdler", DisableHLEFlags::sceAdler}, {"sceMD5_Library", "sceMd5", DisableHLEFlags::sceMd5}, {"sceSHA256_Library", "sceSha256", DisableHLEFlags::sceSha256}, {"sceMT19937_Library", "sceMt19937", DisableHLEFlags::sceMt19937}, {"sceSfmt19937_Library", "sceSfmt19937", DisableHLEFlags::sceSfmt19937}, + // sceHeap imports only Kernel_Library and ThreadManForUser. {"sceHeap_Library", "sceHeap", DisableHLEFlags::sceHeap}, // Guessing these names {"sceJpeg", "sceJpeg"}, @@ -342,11 +341,8 @@ static void hleDelayResultFinish(u64 userdata, int cycleslate) { static void CheckDisableHLEAvailability() { g_unavailableDisableFlags = (DisableHLEFlags)0; - // The real libfont.prx a disc ships reads its fonts from flash0:/font and has nothing to fall - // back on, so without them it would render nothing at all. Our HLE does have a fallback - the - // fonts in assets - so keep it when the NAND set isn't there. Same question the HLE font loader - // asks itself, so the same answer: "the fonts this game's firmware would have had", not every - // font we know of, since an older game's firmware never had the later ones. + // libfont.prx/sceFont is shipped on game discs but reads its fonts from flash0:/font and has + // nothing to fall back on, so the fonts are required. if (AlwaysDisableHLEFlags() & DisableHLEFlags::sceFont) { if (!NandFontsComplete()) { g_unavailableDisableFlags |= DisableHLEFlags::sceFont; @@ -444,7 +440,6 @@ const HLEModule *GetHLEModuleByIndex(int index) { return &moduleDB[index]; } -// TODO: Do something faster. const HLEModule *GetHLEModuleByName(std::string_view name) { for (auto &module : moduleDB) { if (name == module.name) { @@ -454,7 +449,6 @@ const HLEModule *GetHLEModuleByName(std::string_view name) { return nullptr; } -// TODO: Do something faster. const HLEFunction *GetHLEFuncByName(const HLEModule *module, std::string_view name) { for (int i = 0; i < module->numFunctions; i++) { auto &func = module->funcTable[i]; diff --git a/headless/Headless.cpp b/headless/Headless.cpp index bed12ab90a..0ec0da4b4f 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -292,9 +292,8 @@ static GraphicsContext *CreateGraphicsContext(GPUCore gpuCore, std::string **dev // Whether what we're booting is homebrew rather than a retail disc. The two want opposite // defaults for the graduated HLE modules - see where this is used. // -// By extension, not by content: this runs before the loaders are up, and Identify_File can't even -// see the file yet. pspautotests is .prx, with .elf as its fallback, and that is the whole set we -// need to tell apart from a disc. +// This runs before the loaders are up, and Identify_File can't even see the file yet. +// pspautotests is .prx, with .elf as its fallback. static bool BootTargetIsHomebrewExecutable(const std::string &filename) { const std::string ext = Path(filename).GetFileExtension(); return ext == ".prx" || ext == ".elf"; @@ -792,26 +791,17 @@ int main(int argc, const char* argv[]) { // overrides above, so a matching command line flag always wins. cmdLineOptions.ApplyToConfig(); - // pspautotests is homebrew PRXes that ship none of the user libraries a retail disc carries, so - // the graduated modules (scePsmfPlayer and friends) would have nothing real to run and every - // test that touches them would fail on unresolved imports. Force those back to HLE. - // - // A disc is the opposite case: it brings its own copies and the app runs them for real, so - // headless has to as well or it isn't testing what ships. An explicit --disable-hle always - // wins, in either case, since the caller is saying they have what's needed. - // From the resolved list, not the command line: a test batch arrives as "@-" and is expanded - // above, and that is not a disc however it is spelled. A batch is always homebrew; a game run - // is exactly one disc. A --vsh run has no file at all and keeps the homebrew treatment, since - // the shell's own libraries come from the firmware rather than from a disc. + // pspautotests is plain homebrew PRXes so do not ship user libraries that a retail disc may carry. + // So we must use HLE, unless we install firmware. + // A disc brings its own copies and the app runs them for real, so + // headless has to as well or it isn't testing what ships. const bool bootIsDisc = testFilenames.size() == 1 && !BootTargetIsHomebrewExecutable(testFilenames[0]); if (!bootIsDisc) { g_Config.iForceEnableHLE = 0xFFFFFFFF & ~g_Config.iDisableHLE; } - - - // This looks contradictory to the above. But, this preserves the old test behavior which apparently ran the JIT for the CPU + // This looks contradictory to above checks. But, this preserves the old test behavior which apparently ran the JIT for the CPU // but ended up running software vertex decoding due to the setting in g_Config. Yeah, it's a mess. CPUCore cpuCore = CPUCore::JIT; if (cmdLineOptions.cpuCore.has_value()) { @@ -900,9 +890,8 @@ int main(int argc, const char* argv[]) { g_Config.nandRootDirectory = GetSysDirectory(DIRECTORY_NAND); coreParameter.nandRoot = g_Config.nandRootDirectory; - // Most discs carry the firmware they shipped with, which is the right version to run this game - // against and saves installing one by hand. Unpacked per disc and kept, so a second run of the - // same game reuses it - these are ~25MB each. + // Most discs carry the firmware they shipped with - this option installs it, if one + // isn't already installed. TODO: Check version here. if (cmdLineOptions.firmwareFromDisc.value_or(false)) { if (!bootIsDisc) { fprintf(stderr, "--firmware-from-disc only applies when booting a disc\n"); @@ -928,6 +917,7 @@ int main(int argc, const char* argv[]) { g_Config.nandRootDirectory = nand; coreParameter.nandRoot = nand; } + // Placed here rather than with the other early-exit subcommands above, because resolving a // "flash0:/kd/foo.prx" module path needs nandRootDirectory, which is only settled just above. if (cmdLineOptions.reDecrypt.has_value()) { diff --git a/headless/ReverseEngineer.h b/headless/ReverseEngineer.h index 212bc5df32..8f71d8c713 100644 --- a/headless/ReverseEngineer.h +++ b/headless/ReverseEngineer.h @@ -22,12 +22,12 @@ #include "Common/CommonTypes.h" struct ReverseEngineerOptions { - // PRX/ELF to load. A host path; a PSP path like "flash0:/kd/libmp3.prx", resolved against the - // configured NAND directory; or "disc0:/PSP_GAME/USRDIR/MODULES/LIBDEFLT.PRX", read out of the - // disc image named as the positional argument. The last is how you look at the copy of a - // library a game ships rather than the firmware's. + // PRX/ELF to load. Can be either a host path or a PSP path like "flash0:/kd/libmp3.prx", + // resolved against the configured NAND directory, or even something like + // "disc0:/PSP_GAME/USRDIR/MODULES/LIBDEFLT.PRX", read out of the + // disc image named as the positional argument. std::string modulePath; - // The disc image a "disc0:" modulePath is read from. + // The disc image that a "disc0:" modulePath is read from. std::string discPath; // Where to write the report. Created if missing. std::string outDir;