diff --git a/Core/CmdLine.cpp b/Core/CmdLine.cpp index b6012a52f9..392bf38ab3 100644 --- a/Core/CmdLine.cpp +++ b/Core/CmdLine.cpp @@ -512,7 +512,6 @@ void CommandLineOptions::ApplyToConfig() const { if (pauseMenuExit.has_value()) { g_Config.bPauseMenuExitsEmulator = pauseMenuExit.value(); } - if (debuggerPort.has_value()) { g_Config.iRemoteISOPort = debuggerPort.value(); g_Config.DoNotSaveSetting(&g_Config.iRemoteISOPort); @@ -551,6 +550,12 @@ void CommandLineOptions::ApplyToConfig() const { CreateSysDirectories(); } + if (nand.has_value()) { + // No DoNotSaveSetting() here - memStickDirectory isn't an ordinary setting and never gets + // written to ppsspp.ini, since the ini itself lives inside the memory stick directory. + g_Config.nandRootDirectory = Path(nand.value()); + } + if (resolutionScale.has_value()) { g_Config.iInternalResolution = resolutionScale.value(); g_Config.DoNotSaveSetting(&g_Config.iInternalResolution); diff --git a/Core/CmdLine.h b/Core/CmdLine.h index 1fa39e0206..817262b804 100644 --- a/Core/CmdLine.h +++ b/Core/CmdLine.h @@ -59,6 +59,8 @@ struct CommandLineOptions { std::optional appendConfig; std::optional root; // This is supposed to configure host0:. + std::optional nand; // Set the root nand directory (one level above flash0, ...) + // Memory stick root (the directory containing PSP/GAME, PSP/SYSTEM, ...). Mainly for headless, // which otherwise always uses "memstick" next to the executable - so testing a real game there // meant copying it in. Points at the same layout the app uses, so the two can share one. diff --git a/Core/Config.h b/Core/Config.h index d0f18f6418..2a81b0f9d1 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -706,7 +706,7 @@ public: Path defaultCurrentDirectory; // Platform dependent, initialized at startup. Path memStickDirectory; - Path flash0Directory; + Path nandRootDirectory; Path internalDataDirectory; Path appCacheDirectory; diff --git a/Core/CoreParameter.h b/Core/CoreParameter.h index 790fec463b..22b75f18e8 100644 --- a/Core/CoreParameter.h +++ b/Core/CoreParameter.h @@ -59,9 +59,12 @@ struct CoreParameter { bool enableSound = true; // there aren't multiple sound cores. Path fileToStart; + Path mountIso; // If non-empty, and fileToStart is an ELF or PBP, will mount this ISO in the background to umd1:. Path mountRoot; // If non-empty, and fileToStart is an ELF or PBP, mount this as host0:. + Path nandRoot; // If non-empty, use this directory as the root above flash0:-flash3: (which are hosted in subdirectories flash0-flash3 of it). + std::string errorString; bool loadGameConfigs = true; diff --git a/Core/FileSystems/MetaFileSystem.cpp b/Core/FileSystems/MetaFileSystem.cpp index 3bcde05700..5e157f35b0 100644 --- a/Core/FileSystems/MetaFileSystem.cpp +++ b/Core/FileSystems/MetaFileSystem.cpp @@ -195,6 +195,7 @@ int MetaFileSystem::MapFilePath(std::string_view _inpath, std::string *outpath, // Special handling: host0:command.txt (as seen in Super Monkey Ball Adventures, for example) // appears to mean the current directory on the UMD. + // Actually, not sure if this is still needed. It doesn't make a whole lot of sense. if (startsWithNoCase(inpath.c_str(), "host0:") && !host0Mapped_) { inpath = "umd0:" + inpath.substr(strlen("host0:")); } diff --git a/Core/Reporting.cpp b/Core/Reporting.cpp index 08025004d1..67b61949a9 100644 --- a/Core/Reporting.cpp +++ b/Core/Reporting.cpp @@ -558,12 +558,6 @@ namespace Reporting if (PSP_GetBootState() == BootState::Complete && g_paramSFO.GetValueString("DISC_VERSION").empty()) return false; - // Some users run the exe from a zip or something, and don't have fonts. - // This breaks things, but let's not report it since it's confusing. - File::FileInfo fo; - if (!File::Exists(g_Config.flash0Directory / "font/jpn0.pgf") || !g_VFS.GetFileInfo("flash0/font/jpn0.pgf", &fo)) - return false; - return !everUnsupported; } diff --git a/Core/System.cpp b/Core/System.cpp index edbc119fd4..6a97027acb 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -300,12 +300,6 @@ static void ShowCompatWarnings(const Compatibility &compat) { extern const std::string INDEX_FILENAME; static void MountFileSystems() { - // TODO: Revisit this flash0 configurability. It was added for -#if PPSSPP_PLATFORM(WINDOWS) || PPSSPP_PLATFORM(MACOS) - auto flash0System = std::make_shared(&pspFileSystem, g_Config.flash0Directory, FileSystemFlags::FLASH); -#else - auto flash0System = std::make_shared(&pspFileSystem, "flash0"); -#endif FileSystemFlags memstickFlags = FileSystemFlags::SIMULATE_FAT32 | FileSystemFlags::CARD; Path pspDir = GetSysDirectory(DIRECTORY_PSP); @@ -322,10 +316,13 @@ static void MountFileSystems() { pspFileSystem.Mount("fatms:", memstickSystem); pspFileSystem.Mount("pfat0:", memstickSystem); + // TODO: These should be made "lazy" mounts. + auto flash0System = std::make_shared(&pspFileSystem, g_Config.nandRootDirectory / "flash0", FileSystemFlags::FLASH); + auto flash1System = std::make_shared(&pspFileSystem, g_Config.nandRootDirectory / "flash1", FileSystemFlags::FLASH); pspFileSystem.Mount("flash0:", flash0System); + pspFileSystem.Mount("flash1:", flash1System); // NOTE: We don't handle the host0: mount here, it's in Load_PSP_ELF_PBP. - // Additionally, host0: is remapped to umd0: if there is an UMD inserted (old hack in MetaFileSystem). if (g_RemasterMode) { const std::string gameId = g_paramSFO.GetDiscID(); diff --git a/Core/Util/PathUtil.cpp b/Core/Util/PathUtil.cpp index 564e8c354f..7a0b8eacfc 100644 --- a/Core/Util/PathUtil.cpp +++ b/Core/Util/PathUtil.cpp @@ -112,6 +112,8 @@ Path GetSysDirectory(PSPDirectories directoryType) { return pspDirectory / "shaders"; case DIRECTORY_CUSTOM_THEMES: return pspDirectory / "themes"; + case DIRECTORY_NAND: + return pspDirectory / "NAND"; case DIRECTORY_MEMSTICK_ROOT: return g_Config.memStickDirectory; diff --git a/Core/Util/PathUtil.h b/Core/Util/PathUtil.h index c69ea2f7db..73e4b21264 100644 --- a/Core/Util/PathUtil.h +++ b/Core/Util/PathUtil.h @@ -11,6 +11,7 @@ enum PSPDirectories { DIRECTORY_CHEATS, DIRECTORY_SCREENSHOT, DIRECTORY_SYSTEM, + DIRECTORY_NAND, DIRECTORY_GAME, DIRECTORY_SAVEDATA, DIRECTORY_PAUTH, diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index d715605c28..048c1a2bd2 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -595,11 +595,6 @@ void NativeInit(int argc, const char *argv[], const CommandLineOptions &cmdLineO g_Config.defaultCurrentDirectory = Path(external_dir); } - // Might also add an option to move it to internal / non-visible storage, but there's - // little point, really. - - g_Config.flash0Directory = Path(external_dir) / "flash0"; - Path memstickDirFile = g_Config.internalDataDirectory / "memstick_dir.txt"; if (File::Exists(memstickDirFile)) { INFO_LOG(Log::System, "Reading '%s' to find memstick dir.", memstickDirFile.c_str()); @@ -650,13 +645,10 @@ void NativeInit(int argc, const char *argv[], const CommandLineOptions &cmdLineO #elif PPSSPP_PLATFORM(IOS) g_Config.defaultCurrentDirectory = g_Config.internalDataDirectory; g_Config.memStickDirectory = DarwinFileSystemServices::appropriateMemoryStickDirectoryToUse(); - g_Config.flash0Directory = Path(external_dir) / "flash0"; #elif PPSSPP_PLATFORM(MAC) g_Config.memStickDirectory = DarwinFileSystemServices::appropriateMemoryStickDirectoryToUse(); - g_Config.flash0Directory = Path(external_dir) / "flash0"; #elif PPSSPP_PLATFORM(SWITCH) g_Config.memStickDirectory = g_Config.internalDataDirectory / "config/ppsspp"; - g_Config.flash0Directory = g_Config.internalDataDirectory / "assets/flash0"; #elif PPSSPP_PLATFORM(WINDOWS) // ... #else @@ -669,7 +661,6 @@ void NativeInit(int argc, const char *argv[], const CommandLineOptions &cmdLineO config = "./config"; g_Config.memStickDirectory = Path(config) / "ppsspp"; - g_Config.flash0Directory = File::GetExeDirectory() / "assets/flash0"; if (getenv("HOME") != nullptr) { g_Config.defaultCurrentDirectory = Path(getenv("HOME")); } else { @@ -683,6 +674,9 @@ void NativeInit(int argc, const char *argv[], const CommandLineOptions &cmdLineO g_Config.currentDirectory = g_Config.defaultCurrentDirectory; } + // Mount a filesystem + g_Config.nandRootDirectory = GetSysDirectory(DIRECTORY_NAND); + if (cache_dir && strlen(cache_dir)) { g_Config.appCacheDirectory = Path(cache_dir); DiskCachingFileLoaderCache::SetCacheDir(g_Config.appCacheDirectory); @@ -702,7 +696,7 @@ void NativeInit(int argc, const char *argv[], const CommandLineOptions &cmdLineO boot_filename.clear(); if (boot_filename.empty() && cmdLineOptions.bootVSH.has_value() && cmdLineOptions.bootVSH.value()) { - boot_filename = g_Config.flash0Directory / "vsh/module/vshmain.prx"; + boot_filename = g_Config.nandRootDirectory / "flash0/vsh/module/vshmain.prx"; } if (cmdLineOptions.appendConfig.has_value()) { diff --git a/UWP/App.cpp b/UWP/App.cpp index 62135b6817..d1d553ed63 100644 --- a/UWP/App.cpp +++ b/UWP/App.cpp @@ -61,14 +61,14 @@ void App::InitialPPSSPP() { g_VFS.Register("", new DirectoryReader(exePath / "Content")); g_VFS.Register("", new DirectoryReader(exePath)); - // Mount a filesystem - g_Config.flash0Directory = exePath / "assets/flash0"; - // Prepare for initialization std::wstring internalDataFolderW = std::wstring(winrt::Windows::Storage::ApplicationData::Current().LocalFolder().Path()); g_Config.internalDataDirectory = Path(internalDataFolderW); g_Config.memStickDirectory = g_Config.internalDataDirectory; + // Mount a filesystem + g_Config.nandRootDirectory = GetSysDirectory(PSPDirectories::DIRECTORY_NAND); + // On Win32 it makes more sense to initialize the system directories here // because the next place it was called was in the EmuThread, and it's too late by then. CreateSysDirectories(); diff --git a/Windows/main.cpp b/Windows/main.cpp index f27468b19c..4828013d6d 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -927,12 +927,10 @@ std::vector GetWideCmdLine() { } static void InitMemstickDirectory() { - if (!g_Config.memStickDirectory.empty() && !g_Config.flash0Directory.empty()) + if (!g_Config.memStickDirectory.empty() && !g_Config.nandRootDirectory.empty()) return; const Path &exePath = File::GetExeDirectory(); - // Mount a filesystem - g_Config.flash0Directory = exePath / "assets/flash0"; // Caller sets this to the Documents folder. const Path rootMyDocsPath = g_Config.internalDataDirectory; diff --git a/headless/Headless.cpp b/headless/Headless.cpp index a33a6260d2..68e2068e8c 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -782,11 +782,11 @@ int main(int argc, const char* argv[]) { coreParameter.fastForward = true; Path exePath = File::GetExeDirectory(); - g_Config.flash0Directory = exePath / "assets/flash0"; // --memstick, applied by ApplyToConfig() further up, wins. This runs after it, so without the // check the default below would silently overwrite whatever was asked for. if (!cmdLineOptions.memStick.has_value()) { + // TODO: Share this derivation with the main build. #if PPSSPP_PLATFORM(WINDOWS) // Mount a filesystem g_Config.memStickDirectory = exePath / "memstick"; @@ -796,12 +796,14 @@ int main(int argc, const char* argv[]) { g_Config.memStickDirectory = Path(std::string(getenv("HOME"))) / ".ppsspp"; #endif } + g_Config.nandRootDirectory = GetSysDirectory(DIRECTORY_NAND); + coreParameter.nandRoot = g_Config.nandRootDirectory; - // Try to find the flash0 directory. Often this is from a subdirectory. + // Try to find the assets flash0 directory. Often this is from a subdirectory. + // This is needed for our fallback fonts. Path nextPath = exePath; for (int i = 0; i < 5; ++i) { if (File::Exists(nextPath / "assets/flash0")) { - g_Config.flash0Directory = nextPath / "assets/flash0"; #if !PPSSPP_PLATFORM(ANDROID) g_VFS.Register("", new DirectoryReader(nextPath / "assets")); #endif @@ -847,8 +849,9 @@ int main(int argc, const char* argv[]) { UpdateUIState(UISTATE_INGAME); if (cmdLineOptions.bootVSH.has_value() && cmdLineOptions.bootVSH.value()) { - AddToTestsByPath(&testFilenames, (g_Config.flash0Directory / "vsh/module/vshmain.prx").ToString()); + AddToTestsByPath(&testFilenames, (coreParameter.nandRoot / "flash0/vsh/module/vshmain.prx").ToString()); } + if (testFilenames.empty()) { return printUsage(cmdLineOptions, argv[0], argc <= 1 ? NULL : "No executables specified"); } diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index c55b2d4065..283b083953 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -1267,10 +1267,10 @@ void retro_init(void) g_Config.currentDirectory = retro_base_dir; g_Config.defaultCurrentDirectory = retro_base_dir; g_Config.memStickDirectory = retro_save_dir; - g_Config.flash0Directory = retro_base_dir / "flash0"; g_Config.internalDataDirectory = retro_base_dir; g_Config.bEnableNetworkChat = false; g_Config.bDiscordRichPresence = false; + g_Config.nandRootDirectory = GetSysDirectory(PSPDirectories::DIRECTORY_NAND); g_VFS.Register("", new DirectoryReader(retro_base_dir));