diff --git a/Core/CoreParameter.h b/Core/CoreParameter.h index da16dfe87..3cb404f46 100644 --- a/Core/CoreParameter.h +++ b/Core/CoreParameter.h @@ -39,7 +39,8 @@ struct CoreParameter { bool enableSound; // there aren't multiple sound cores. std::string fileToStart; - std::string mountIso; // If non-empty, and fileToStart is an ELF or PBP, will mount this ISO in the background. + std::string mountIso; // If non-empty, and fileToStart is an ELF or PBP, will mount this ISO in the background to umd1:. + std::string mountRoot; // If non-empty, and fileToStart is an ELF or PBP, mount this as host0: / umd0:. std::string errorString; bool startPaused; diff --git a/Core/FileSystems/MetaFileSystem.cpp b/Core/FileSystems/MetaFileSystem.cpp index 1c7197cd3..c52ca15d8 100644 --- a/Core/FileSystems/MetaFileSystem.cpp +++ b/Core/FileSystems/MetaFileSystem.cpp @@ -23,6 +23,7 @@ #include "Core/FileSystems/MetaFileSystem.h" #include "Core/HLE/sceKernelThread.h" #include "Core/Reporting.h" +#include "Core/System.h" static bool ApplyPathStringToComponentsVector(std::vector &vector, const std::string &pathString) { @@ -197,7 +198,13 @@ bool MetaFileSystem::MapFilePath(const std::string &_inpath, std::string &outpat // appears to mean the current directory on the UMD. Let's just assume the current directory. if (strncasecmp(inpath.c_str(), "host0:", strlen("host0:")) == 0) { INFO_LOG(FILESYS, "Host0 path detected, stripping: %s", inpath.c_str()); - inpath = inpath.substr(strlen("host0:")); + // However, this causes trouble when running tests, since our test framework uses host0:. + // Maybe it's really just supposed to map to umd0 or something? + if (PSP_CoreParameter().headLess) { + inpath = "umd0:" + inpath.substr(strlen("host0:")); + } else { + inpath = inpath.substr(strlen("host0:")); + } } const std::string *currentDirectory = &startingDirectory; diff --git a/Core/PSPLoaders.cpp b/Core/PSPLoaders.cpp index 511db5deb..d5c42400c 100644 --- a/Core/PSPLoaders.cpp +++ b/Core/PSPLoaders.cpp @@ -185,6 +185,20 @@ bool Load_PSP_ISO(const char *filename, std::string *error_string) return __KernelLoadExec(bootpath.c_str(), 0, error_string); } +static std::string NormalizePath(const std::string &path) +{ +#ifdef _WIN32 + char buf[512] = {0}; + if (GetFullPathNameA(path.c_str(), sizeof(buf) - 1, buf, NULL) == 0) + return ""; +#else + char buf[PATH_MAX + 1]; + if (realpath(path.c_str(), buf) == NULL) + return ""; +#endif + return buf; +} + bool Load_PSP_ELF_PBP(const char *filename, std::string *error_string) { // This is really just for headless, might need tweaking later. @@ -207,6 +221,25 @@ bool Load_PSP_ELF_PBP(const char *filename, std::string *error_string) path = ReplaceAll(path, "/", "\\"); #endif + if (!PSP_CoreParameter().mountRoot.empty()) + { + // We don't want to worry about .. and cwd and such. + const std::string rootNorm = NormalizePath(PSP_CoreParameter().mountRoot + "/"); + const std::string pathNorm = NormalizePath(path + "/"); + + // If root is not a subpath of path, we can't boot the game. + if (!startsWith(pathNorm, rootNorm)) + { + *error_string = "Cannot boot ELF located outside mountRoot."; + return false; + } + + const std::string filepath = ReplaceAll(pathNorm.substr(rootNorm.size()), "\\", "/"); + file = filepath + "/" + file; + path = rootNorm; + pspFileSystem.SetStartingDirectory(filepath); + } + DirectoryFileSystem *fs = new DirectoryFileSystem(&pspFileSystem, path); pspFileSystem.Mount("umd0:", fs); diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 6658d6067..6a28d2d45 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -89,6 +89,7 @@ void EmuScreen::bootGame(const std::string &filename) { coreParam.enableSound = g_Config.bEnableSound; coreParam.fileToStart = filename; coreParam.mountIso = ""; + coreParam.mountRoot = ""; coreParam.startPaused = false; coreParam.printfEmuLog = false; coreParam.headLess = false; diff --git a/android/jni/TestRunner.cpp b/android/jni/TestRunner.cpp index 2b88f3e6a..80b8cf44b 100644 --- a/android/jni/TestRunner.cpp +++ b/android/jni/TestRunner.cpp @@ -64,11 +64,18 @@ void RunTests() { std::string output; +#ifdef IOS + const std::string baseDirectory = g_Config.flash0Directory + "../"; +#else + const std::string baseDirectory = g_Config.memCardDirectory; +#endif + CoreParameter coreParam; coreParam.cpuCore = g_Config.bJit ? CPU_JIT : CPU_INTERPRETER; coreParam.gpuCore = g_Config.bSoftwareRendering ? GPU_SOFTWARE : GPU_GLES; coreParam.enableSound = g_Config.bEnableSound; coreParam.mountIso = ""; + coreParam.mountRoot = baseDirectory + "pspautotests/"; coreParam.startPaused = false; coreParam.printfEmuLog = false; coreParam.headLess = true; @@ -80,12 +87,6 @@ void RunTests() coreParam.unthrottle = true; coreParam.updateRecent = false; -#ifdef IOS - std::string baseDirectory = g_Config.flash0Directory + "../"; -#else - std::string baseDirectory = g_Config.memCardDirectory; -#endif - // Never report from tests. std::string savedReportHost = g_Config.sReportHost; g_Config.sReportHost = ""; diff --git a/headless/Headless.cpp b/headless/Headless.cpp index 5d4836004..17f45a26b 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -80,7 +80,7 @@ bool System_InputBoxGetWString(const wchar_t *title, const std::wstring &default InputState input_state; #endif -void printUsage(const char *progname, const char *reason) +int printUsage(const char *progname, const char *reason) { if (reason != NULL) fprintf(stderr, "Error: %s\n\n", reason); @@ -88,7 +88,8 @@ void printUsage(const char *progname, const char *reason) fprintf(stderr, "This is primarily meant as a non-interactive test tool.\n\n"); fprintf(stderr, "Usage: %s file.elf... [options]\n\n", progname); fprintf(stderr, "Options:\n"); - fprintf(stderr, " -m, --mount umd.cso mount iso on umd:\n"); + fprintf(stderr, " -m, --mount umd.cso mount iso on umd1:\n"); + fprintf(stderr, " -r, --root some/path mount path on host0: (elfs must be in here)\n"); fprintf(stderr, " -l, --log full log output, not just emulated printfs\n"); #if HEADLESSHOST_CLASS != HeadlessHost @@ -105,6 +106,8 @@ void printUsage(const char *progname, const char *reason) fprintf(stderr, " -j use jit (default)\n"); fprintf(stderr, " -c, --compare compare with output in file.expected\n"); fprintf(stderr, "\nSee headless.txt for details.\n"); + + return 1; } static HeadlessHost * getHost(GPUCore gpuCore) { @@ -205,20 +208,24 @@ int main(int argc, const char* argv[]) std::vector testFilenames; const char *mountIso = 0; + const char *mountRoot = 0; const char *screenshotFilename = 0; - bool readMount = false; float timeout = std::numeric_limits::infinity(); for (int i = 1; i < argc; i++) { - if (readMount) - { - mountIso = argv[i]; - readMount = false; - continue; - } if (!strcmp(argv[i], "-m") || !strcmp(argv[i], "--mount")) - readMount = true; + { + if (++i >= argc) + return printUsage(argv[0], "Missing argument after -m"); + mountIso = argv[i]; + } + else if (!strcmp(argv[i], "-r") || !strcmp(argv[i], "--root")) + { + if (++i >= argc) + return printUsage(argv[0], "Missing argument after -r"); + mountRoot = argv[i]; + } else if (!strcmp(argv[i], "-l") || !strcmp(argv[i], "--log")) fullLog = true; else if (!strcmp(argv[i], "-i")) @@ -241,10 +248,7 @@ int main(int argc, const char* argv[]) else if (!strcasecmp(gpuName, "null")) gpuCore = GPU_NULL; else - { - printUsage(argv[0], "Unknown gpu backend specified after --graphics="); - return 1; - } + return printUsage(argv[0], "Unknown gpu backend specified after --graphics="); } // Default to GLES if no value selected. else if (!strcmp(argv[i], "--graphics")) @@ -258,10 +262,7 @@ int main(int argc, const char* argv[]) else if (!strncmp(argv[i], "--state=", strlen("--state=")) && strlen(argv[i]) > strlen("--state=")) stateToLoad = argv[i] + strlen("--state="); else if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h")) - { - printUsage(argv[0], NULL); - return 1; - } + return printUsage(argv[0], NULL); else testFilenames.push_back(argv[i]); } @@ -277,16 +278,8 @@ int main(int argc, const char* argv[]) testFilenames.push_back(temp); } - if (readMount) - { - printUsage(argv[0], "Missing argument after -m"); - return 1; - } if (testFilenames.empty()) - { - printUsage(argv[0], argc <= 1 ? NULL : "No executables specified"); - return 1; - } + return printUsage(argv[0], argc <= 1 ? NULL : "No executables specified"); HeadlessHost *headlessHost = getHost(gpuCore); host = headlessHost; @@ -312,6 +305,7 @@ int main(int argc, const char* argv[]) coreParameter.gpuCore = glWorking ? gpuCore : GPU_NULL; coreParameter.enableSound = false; coreParameter.mountIso = mountIso ? mountIso : ""; + coreParameter.mountRoot = mountRoot ? mountRoot : ""; coreParameter.startPaused = false; coreParameter.printfEmuLog = !autoCompare; coreParameter.headLess = true; diff --git a/test.py b/test.py index e2c89aedb..691c33b7d 100755 --- a/test.py +++ b/test.py @@ -381,7 +381,7 @@ def run_tests(test_list, args): if len(test_filenames): # TODO: Maybe --compare should detect --graphics? - cmdline = [PPSSPP_EXE, '--compare', '--timeout=' + str(TIMEOUT), '@-'] + cmdline = [PPSSPP_EXE, '--root', TEST_ROOT + '../', '--compare', '--timeout=' + str(TIMEOUT), '@-'] cmdline.extend([i for i in args if i not in ['-g', '-m']]) c = Command(cmdline, '\n'.join(test_filenames))