diff --git a/Core/FileSystems/MetaFileSystem.cpp b/Core/FileSystems/MetaFileSystem.cpp index 0cf66541e3..2a3ec02f7b 100644 --- a/Core/FileSystems/MetaFileSystem.cpp +++ b/Core/FileSystems/MetaFileSystem.cpp @@ -270,8 +270,7 @@ std::string MetaFileSystem::NormalizePrefix(std::string prefix) const { return prefix; } -void MetaFileSystem::Mount(std::string prefix, IFileSystem *system) -{ +void MetaFileSystem::Mount(std::string prefix, IFileSystem *system) { std::lock_guard guard(lock); MountPoint x; x.prefix = prefix; @@ -279,8 +278,7 @@ void MetaFileSystem::Mount(std::string prefix, IFileSystem *system) fileSystems.push_back(x); } -void MetaFileSystem::Unmount(std::string prefix, IFileSystem *system) -{ +void MetaFileSystem::Unmount(std::string prefix, IFileSystem *system) { std::lock_guard guard(lock); MountPoint x; x.prefix = prefix; @@ -288,10 +286,13 @@ void MetaFileSystem::Unmount(std::string prefix, IFileSystem *system) fileSystems.erase(std::remove(fileSystems.begin(), fileSystems.end(), x), fileSystems.end()); } -void MetaFileSystem::Remount(IFileSystem *oldSystem, IFileSystem *newSystem) { - for (auto it = fileSystems.begin(); it != fileSystems.end(); ++it) { - if (it->system == oldSystem) { - it->system = newSystem; +void MetaFileSystem::Remount(std::string prefix, IFileSystem *newSystem, bool delOldSystem) { + std::lock_guard guard(lock); + for (auto &it : fileSystems) { + if (it.prefix == prefix) { + if (delOldSystem) + delete it.system; + it.system = newSystem; } } } diff --git a/Core/FileSystems/MetaFileSystem.h b/Core/FileSystems/MetaFileSystem.h index cfc202b0d1..3fa2d16063 100644 --- a/Core/FileSystems/MetaFileSystem.h +++ b/Core/FileSystems/MetaFileSystem.h @@ -52,7 +52,7 @@ public: void Mount(std::string prefix, IFileSystem *system); void Unmount(std::string prefix, IFileSystem *system); - void Remount(IFileSystem *oldSystem, IFileSystem *newSystem); + void Remount(std::string prefix, IFileSystem *newSystem, bool delOldSystem = true); IFileSystem *GetSystem(const std::string &prefix); IFileSystem *GetSystemFromFilename(const std::string &filename); diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index bd4cb56d7b..2f61e739ec 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -425,7 +425,7 @@ static int sceUmdWaitDriveStatWithTimer(u32 stat, u32 timeout) DEBUG_LOG(SCEIO, "sceUmdWaitDriveStatWithTimer(stat = %08x, timeout = %d): waiting", stat, timeout); __UmdWaitStat(timeout); umdWaitingThreads.push_back(__KernelGetCurThread()); - __KernelWaitCurThread(WAITTYPE_UMD, 1, stat, 0, 0, "umd stat waited with timer"); + __KernelWaitCurThread(WAITTYPE_UMD, 1, stat, 0, false, "umd stat waited with timer"); return 0; } else { hleReSchedule("umd stat checked"); @@ -495,45 +495,15 @@ static u32 sceUmdGetErrorStat() } void __UmdReplace(std::string filepath) { - // TODO: This should really go through Loaders, no? What if it's an invalid file? + char *error = ""; + if (!UmdReplace(filepath, error)) + ERROR_LOG(SCEIO, "UMD Replace failed: %s", error); - // Only get system from disc0 seems have been enough. - IFileSystem* currentUMD = pspFileSystem.GetSystem("disc0:"); - IFileSystem* currentISOBlock = pspFileSystem.GetSystem("umd0:"); - if (!currentUMD) - return; - - FileLoader *loadedFile = ConstructFileLoader(filepath); - - IFileSystem* umd2; - if (!loadedFile->Exists()) { - delete loadedFile; - return; - } - UpdateLoadedFile(loadedFile); - - if (loadedFile->IsDirectory()) { - umd2 = new VirtualDiscFileSystem(&pspFileSystem, filepath); - } else { - auto bd = constructBlockDevice(loadedFile); - if (!bd) - return; - umd2 = new ISOFileSystem(&pspFileSystem, bd); - pspFileSystem.Remount(currentUMD, umd2); - - if (currentUMD != currentISOBlock) { - // We mounted an ISO block system separately. - IFileSystem *iso = new ISOBlockSystem(static_cast(umd2)); - pspFileSystem.Remount(currentISOBlock, iso); - delete currentISOBlock; - } - } - delete currentUMD; UMDInserted = false; CoreTiming::ScheduleEvent(usToCycles(200*1000), umdInsertChangeEvent, 0); // Wait sceUmdCheckMedium call // TODO Is this always correct if UMD was not activated? u32 notifyArg = PSP_UMD_PRESENT | PSP_UMD_READABLE | PSP_UMD_CHANGED; - if (driveCBId != -1) + if (driveCBId != 0) __KernelNotifyCallback(driveCBId, notifyArg); } diff --git a/Core/Loaders.cpp b/Core/Loaders.cpp index 14bc31973d..a07c7b8dd8 100644 --- a/Core/Loaders.cpp +++ b/Core/Loaders.cpp @@ -355,3 +355,37 @@ bool LoadFile(FileLoader **fileLoaderPtr, std::string *error_string) { coreState = CORE_ERROR; return false; } + +bool UmdReplace(std::string filepath, char *error) { + IFileSystem* currentUMD = pspFileSystem.GetSystem("disc0:"); + + if (!currentUMD) { + error = "has no disc"; + return false; + } + + FileLoader *loadedFile = ConstructFileLoader(filepath); + + if (!loadedFile->Exists()) { + delete loadedFile; + sprintf(error, "%s doesn't exist", loadedFile->Path().c_str()); + return false; + } + UpdateLoadedFile(loadedFile); + + loadedFile = ResolveFileLoaderTarget(loadedFile); + IdentifiedFileType type = Identify_File(loadedFile); + + switch (type) { + case IdentifiedFileType::PSP_ISO: + case IdentifiedFileType::PSP_ISO_NP: + case IdentifiedFileType::PSP_DISC_DIRECTORY: + ReInitMemoryForGameISO(loadedFile); + break; + default: + sprintf(error, "Unsupported file type: %i", type); + return false; + break; + } + return true; +} diff --git a/Core/Loaders.h b/Core/Loaders.h index 690376c73b..9d114b446d 100644 --- a/Core/Loaders.h +++ b/Core/Loaders.h @@ -158,3 +158,5 @@ void RegisterFileLoaderFactory(std::string name, std::unique_ptrIsDirectory()) { fileSystem = new VirtualDiscFileSystem(&pspFileSystem, fileLoader->Path()); blockSystem = fileSystem; @@ -144,6 +144,40 @@ void InitMemoryForGameISO(FileLoader *fileLoader) { } } +bool ReInitMemoryForGameISO(FileLoader *fileLoader) { + if (!fileLoader->Exists()) { + return false; + } + + IFileSystem *fileSystem = nullptr; + IFileSystem *blockSystem = nullptr; + + if (fileLoader->IsDirectory()) { + fileSystem = new VirtualDiscFileSystem(&pspFileSystem, fileLoader->Path()); + blockSystem = fileSystem; + } + else { + auto bd = constructBlockDevice(fileLoader); + if (!bd) + return false; + + ISOFileSystem *iso = new ISOFileSystem(&pspFileSystem, bd); + fileSystem = iso; + blockSystem = new ISOBlockSystem(iso); + } + + if (pspFileSystem.GetSystem("disc0:") != pspFileSystem.GetSystem("umd0:")) { + // We mounted an ISO block system separately. + pspFileSystem.Remount("umd0:", blockSystem, false); + pspFileSystem.Remount("umd1:", blockSystem, false); + pspFileSystem.Remount("umd:", blockSystem); + } + + pspFileSystem.Remount("disc0:", fileSystem); + + return true; +} + void InitMemoryForGamePBP(FileLoader *fileLoader) { if (!fileLoader->Exists()) { return; diff --git a/Core/PSPLoaders.h b/Core/PSPLoaders.h index f344008460..e9c089494e 100644 --- a/Core/PSPLoaders.h +++ b/Core/PSPLoaders.h @@ -25,5 +25,6 @@ bool Load_PSP_ISO(FileLoader *fileLoader, std::string *error_string); bool Load_PSP_ELF_PBP(FileLoader *fileLoader, std::string *error_string); bool Load_PSP_GE_Dump(FileLoader *fileLoader, std::string *error_string); void InitMemoryForGameISO(FileLoader *fileLoader); +bool ReInitMemoryForGameISO(FileLoader *fileLoader); void InitMemoryForGamePBP(FileLoader *fileLoader); void PSPLoaders_Shutdown();