From 3b39e9e068e344d24f403a178183297cf614d67d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 6 Mar 2023 14:23:56 +0100 Subject: [PATCH 1/6] Turn the VFS into a class, to be able to reuse it for other purposes. --- Common/Data/Format/IniFile.cpp | 2 +- Common/Data/Format/JSONReader.cpp | 2 +- Common/Data/Format/ZIMLoad.cpp | 2 +- Common/Data/Text/I18n.cpp | 2 +- Common/File/AndroidStorage.cpp | 2 + Common/File/VFS/VFS.cpp | 56 +++++++++++------------- Common/File/VFS/VFS.h | 30 +++++++++---- Common/GPU/OpenGL/GLSLProgram.cpp | 4 +- Common/Render/ManagedTexture.cpp | 2 +- Core/FileSystems/DirectoryFileSystem.cpp | 4 +- Core/Reporting.cpp | 2 +- Core/Util/PPGeDraw.cpp | 2 +- Core/WebServer.cpp | 2 +- GPU/Common/PostShader.cpp | 2 +- GPU/Common/PresentationCommon.cpp | 2 +- GPU/Vulkan/TextureCacheVulkan.cpp | 2 +- SDL/SDLJoystick.cpp | 4 +- UI/BackgroundAudio.cpp | 2 +- UI/GameInfoCache.cpp | 2 +- UI/MiscScreens.cpp | 2 +- UI/NativeApp.cpp | 24 +++++----- UI/Theme.cpp | 6 +-- UWP/PPSSPP_UWPMain.cpp | 5 ++- Windows/main.cpp | 6 +-- android/jni/app-android.cpp | 4 +- headless/Headless.cpp | 8 ++-- headless/SDLHeadlessHost.cpp | 6 +-- headless/WindowsHeadlessHost.cpp | 10 ++--- libretro/libretro.cpp | 4 +- 29 files changed, 106 insertions(+), 95 deletions(-) diff --git a/Common/Data/Format/IniFile.cpp b/Common/Data/Format/IniFile.cpp index 72aeee6f8..27f38e3c1 100644 --- a/Common/Data/Format/IniFile.cpp +++ b/Common/Data/Format/IniFile.cpp @@ -569,7 +569,7 @@ bool IniFile::Load(const Path &path) bool IniFile::LoadFromVFS(const std::string &filename) { size_t size; - uint8_t *data = VFSReadFile(filename.c_str(), &size); + uint8_t *data = g_VFS.ReadFile(filename.c_str(), &size); if (!data) return false; std::string str((const char*)data, size); diff --git a/Common/Data/Format/JSONReader.cpp b/Common/Data/Format/JSONReader.cpp index 9c2128e6e..b65381d98 100644 --- a/Common/Data/Format/JSONReader.cpp +++ b/Common/Data/Format/JSONReader.cpp @@ -8,7 +8,7 @@ namespace json { JsonReader::JsonReader(const std::string &filename) { size_t buf_size; - buffer_ = (char *)VFSReadFile(filename.c_str(), &buf_size); + buffer_ = (char *)g_VFS.ReadFile(filename.c_str(), &buf_size); if (buffer_) { parse(); } else { diff --git a/Common/Data/Format/ZIMLoad.cpp b/Common/Data/Format/ZIMLoad.cpp index 3fd759e92..9a145afbe 100644 --- a/Common/Data/Format/ZIMLoad.cpp +++ b/Common/Data/Format/ZIMLoad.cpp @@ -126,7 +126,7 @@ int LoadZIMPtr(const uint8_t *zim, size_t datasize, int *width, int *height, int int LoadZIM(const char *filename, int *width, int *height, int *format, uint8_t **image) { size_t size; - uint8_t *buffer = VFSReadFile(filename, &size); + uint8_t *buffer = g_VFS.ReadFile(filename, &size); if (!buffer) { ERROR_LOG(IO, "Couldn't read data for '%s'", filename); return 0; diff --git a/Common/Data/Text/I18n.cpp b/Common/Data/Text/I18n.cpp index 9c222da8b..ebcb95a90 100644 --- a/Common/Data/Text/I18n.cpp +++ b/Common/Data/Text/I18n.cpp @@ -73,7 +73,7 @@ Path I18NRepo::GetIniPath(const std::string &languageID) const { bool I18NRepo::IniExists(const std::string &languageID) const { File::FileInfo info; - if (!VFSGetFileInfo(GetIniPath(languageID).ToString().c_str(), &info)) + if (!g_VFS.GetFileInfo(GetIniPath(languageID).ToString().c_str(), &info)) return false; if (!info.exists) return false; diff --git a/Common/File/AndroidStorage.cpp b/Common/File/AndroidStorage.cpp index ec8248947..c4ddcc73c 100644 --- a/Common/File/AndroidStorage.cpp +++ b/Common/File/AndroidStorage.cpp @@ -1,3 +1,5 @@ +#include + #include "Common/File/AndroidStorage.h" #include "Common/StringUtils.h" #include "Common/Log.h" diff --git a/Common/File/VFS/VFS.cpp b/Common/File/VFS/VFS.cpp index cf347dcf4..3dc9c66a1 100644 --- a/Common/File/VFS/VFS.cpp +++ b/Common/File/VFS/VFS.cpp @@ -3,26 +3,20 @@ #include "Common/File/VFS/AssetReader.h" #include "Common/File/AndroidStorage.h" -struct VFSEntry { - const char *prefix; - AssetReader *reader; -}; +VFS g_VFS; -static VFSEntry entries[16]; -static int num_entries = 0; - -void VFSRegister(const char *prefix, AssetReader *reader) { - entries[num_entries].prefix = prefix; - entries[num_entries].reader = reader; +void VFS::Register(const char *prefix, AssetReader *reader) { + entries_[numEntries_].prefix = prefix; + entries_[numEntries_].reader = reader; DEBUG_LOG(IO, "Registered VFS for prefix %s: %s", prefix, reader->toString().c_str()); - num_entries++; + numEntries_++; } -void VFSShutdown() { - for (int i = 0; i < num_entries; i++) { - delete entries[i].reader; +void VFS::Clear() { + for (int i = 0; i < numEntries_; i++) { + delete entries_[i].reader; } - num_entries = 0; + numEntries_ = 0; } // TODO: Use Path more. @@ -38,7 +32,7 @@ static bool IsLocalAbsolutePath(const char *path) { } // The returned data should be free'd with delete[]. -uint8_t *VFSReadFile(const char *filename, size_t *size) { +uint8_t *VFS::ReadFile(const char *filename, size_t *size) { if (IsLocalAbsolutePath(filename)) { // Local path, not VFS. // INFO_LOG(IO, "Not a VFS path: %s . Reading local file.", filename); @@ -47,13 +41,13 @@ uint8_t *VFSReadFile(const char *filename, size_t *size) { int fn_len = (int)strlen(filename); bool fileSystemFound = false; - for (int i = 0; i < num_entries; i++) { - int prefix_len = (int)strlen(entries[i].prefix); + for (int i = 0; i < numEntries_; i++) { + int prefix_len = (int)strlen(entries_[i].prefix); if (prefix_len >= fn_len) continue; - if (0 == memcmp(filename, entries[i].prefix, prefix_len)) { + if (0 == memcmp(filename, entries_[i].prefix, prefix_len)) { fileSystemFound = true; // INFO_LOG(IO, "Prefix match: %s (%s) -> %s", entries[i].prefix, filename, filename + prefix_len); - uint8_t *data = entries[i].reader->ReadAsset(filename + prefix_len, size); + uint8_t *data = entries_[i].reader->ReadAsset(filename + prefix_len, size); if (data) return data; else @@ -67,7 +61,7 @@ uint8_t *VFSReadFile(const char *filename, size_t *size) { return 0; } -bool VFSGetFileListing(const char *path, std::vector *listing, const char *filter) { +bool VFS::GetFileListing(const char *path, std::vector *listing, const char *filter) { if (IsLocalAbsolutePath(path)) { // Local path, not VFS. // INFO_LOG(IO, "Not a VFS path: %s . Reading local directory.", path); @@ -77,12 +71,12 @@ bool VFSGetFileListing(const char *path, std::vector *listing, c int fn_len = (int)strlen(path); bool fileSystemFound = false; - for (int i = 0; i < num_entries; i++) { - int prefix_len = (int)strlen(entries[i].prefix); + for (int i = 0; i < numEntries_; i++) { + int prefix_len = (int)strlen(entries_[i].prefix); if (prefix_len >= fn_len) continue; - if (0 == memcmp(path, entries[i].prefix, prefix_len)) { + if (0 == memcmp(path, entries_[i].prefix, prefix_len)) { fileSystemFound = true; - if (entries[i].reader->GetFileListing(path + prefix_len, listing, filter)) { + if (entries_[i].reader->GetFileListing(path + prefix_len, listing, filter)) { return true; } } @@ -94,7 +88,7 @@ bool VFSGetFileListing(const char *path, std::vector *listing, c return false; } -bool VFSGetFileInfo(const char *path, File::FileInfo *info) { +bool VFS::GetFileInfo(const char *path, File::FileInfo *info) { if (IsLocalAbsolutePath(path)) { // Local path, not VFS. // INFO_LOG(IO, "Not a VFS path: %s . Getting local file info.", path); @@ -103,19 +97,19 @@ bool VFSGetFileInfo(const char *path, File::FileInfo *info) { bool fileSystemFound = false; int fn_len = (int)strlen(path); - for (int i = 0; i < num_entries; i++) { - int prefix_len = (int)strlen(entries[i].prefix); + for (int i = 0; i < numEntries_; i++) { + int prefix_len = (int)strlen(entries_[i].prefix); if (prefix_len >= fn_len) continue; - if (0 == memcmp(path, entries[i].prefix, prefix_len)) { + if (0 == memcmp(path, entries_[i].prefix, prefix_len)) { fileSystemFound = true; - if (entries[i].reader->GetFileInfo(path + prefix_len, info)) + if (entries_[i].reader->GetFileInfo(path + prefix_len, info)) return true; else continue; } } if (!fileSystemFound) { - ERROR_LOG(IO, "Missing filesystem for %s", path); + ERROR_LOG(IO, "Missing filesystem for '%s'", path); } // Otherwise, the file was just missing. No need to log. return false; } diff --git a/Common/File/VFS/VFS.h b/Common/File/VFS/VFS.h index 0f7e03c3f..baaeebf06 100644 --- a/Common/File/VFS/VFS.h +++ b/Common/File/VFS/VFS.h @@ -10,12 +10,26 @@ class AssetReader; -void VFSRegister(const char *prefix, AssetReader *reader); -void VFSShutdown(); +class VFS { +public: + void Register(const char *prefix, AssetReader *reader); + void Clear(); -// Use delete [] to release the returned memory. -// Always allocates an extra zero byte at the end, so that it -// can be used for text like shader sources. -uint8_t *VFSReadFile(const char *filename, size_t *size); -bool VFSGetFileListing(const char *path, std::vector *listing, const char *filter = 0); -bool VFSGetFileInfo(const char *filename, File::FileInfo *fileInfo); + // Use delete [] to release the returned memory. + // Always allocates an extra zero byte at the end, so that it + // can be used for text like shader sources. + uint8_t *ReadFile(const char *filename, size_t *size); + bool GetFileListing(const char *path, std::vector *listing, const char *filter = 0); + bool GetFileInfo(const char *filename, File::FileInfo *fileInfo); + +private: + struct VFSEntry { + const char *prefix; + AssetReader *reader; + }; + + VFSEntry entries_[16]; + int numEntries_ = 0; +}; + +extern VFS g_VFS; diff --git a/Common/GPU/OpenGL/GLSLProgram.cpp b/Common/GPU/OpenGL/GLSLProgram.cpp index 45b098d71..fc5698085 100644 --- a/Common/GPU/OpenGL/GLSLProgram.cpp +++ b/Common/GPU/OpenGL/GLSLProgram.cpp @@ -102,7 +102,7 @@ bool glsl_recompile(GLSLProgram *program, std::string *error_message) { if (!program->vshader_source && !vsh_src) { size_t sz; - vsh_src.reset((char *)VFSReadFile(program->vshader_filename, &sz)); + vsh_src.reset((char *)g_VFS.ReadFile(program->vshader_filename, &sz)); } if (!program->vshader_source && !vsh_src) { ERROR_LOG(G3D, "File missing: %s", program->vshader_filename); @@ -113,7 +113,7 @@ bool glsl_recompile(GLSLProgram *program, std::string *error_message) { } if (!program->fshader_source && !fsh_src) { size_t sz; - fsh_src.reset((char *)VFSReadFile(program->fshader_filename, &sz)); + fsh_src.reset((char *)g_VFS.ReadFile(program->fshader_filename, &sz)); } if (!program->fshader_source && !fsh_src) { ERROR_LOG(G3D, "File missing: %s", program->fshader_filename); diff --git a/Common/Render/ManagedTexture.cpp b/Common/Render/ManagedTexture.cpp index 771d4f8a9..dce43253c 100644 --- a/Common/Render/ManagedTexture.cpp +++ b/Common/Render/ManagedTexture.cpp @@ -148,7 +148,7 @@ bool ManagedTexture::LoadFromFileData(const uint8_t *data, size_t dataSize, Imag bool ManagedTexture::LoadFromFile(const std::string &filename, ImageFileType type, bool generateMips) { generateMips_ = generateMips; size_t fileSize; - uint8_t *buffer = VFSReadFile(filename.c_str(), &fileSize); + uint8_t *buffer = g_VFS.ReadFile(filename.c_str(), &fileSize); if (!buffer) { filename_.clear(); ERROR_LOG(IO, "Failed to read file '%s'", filename.c_str()); diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index 27abc9056..b4fc83345 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -980,7 +980,7 @@ int VFSFileSystem::OpenFile(std::string filename, FileAccess access, const char VERBOSE_LOG(FILESYS, "VFSFileSystem actually opening %s (%s)", fullNameC, filename.c_str()); size_t size; - u8 *data = VFSReadFile(fullNameC, &size); + u8 *data = g_VFS.ReadFile(fullNameC, &size); if (!data) { ERROR_LOG(FILESYS, "VFSFileSystem failed to open %s", filename.c_str()); return SCE_KERNEL_ERROR_ERRNO_FILE_NOT_FOUND; @@ -1001,7 +1001,7 @@ PSPFileInfo VFSFileSystem::GetFileInfo(std::string filename) { std::string fullName = GetLocalPath(filename); File::FileInfo fo; - if (VFSGetFileInfo(fullName.c_str(), &fo)) { + if (g_VFS.GetFileInfo(fullName.c_str(), &fo)) { x.exists = fo.exists; if (x.exists) { x.size = fo.size; diff --git a/Core/Reporting.cpp b/Core/Reporting.cpp index d85533d67..946285dfe 100644 --- a/Core/Reporting.cpp +++ b/Core/Reporting.cpp @@ -569,7 +569,7 @@ namespace Reporting return false; #else File::FileInfo fo; - if (!VFSGetFileInfo("flash0/font/jpn0.pgf", &fo)) + if (!g_VFS.GetFileInfo("flash0/font/jpn0.pgf", &fo)) return false; #endif diff --git a/Core/Util/PPGeDraw.cpp b/Core/Util/PPGeDraw.cpp index 525937a51..12dc1e86a 100644 --- a/Core/Util/PPGeDraw.cpp +++ b/Core/Util/PPGeDraw.cpp @@ -252,7 +252,7 @@ void __PPGeInit() { if (loadedZIM) { size_t atlas_data_size; if (!g_ppge_atlas.IsMetadataLoaded()) { - uint8_t *atlas_data = VFSReadFile("ppge_atlas.meta", &atlas_data_size); + uint8_t *atlas_data = g_VFS.ReadFile("ppge_atlas.meta", &atlas_data_size); if (atlas_data) g_ppge_atlas.Load(atlas_data, atlas_data_size); delete[] atlas_data; diff --git a/Core/WebServer.cpp b/Core/WebServer.cpp index 3de0fabc7..578482702 100644 --- a/Core/WebServer.cpp +++ b/Core/WebServer.cpp @@ -237,7 +237,7 @@ static bool ServeDebuggerFile(const http::Request &request) { return false; size_t size; - uint8_t *data = VFSReadFile(filename, &size); + uint8_t *data = g_VFS.ReadFile(filename, &size); if (!data) return false; diff --git a/GPU/Common/PostShader.cpp b/GPU/Common/PostShader.cpp index 831bc1bf8..ae03877d9 100644 --- a/GPU/Common/PostShader.cpp +++ b/GPU/Common/PostShader.cpp @@ -70,7 +70,7 @@ void LoadPostShaderInfo(Draw::DrawContext *draw, const std::vector &direct for (size_t d = 0; d < directories.size(); d++) { std::vector fileInfo; - VFSGetFileListing(directories[d].c_str(), &fileInfo, "ini:"); + g_VFS.GetFileListing(directories[d].c_str(), &fileInfo, "ini:"); if (fileInfo.empty()) { File::GetFilesInDir(directories[d], &fileInfo, "ini:"); diff --git a/GPU/Common/PresentationCommon.cpp b/GPU/Common/PresentationCommon.cpp index 3305e03b7..3da9c795f 100644 --- a/GPU/Common/PresentationCommon.cpp +++ b/GPU/Common/PresentationCommon.cpp @@ -212,7 +212,7 @@ void PresentationCommon::CalculatePostShaderUniforms(int bufferWidth, int buffer static std::string ReadShaderSrc(const Path &filename) { size_t sz = 0; - char *data = (char *)VFSReadFile(filename.c_str(), &sz); + char *data = (char *)g_VFS.ReadFile(filename.c_str(), &sz); if (!data) { return ""; } diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 108356cad..21cf13139 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -260,7 +260,7 @@ void TextureCacheVulkan::NotifyConfigChanged() { static std::string ReadShaderSrc(const Path &filename) { size_t sz = 0; - char *data = (char *)VFSReadFile(filename.c_str(), &sz); + char *data = (char *)g_VFS.ReadFile(filename.c_str(), &sz); if (!data) return std::string(); diff --git a/SDL/SDLJoystick.cpp b/SDL/SDLJoystick.cpp index 0a53ef80b..59906f4a3 100644 --- a/SDL/SDLJoystick.cpp +++ b/SDL/SDLJoystick.cpp @@ -29,7 +29,7 @@ SDLJoystick::SDLJoystick(bool init_SDL ) : registeredAsEventHandler(false) { cout << "loading control pad mappings from " << dbPath << ": "; size_t size; - u8 *mappingData = VFSReadFile(dbPath, &size); + u8 *mappingData = g_VFS.ReadFile(dbPath, &size); if (mappingData) { SDL_RWops *rw = SDL_RWFromConstMem(mappingData, size); // 1 to free the rw after use @@ -191,7 +191,7 @@ void SDLJoystick::ProcessInput(SDL_Event &event){ NativeAxis(axis); break; case SDL_CONTROLLERDEVICEREMOVED: - // for removal events, "which" is the instance ID for SDL_CONTROLLERDEVICEREMOVED + // for removal events, "which" is the instance ID for SDL_CONTROLLERDEVICEREMOVED for (auto it = controllers.begin(); it != controllers.end(); ++it) { if (SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(*it)) == event.cdevice.which) { SDL_GameControllerClose(*it); diff --git a/UI/BackgroundAudio.cpp b/UI/BackgroundAudio.cpp index ff83abcfc..e9f13a483 100644 --- a/UI/BackgroundAudio.cpp +++ b/UI/BackgroundAudio.cpp @@ -257,7 +257,7 @@ BackgroundAudio::~BackgroundAudio() { BackgroundAudio::Sample *BackgroundAudio::LoadSample(const std::string &path) { size_t bytes; - uint8_t *data = VFSReadFile(path.c_str(), &bytes); + uint8_t *data = g_VFS.ReadFile(path.c_str(), &bytes); if (!data) { return nullptr; } diff --git a/UI/GameInfoCache.cpp b/UI/GameInfoCache.cpp index c71e5e6fc..ceef80ced 100644 --- a/UI/GameInfoCache.cpp +++ b/UI/GameInfoCache.cpp @@ -314,7 +314,7 @@ static bool ReadFileToString(IFileSystem *fs, const char *filename, std::string static bool ReadVFSToString(const char *filename, std::string *contents, std::mutex *mtx) { size_t sz; - uint8_t *data = VFSReadFile(filename, &sz); + uint8_t *data = g_VFS.ReadFile(filename, &sz); if (data) { if (mtx) { std::lock_guard lock(*mtx); diff --git a/UI/MiscScreens.cpp b/UI/MiscScreens.cpp index 6887d5ecd..b9e93d7ab 100644 --- a/UI/MiscScreens.cpp +++ b/UI/MiscScreens.cpp @@ -590,7 +590,7 @@ NewLanguageScreen::NewLanguageScreen(const std::string &title) : ListPopupScreen auto &langValuesMapping = g_Config.GetLangValuesMapping(); std::vector tempLangs; - VFSGetFileListing("lang", &tempLangs, "ini"); + g_VFS.GetFileListing("lang", &tempLangs, "ini"); std::vector listing; int selected = -1; int counter = 0; diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index c89c7ec12..833f8fdd7 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -467,27 +467,27 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch // We want this to be FIRST. #if PPSSPP_PLATFORM(IOS) || PPSSPP_PLATFORM(MAC) // Packed assets are included in app - VFSRegister("", new DirectoryAssetReader(Path(external_dir))); + g_VFS.Register("", new DirectoryAssetReader(Path(external_dir))); #endif #if defined(ASSETS_DIR) - VFSRegister("", new DirectoryAssetReader(Path(ASSETS_DIR))); + g_VFS.Register("", new DirectoryAssetReader(Path(ASSETS_DIR))); #endif #if !defined(MOBILE_DEVICE) && !defined(_WIN32) && !PPSSPP_PLATFORM(SWITCH) - VFSRegister("", new DirectoryAssetReader(File::GetExeDirectory() / "assets")); - VFSRegister("", new DirectoryAssetReader(File::GetExeDirectory())); - VFSRegister("", new DirectoryAssetReader(Path("/usr/local/share/ppsspp/assets"))); - VFSRegister("", new DirectoryAssetReader(Path("/usr/local/share/games/ppsspp/assets"))); - VFSRegister("", new DirectoryAssetReader(Path("/usr/share/ppsspp/assets"))); - VFSRegister("", new DirectoryAssetReader(Path("/usr/share/games/ppsspp/assets"))); + g_VFS.Register("", new DirectoryAssetReader(File::GetExeDirectory() / "assets")); + g_VFS.Register("", new DirectoryAssetReader(File::GetExeDirectory())); + g_VFS.Register("", new DirectoryAssetReader(Path("/usr/local/share/ppsspp/assets"))); + g_VFS.Register("", new DirectoryAssetReader(Path("/usr/local/share/games/ppsspp/assets"))); + g_VFS.Register("", new DirectoryAssetReader(Path("/usr/share/ppsspp/assets"))); + g_VFS.Register("", new DirectoryAssetReader(Path("/usr/share/games/ppsspp/assets"))); #endif #if PPSSPP_PLATFORM(SWITCH) Path assetPath = Path(user_data_path) / "assets"; - VFSRegister("", new DirectoryAssetReader(assetPath)); + g_VFS.Register("", new DirectoryAssetReader(assetPath)); #else - VFSRegister("", new DirectoryAssetReader(Path("assets"))); + g_VFS.Register("", new DirectoryAssetReader(Path("assets"))); #endif - VFSRegister("", new DirectoryAssetReader(Path(savegame_dir))); + g_VFS.Register("", new DirectoryAssetReader(Path(savegame_dir))); #if (defined(MOBILE_DEVICE) || !defined(USING_QT_UI)) && !PPSSPP_PLATFORM(UWP) if (host == nullptr) { @@ -777,7 +777,7 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch } #elif defined(USING_QT_UI) size_t fontSize = 0; - uint8_t *fontData = VFSReadFile("Roboto-Condensed.ttf", &fontSize); + uint8_t *fontData = g_VFS.ReadFile("Roboto-Condensed.ttf", &fontSize); if (fontData) { int fontID = QFontDatabase::addApplicationFontFromData(QByteArray((const char *)fontData, fontSize)); delete [] fontData; diff --git a/UI/Theme.cpp b/UI/Theme.cpp index 59be83522..f733c37c7 100644 --- a/UI/Theme.cpp +++ b/UI/Theme.cpp @@ -84,7 +84,7 @@ static void LoadThemeInfo(const std::vector &directories) { for (size_t d = 0; d < directories.size(); d++) { std::vector fileInfo; - VFSGetFileListing(directories[d].c_str(), &fileInfo, "ini:"); + g_VFS.GetFileListing(directories[d].c_str(), &fileInfo, "ini:"); if (fileInfo.empty()) { File::GetFilesInDir(directories[d], &fileInfo, "ini:"); @@ -138,7 +138,7 @@ static void LoadThemeInfo(const std::vector &directories) { tmpPath = (path / tmpPath).ToString(); File::FileInfo tmpInfo; - if (VFSGetFileInfo((tmpPath+".meta").c_str(), &tmpInfo) && VFSGetFileInfo((tmpPath+".zim").c_str(), &tmpInfo)) { + if (g_VFS.GetFileInfo((tmpPath + ".meta").c_str(), &tmpInfo) && g_VFS.GetFileInfo((tmpPath + ".zim").c_str(), &tmpInfo)) { info.sUIAtlas = tmpPath; } } @@ -158,7 +158,7 @@ static UI::Style MakeStyle(uint32_t fg, uint32_t bg) { static void LoadAtlasMetadata(Atlas &metadata, const char *filename, bool required) { size_t atlas_data_size = 0; - const uint8_t *atlas_data = VFSReadFile(filename, &atlas_data_size); + const uint8_t *atlas_data = g_VFS.ReadFile(filename, &atlas_data_size); bool load_success = atlas_data != nullptr && metadata.Load(atlas_data, atlas_data_size); if (!load_success) { if (required) diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index 23d1801cf..c2995c871 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -76,8 +76,8 @@ PPSSPP_UWPMain::PPSSPP_UWPMain(App ^app, const std::shared_ptrGetDrawContext()->HandleEvent(Draw::Event::LOST_BACKBUFFER, 0, 0, nullptr); NativeShutdownGraphics(); NativeShutdown(); + g_VFS.Clear(); // Deregister device notification m_deviceResources->RegisterDeviceNotify(nullptr); diff --git a/Windows/main.cpp b/Windows/main.cpp index d14b654f9..0c313e72a 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -583,8 +583,8 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin #endif const Path &exePath = File::GetExeDirectory(); - VFSRegister("", new DirectoryAssetReader(exePath / "assets")); - VFSRegister("", new DirectoryAssetReader(exePath)); + g_VFS.Register("", new DirectoryAssetReader(exePath / "assets")); + g_VFS.Register("", new DirectoryAssetReader(exePath)); langRegion = GetDefaultLangRegion(); osName = GetWindowsVersion() + " " + GetWindowsSystemArchitecture(); @@ -796,7 +796,7 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin } } - VFSShutdown(); + g_VFS.Clear(); MainWindow::DestroyDebugWindows(); DialogManager::DestroyAll(); diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 42d46cae4..e09288ee8 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -695,7 +695,7 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init deviceType = jdeviceType; std::string apkPath = GetJavaString(env, japkpath); - VFSRegister("", new ZipAssetReader(apkPath.c_str(), "assets/")); + g_VFS.Register("", new ZipAssetReader(apkPath.c_str(), "assets/")); systemName = GetJavaString(env, jmodel); langRegion = GetJavaString(env, jlangRegion); @@ -907,7 +907,7 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_shutdown(JNIEnv *, jclass) { std::lock_guard guard(renderLock); inputBoxCallbacks.clear(); NativeShutdown(); - VFSShutdown(); + g_VFS.Clear(); } { diff --git a/headless/Headless.cpp b/headless/Headless.cpp index fa63a489e..1f3c54ed9 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -482,13 +482,13 @@ int main(int argc, const char* argv[]) #if PPSSPP_PLATFORM(ANDROID) // For some reason the debugger installs it with this name? if (File::Exists(Path("/data/app/org.ppsspp.ppsspp-2.apk"))) { - VFSRegister("", new ZipAssetReader("/data/app/org.ppsspp.ppsspp-2.apk", "assets/")); + g_VFS.Register("", new ZipAssetReader("/data/app/org.ppsspp.ppsspp-2.apk", "assets/")); } if (File::Exists(Path("/data/app/org.ppsspp.ppsspp.apk"))) { - VFSRegister("", new ZipAssetReader("/data/app/org.ppsspp.ppsspp.apk", "assets/")); + g_VFS.Register("", new ZipAssetReader("/data/app/org.ppsspp.ppsspp.apk", "assets/")); } #elif !PPSSPP_PLATFORM(WINDOWS) - VFSRegister("", new DirectoryAssetReader(g_Config.flash0Directory / "..")); + g_VFS.Register("", new DirectoryAssetReader(g_Config.flash0Directory / "..")); #endif UpdateUIState(UISTATE_INGAME); @@ -557,7 +557,7 @@ int main(int argc, const char* argv[]) host = nullptr; headlessHost = nullptr; - VFSShutdown(); + g_VFS.Clear(); LogManager::Shutdown(); delete printfLogger; diff --git a/headless/SDLHeadlessHost.cpp b/headless/SDLHeadlessHost.cpp index 9960b0136..0a25cbdb8 100644 --- a/headless/SDLHeadlessHost.cpp +++ b/headless/SDLHeadlessHost.cpp @@ -100,9 +100,9 @@ private: }; void SDLHeadlessHost::LoadNativeAssets() { - VFSRegister("", new DirectoryAssetReader(Path("assets"))); - VFSRegister("", new DirectoryAssetReader(Path(""))); - VFSRegister("", new DirectoryAssetReader(Path(".."))); + g_VFS.Register("", new DirectoryAssetReader(Path("assets"))); + g_VFS.Register("", new DirectoryAssetReader(Path(""))); + g_VFS.Register("", new DirectoryAssetReader(Path(".."))); } bool GLDummyGraphicsContext::InitFromRenderThread(std::string *errorMessage) { diff --git a/headless/WindowsHeadlessHost.cpp b/headless/WindowsHeadlessHost.cpp index 32624f000..7a9e744bb 100644 --- a/headless/WindowsHeadlessHost.cpp +++ b/headless/WindowsHeadlessHost.cpp @@ -68,11 +68,11 @@ HWND CreateHiddenWindow() { void WindowsHeadlessHost::LoadNativeAssets() { - VFSRegister("", new DirectoryAssetReader(Path("assets"))); - VFSRegister("", new DirectoryAssetReader(Path(""))); - VFSRegister("", new DirectoryAssetReader(Path(".."))); - VFSRegister("", new DirectoryAssetReader(Path("../Windows/assets"))); - VFSRegister("", new DirectoryAssetReader(Path("../Windows"))); + g_VFS.Register("", new DirectoryAssetReader(Path("assets"))); + g_VFS.Register("", new DirectoryAssetReader(Path(""))); + g_VFS.Register("", new DirectoryAssetReader(Path(".."))); + g_VFS.Register("", new DirectoryAssetReader(Path("../Windows/assets"))); + g_VFS.Register("", new DirectoryAssetReader(Path("../Windows"))); } void WindowsHeadlessHost::SendDebugOutput(const std::string &output) diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index a5909da4a..26a33e59f 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -1284,7 +1284,7 @@ void retro_init(void) g_Config.bEnableNetworkChat = false; g_Config.bDiscordPresence = false; - VFSRegister("", new DirectoryAssetReader(retro_base_dir)); + g_VFS.Register("", new DirectoryAssetReader(retro_base_dir)); host = new LibretroHost(); } @@ -1486,7 +1486,7 @@ void retro_unload_game(void) Libretro::EmuThreadStop(); PSP_Shutdown(); - VFSShutdown(); + g_VFS.Clear(); delete ctx; ctx = nullptr; From 76497941644ba4c04947de9f674dea603f6af6ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 6 Mar 2023 14:29:47 +0100 Subject: [PATCH 2/6] Remove some ifdefs --- Common/File/VFS/AssetReader.cpp | 16 +++++----------- Common/File/VFS/AssetReader.h | 21 ++++----------------- Common/File/VFS/VFS.h | 11 ++++++++++- 3 files changed, 19 insertions(+), 29 deletions(-) diff --git a/Common/File/VFS/AssetReader.cpp b/Common/File/VFS/AssetReader.cpp index 306cd0c5e..64116703b 100644 --- a/Common/File/VFS/AssetReader.cpp +++ b/Common/File/VFS/AssetReader.cpp @@ -3,15 +3,16 @@ #include #include -#ifdef __ANDROID__ +#ifdef SHARED_LIBZIP #include +#else +#include "ext/libzip/zip.h" #endif #include "Common/Common.h" #include "Common/Log.h" #include "Common/File/VFS/AssetReader.h" -#ifdef __ANDROID__ uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size) { // Figure out the file size first. struct zip_stat zstat; @@ -31,10 +32,6 @@ uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size) { return contents; } -#endif - -#ifdef __ANDROID__ - ZipAssetReader::ZipAssetReader(const char *zip_file, const char *in_zip_path) { zip_file_ = zip_open(zip_file, 0, NULL); strcpy(in_zip_path_, in_zip_path); @@ -155,9 +152,8 @@ void ZipAssetReader::GetZipListings(const char *path, std::set &fil bool ZipAssetReader::GetFileInfo(const char *path, File::FileInfo *info) { struct zip_stat zstat; char temp_path[1024]; - strcpy(temp_path, in_zip_path_); - strcat(temp_path, path); - if (0 != zip_stat(zip_file_, temp_path, ZIP_FL_NOCASE|ZIP_FL_UNCHANGED, &zstat)) { + snprintf(temp_path, sizeof(temp_path), "%s%s", in_zip_path_, path); + if (0 != zip_stat(zip_file_, temp_path, ZIP_FL_NOCASE | ZIP_FL_UNCHANGED, &zstat)) { // ZIP files do not have real directories, so we'll end up here if we // try to stat one. For now that's fine. info->exists = false; @@ -173,8 +169,6 @@ bool ZipAssetReader::GetFileInfo(const char *path, File::FileInfo *info) { return true; } -#endif - DirectoryAssetReader::DirectoryAssetReader(const Path &path) { path_ = path; } diff --git a/Common/File/VFS/AssetReader.h b/Common/File/VFS/AssetReader.h index 8352f8eea..b1ec62972 100644 --- a/Common/File/VFS/AssetReader.h +++ b/Common/File/VFS/AssetReader.h @@ -1,8 +1,9 @@ -// TODO: Move much of this code to vfs.cpp #pragma once -#ifdef __ANDROID__ +#ifdef SHARED_LIBZIP #include +#else +#include "ext/libzip/zip.h" #endif #include @@ -14,24 +15,11 @@ #include "Common/File/FileUtil.h" #include "Common/File/Path.h" -class AssetReader { -public: - virtual ~AssetReader() {} - // use delete[] - virtual uint8_t *ReadAsset(const char *path, size_t *size) = 0; - // Filter support is optional but nice to have - virtual bool GetFileListing(const char *path, std::vector *listing, const char *filter = 0) = 0; - virtual bool GetFileInfo(const char *path, File::FileInfo *info) = 0; - virtual std::string toString() const = 0; -}; - -#ifdef __ANDROID__ -uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size); class ZipAssetReader : public AssetReader { public: ZipAssetReader(const char *zip_file, const char *in_zip_path); ~ZipAssetReader(); - // use delete[] + // use delete[] on the returned value. uint8_t *ReadAsset(const char *path, size_t *size) override; bool GetFileListing(const char *path, std::vector *listing, const char *filter) override; bool GetFileInfo(const char *path, File::FileInfo *info) override; @@ -46,7 +34,6 @@ private: std::mutex lock_; char in_zip_path_[256]; }; -#endif class DirectoryAssetReader : public AssetReader { public: diff --git a/Common/File/VFS/VFS.h b/Common/File/VFS/VFS.h index baaeebf06..c6a2479e8 100644 --- a/Common/File/VFS/VFS.h +++ b/Common/File/VFS/VFS.h @@ -8,7 +8,16 @@ // read them manually out of the APK zipfile, while being able to run on other // platforms as well with the appropriate directory set-up. -class AssetReader; +class AssetReader { +public: + virtual ~AssetReader() {} + // use delete[] + virtual uint8_t *ReadAsset(const char *path, size_t *size) = 0; + // Filter support is optional but nice to have + virtual bool GetFileListing(const char *path, std::vector *listing, const char *filter = 0) = 0; + virtual bool GetFileInfo(const char *path, File::FileInfo *info) = 0; + virtual std::string toString() const = 0; +}; class VFS { public: From 54af2400135e8fef2639ecbc09a2cf1d2ea401b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 6 Mar 2023 14:37:11 +0100 Subject: [PATCH 3/6] Use a vector internally in VFS. --- Common/File/DirListing.h | 4 +--- Common/File/VFS/VFS.cpp | 34 ++++++++++++++++------------------ Common/File/VFS/VFS.h | 16 +++++++++++----- 3 files changed, 28 insertions(+), 26 deletions(-) diff --git a/Common/File/DirListing.h b/Common/File/DirListing.h index c53d42058..4ad9ce0c3 100644 --- a/Common/File/DirListing.h +++ b/Common/File/DirListing.h @@ -2,10 +2,8 @@ #include #include - #include - -#include +#include #include "Common/File/Path.h" diff --git a/Common/File/VFS/VFS.cpp b/Common/File/VFS/VFS.cpp index 3dc9c66a1..e765c9ca7 100644 --- a/Common/File/VFS/VFS.cpp +++ b/Common/File/VFS/VFS.cpp @@ -6,17 +6,15 @@ VFS g_VFS; void VFS::Register(const char *prefix, AssetReader *reader) { - entries_[numEntries_].prefix = prefix; - entries_[numEntries_].reader = reader; + entries_.push_back(VFSEntry{ prefix, reader }); DEBUG_LOG(IO, "Registered VFS for prefix %s: %s", prefix, reader->toString().c_str()); - numEntries_++; } void VFS::Clear() { - for (int i = 0; i < numEntries_; i++) { - delete entries_[i].reader; + for (auto &entry : entries_) { + delete entry.reader; } - numEntries_ = 0; + entries_.clear(); } // TODO: Use Path more. @@ -41,13 +39,13 @@ uint8_t *VFS::ReadFile(const char *filename, size_t *size) { int fn_len = (int)strlen(filename); bool fileSystemFound = false; - for (int i = 0; i < numEntries_; i++) { - int prefix_len = (int)strlen(entries_[i].prefix); + for (const auto &entry : entries_) { + int prefix_len = (int)strlen(entry.prefix); if (prefix_len >= fn_len) continue; - if (0 == memcmp(filename, entries_[i].prefix, prefix_len)) { + if (0 == memcmp(filename, entry.prefix, prefix_len)) { fileSystemFound = true; // INFO_LOG(IO, "Prefix match: %s (%s) -> %s", entries[i].prefix, filename, filename + prefix_len); - uint8_t *data = entries_[i].reader->ReadAsset(filename + prefix_len, size); + uint8_t *data = entry.reader->ReadAsset(filename + prefix_len, size); if (data) return data; else @@ -71,12 +69,12 @@ bool VFS::GetFileListing(const char *path, std::vector *listing, int fn_len = (int)strlen(path); bool fileSystemFound = false; - for (int i = 0; i < numEntries_; i++) { - int prefix_len = (int)strlen(entries_[i].prefix); + for (const auto &entry : entries_) { + int prefix_len = (int)strlen(entry.prefix); if (prefix_len >= fn_len) continue; - if (0 == memcmp(path, entries_[i].prefix, prefix_len)) { + if (0 == memcmp(path, entry.prefix, prefix_len)) { fileSystemFound = true; - if (entries_[i].reader->GetFileListing(path + prefix_len, listing, filter)) { + if (entry.reader->GetFileListing(path + prefix_len, listing, filter)) { return true; } } @@ -97,12 +95,12 @@ bool VFS::GetFileInfo(const char *path, File::FileInfo *info) { bool fileSystemFound = false; int fn_len = (int)strlen(path); - for (int i = 0; i < numEntries_; i++) { - int prefix_len = (int)strlen(entries_[i].prefix); + for (const auto &entry : entries_) { + int prefix_len = (int)strlen(entry.prefix); if (prefix_len >= fn_len) continue; - if (0 == memcmp(path, entries_[i].prefix, prefix_len)) { + if (0 == memcmp(path, entry.prefix, prefix_len)) { fileSystemFound = true; - if (entries_[i].reader->GetFileInfo(path + prefix_len, info)) + if (entry.reader->GetFileInfo(path + prefix_len, info)) return true; else continue; diff --git a/Common/File/VFS/VFS.h b/Common/File/VFS/VFS.h index c6a2479e8..41ac6ae3f 100644 --- a/Common/File/VFS/VFS.h +++ b/Common/File/VFS/VFS.h @@ -1,18 +1,25 @@ #pragma once #include +#include #include "Common/File/DirListing.h" -// Basic virtual file system. Used to manage assets on Android, where we have to +// Basic read-only virtual file system. Used to manage assets on Android, where we have to // read them manually out of the APK zipfile, while being able to run on other // platforms as well with the appropriate directory set-up. +// Note that this is kinda similar in concept to Core/MetaFileSystem.h, but that one +// is specifically for operations done by the emulated PSP, while this is for operations +// on the system level, like loading assets, and maybe texture packs. Also, as mentioned, +// this one is read-only, so a bit smaller and simpler. + class AssetReader { public: virtual ~AssetReader() {} - // use delete[] + // use delete[] to release the returned memory. virtual uint8_t *ReadAsset(const char *path, size_t *size) = 0; + // Filter support is optional but nice to have virtual bool GetFileListing(const char *path, std::vector *listing, const char *filter = 0) = 0; virtual bool GetFileInfo(const char *path, File::FileInfo *info) = 0; @@ -21,6 +28,7 @@ public: class VFS { public: + ~VFS() { Clear(); } void Register(const char *prefix, AssetReader *reader); void Clear(); @@ -36,9 +44,7 @@ private: const char *prefix; AssetReader *reader; }; - - VFSEntry entries_[16]; - int numEntries_ = 0; + std::vector entries_; }; extern VFS g_VFS; From 53172eff6376481ab03f58b42b6dda57c294bdf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 6 Mar 2023 15:30:39 +0100 Subject: [PATCH 4/6] Renaming and file splitting --- CMakeLists.txt | 8 ++- Common/Common.vcxproj | 6 +- Common/Common.vcxproj.filters | 18 ++++-- Common/File/VFS/DirectoryReader.cpp | 31 ++++++++++ Common/File/VFS/DirectoryReader.h | 21 +++++++ Common/File/VFS/VFS.cpp | 8 ++- Common/File/VFS/VFS.h | 10 ++-- .../{AssetReader.cpp => ZipFileReader.cpp} | 57 +++++-------------- .../VFS/{AssetReader.h => ZipFileReader.h} | 25 ++------ Qt/QtMain.h | 3 +- UI/NativeApp.cpp | 25 ++++---- UWP/CommonUWP/CommonUWP.vcxproj | 6 +- UWP/CommonUWP/CommonUWP.vcxproj.filters | 10 +++- UWP/PPSSPP_UWPMain.cpp | 6 +- Windows/main.cpp | 6 +- android/jni/Android.mk | 3 +- android/jni/app-android.cpp | 5 +- headless/Headless.cpp | 11 ++-- headless/SDLHeadlessHost.cpp | 8 +-- headless/WindowsHeadlessHost.cpp | 12 ++-- ios/PPSSPPUIApplication.mm | 12 ++-- libretro/Makefile.common | 5 +- libretro/libretro.cpp | 12 ++-- 23 files changed, 169 insertions(+), 139 deletions(-) create mode 100644 Common/File/VFS/DirectoryReader.cpp create mode 100644 Common/File/VFS/DirectoryReader.h rename Common/File/VFS/{AssetReader.cpp => ZipFileReader.cpp} (70%) rename Common/File/VFS/{AssetReader.h => ZipFileReader.h} (51%) diff --git a/CMakeLists.txt b/CMakeLists.txt index ebd1b151c..91f08e233 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -588,8 +588,10 @@ add_library(Common STATIC Common/Data/Random/Rng.h Common/File/VFS/VFS.h Common/File/VFS/VFS.cpp - Common/File/VFS/AssetReader.cpp - Common/File/VFS/AssetReader.h + Common/File/VFS/ZipFileReader.cpp + Common/File/VFS/ZipFileReader.h + Common/File/VFS/DirectoryReader.cpp + Common/File/VFS/DirectoryReader.h Common/File/AndroidStorage.h Common/File/AndroidStorage.cpp Common/File/DiskFree.h @@ -1150,7 +1152,7 @@ elseif(IOS AND NOT LIBRETRO) UI/DarwinFileSystemServices.h Common/Battery/AppleBatteryClient.m ) - + set(nativeExtraLibs ${nativeExtraLibs} "-framework Foundation -framework MediaPlayer -framework AudioToolbox -framework CoreGraphics -framework QuartzCore -framework UIKit -framework GLKit -framework OpenAL -framework AVFoundation -framework CoreLocation -framework CoreVideo -framework CoreMedia -framework CoreServices" ) if(EXISTS "${CMAKE_IOS_SDK_ROOT}/System/Library/Frameworks/GameController.framework") set(nativeExtraLibs ${nativeExtraLibs} "-weak_framework GameController") diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj index 451e8dd42..8557f133d 100644 --- a/Common/Common.vcxproj +++ b/Common/Common.vcxproj @@ -425,8 +425,9 @@ + - + @@ -861,8 +862,9 @@ + - + diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters index 3c0a310af..0f4009315 100644 --- a/Common/Common.vcxproj.filters +++ b/Common/Common.vcxproj.filters @@ -176,9 +176,6 @@ File\VFS - - File\VFS - Data\Format @@ -467,6 +464,12 @@ GPU\OpenGL + + File\VFS + + + File\VFS + @@ -628,9 +631,6 @@ File\VFS - - File\VFS - Data\Format @@ -884,6 +884,12 @@ GPU\OpenGL + + File\VFS + + + File\VFS + diff --git a/Common/File/VFS/DirectoryReader.cpp b/Common/File/VFS/DirectoryReader.cpp new file mode 100644 index 000000000..d979dd4d7 --- /dev/null +++ b/Common/File/VFS/DirectoryReader.cpp @@ -0,0 +1,31 @@ +#include "Common/Common.h" +#include "Common/Log.h" +#include "Common/File/VFS/DirectoryReader.h" + +DirectoryReader::DirectoryReader(const Path &path) { + path_ = path; +} + +uint8_t *DirectoryReader::ReadFile(const char *path, size_t *size) { + Path new_path = Path(path).StartsWith(path_) ? Path(path) : path_ / path; + return File::ReadLocalFile(new_path, size); +} + +bool DirectoryReader::GetFileListing(const char *path, std::vector *listing, const char *filter = nullptr) { + Path new_path = Path(path).StartsWith(path_) ? Path(path) : path_ / path; + + File::FileInfo info; + if (!File::GetFileInfo(new_path, &info)) + return false; + + if (info.isDirectory) { + File::GetFilesInDir(new_path, listing, filter); + return true; + } + return false; +} + +bool DirectoryReader::GetFileInfo(const char *path, File::FileInfo *info) { + Path new_path = Path(path).StartsWith(path_) ? Path(path) : path_ / path; + return File::GetFileInfo(new_path, info); +} diff --git a/Common/File/VFS/DirectoryReader.h b/Common/File/VFS/DirectoryReader.h new file mode 100644 index 000000000..facd3efe7 --- /dev/null +++ b/Common/File/VFS/DirectoryReader.h @@ -0,0 +1,21 @@ +#pragma once + +#include "Common/File/VFS/VFS.h" +#include "Common/File/FileUtil.h" +#include "Common/File/Path.h" + +class DirectoryReader : public VFSBackend { +public: + explicit DirectoryReader(const Path &path); + // use delete[] on the returned value. + uint8_t *ReadFile(const char *path, size_t *size) override; + bool GetFileListing(const char *path, std::vector *listing, const char *filter) override; + bool GetFileInfo(const char *path, File::FileInfo *info) override; + std::string toString() const override { + return path_.ToString(); + } + +private: + Path path_; +}; + diff --git a/Common/File/VFS/VFS.cpp b/Common/File/VFS/VFS.cpp index e765c9ca7..634f53baa 100644 --- a/Common/File/VFS/VFS.cpp +++ b/Common/File/VFS/VFS.cpp @@ -1,11 +1,13 @@ +#include + #include "Common/Log.h" #include "Common/File/VFS/VFS.h" -#include "Common/File/VFS/AssetReader.h" +#include "Common/File/FileUtil.h" #include "Common/File/AndroidStorage.h" VFS g_VFS; -void VFS::Register(const char *prefix, AssetReader *reader) { +void VFS::Register(const char *prefix, VFSBackend *reader) { entries_.push_back(VFSEntry{ prefix, reader }); DEBUG_LOG(IO, "Registered VFS for prefix %s: %s", prefix, reader->toString().c_str()); } @@ -45,7 +47,7 @@ uint8_t *VFS::ReadFile(const char *filename, size_t *size) { if (0 == memcmp(filename, entry.prefix, prefix_len)) { fileSystemFound = true; // INFO_LOG(IO, "Prefix match: %s (%s) -> %s", entries[i].prefix, filename, filename + prefix_len); - uint8_t *data = entry.reader->ReadAsset(filename + prefix_len, size); + uint8_t *data = entry.reader->ReadFile(filename + prefix_len, size); if (data) return data; else diff --git a/Common/File/VFS/VFS.h b/Common/File/VFS/VFS.h index 41ac6ae3f..bd6cc6f3f 100644 --- a/Common/File/VFS/VFS.h +++ b/Common/File/VFS/VFS.h @@ -14,11 +14,11 @@ // on the system level, like loading assets, and maybe texture packs. Also, as mentioned, // this one is read-only, so a bit smaller and simpler. -class AssetReader { +class VFSBackend { public: - virtual ~AssetReader() {} + virtual ~VFSBackend() {} // use delete[] to release the returned memory. - virtual uint8_t *ReadAsset(const char *path, size_t *size) = 0; + virtual uint8_t *ReadFile(const char *path, size_t *size) = 0; // Filter support is optional but nice to have virtual bool GetFileListing(const char *path, std::vector *listing, const char *filter = 0) = 0; @@ -29,7 +29,7 @@ public: class VFS { public: ~VFS() { Clear(); } - void Register(const char *prefix, AssetReader *reader); + void Register(const char *prefix, VFSBackend *reader); void Clear(); // Use delete [] to release the returned memory. @@ -42,7 +42,7 @@ public: private: struct VFSEntry { const char *prefix; - AssetReader *reader; + VFSBackend *reader; }; std::vector entries_; }; diff --git a/Common/File/VFS/AssetReader.cpp b/Common/File/VFS/ZipFileReader.cpp similarity index 70% rename from Common/File/VFS/AssetReader.cpp rename to Common/File/VFS/ZipFileReader.cpp index 64116703b..f058deb48 100644 --- a/Common/File/VFS/AssetReader.cpp +++ b/Common/File/VFS/ZipFileReader.cpp @@ -1,7 +1,8 @@ #include #include #include -#include +#include +#include #ifdef SHARED_LIBZIP #include @@ -11,9 +12,9 @@ #include "Common/Common.h" #include "Common/Log.h" -#include "Common/File/VFS/AssetReader.h" +#include "Common/File/VFS/ZipFileReader.h" -uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size) { +static uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size) { // Figure out the file size first. struct zip_stat zstat; zip_file *file = zip_fopen(archive, filename, ZIP_FL_NOCASE|ZIP_FL_UNCHANGED); @@ -32,7 +33,7 @@ uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size) { return contents; } -ZipAssetReader::ZipAssetReader(const char *zip_file, const char *in_zip_path) { +ZipFileReader::ZipFileReader(const char *zip_file, const char *in_zip_path) { zip_file_ = zip_open(zip_file, 0, NULL); strcpy(in_zip_path_, in_zip_path); if (!zip_file_) { @@ -50,24 +51,22 @@ ZipAssetReader::ZipAssetReader(const char *zip_file, const char *in_zip_path) { } } -ZipAssetReader::~ZipAssetReader() { +ZipFileReader::~ZipFileReader() { std::lock_guard guard(lock_); zip_close(zip_file_); } -uint8_t *ZipAssetReader::ReadAsset(const char *path, size_t *size) { - char temp_path[1024]; - strcpy(temp_path, in_zip_path_); - strcat(temp_path, path); +uint8_t *ZipFileReader::ReadFile(const char *path, size_t *size) { + char temp_path[2048]; + snprintf(temp_path, sizeof(temp_path), "%s%s", in_zip_path_, path); std::lock_guard guard(lock_); return ReadFromZip(zip_file_, temp_path, size); } -bool ZipAssetReader::GetFileListing(const char *orig_path, std::vector *listing, const char *filter = 0) { - char path[1024]; - strcpy(path, in_zip_path_); - strcat(path, orig_path); +bool ZipFileReader::GetFileListing(const char *orig_path, std::vector *listing, const char *filter = 0) { + char path[2048]; + snprintf(path, sizeof(path), "%s%s", in_zip_path_, orig_path); std::set filters; std::string tmp; @@ -123,7 +122,7 @@ bool ZipAssetReader::GetFileListing(const char *orig_path, std::vector &files, std::set &directories) { +void ZipFileReader::GetZipListings(const char *path, std::set &files, std::set &directories) { size_t pathlen = strlen(path); if (path[pathlen - 1] == '/') pathlen--; @@ -149,7 +148,7 @@ void ZipAssetReader::GetZipListings(const char *path, std::set &fil } } -bool ZipAssetReader::GetFileInfo(const char *path, File::FileInfo *info) { +bool ZipFileReader::GetFileInfo(const char *path, File::FileInfo *info) { struct zip_stat zstat; char temp_path[1024]; snprintf(temp_path, sizeof(temp_path), "%s%s", in_zip_path_, path); @@ -168,31 +167,3 @@ bool ZipAssetReader::GetFileInfo(const char *path, File::FileInfo *info) { info->size = zstat.size; return true; } - -DirectoryAssetReader::DirectoryAssetReader(const Path &path) { - path_ = path; -} - -uint8_t *DirectoryAssetReader::ReadAsset(const char *path, size_t *size) { - Path new_path = Path(path).StartsWith(path_) ? Path(path) : path_ / path; - return File::ReadLocalFile(new_path, size); -} - -bool DirectoryAssetReader::GetFileListing(const char *path, std::vector *listing, const char *filter = nullptr) { - Path new_path = Path(path).StartsWith(path_) ? Path(path) : path_ / path; - - File::FileInfo info; - if (!File::GetFileInfo(new_path, &info)) - return false; - - if (info.isDirectory) { - File::GetFilesInDir(new_path, listing, filter); - return true; - } - return false; -} - -bool DirectoryAssetReader::GetFileInfo(const char *path, File::FileInfo *info) { - Path new_path = Path(path).StartsWith(path_) ? Path(path) : path_ / path; - return File::GetFileInfo(new_path, info); -} diff --git a/Common/File/VFS/AssetReader.h b/Common/File/VFS/ZipFileReader.h similarity index 51% rename from Common/File/VFS/AssetReader.h rename to Common/File/VFS/ZipFileReader.h index b1ec62972..0480d9673 100644 --- a/Common/File/VFS/AssetReader.h +++ b/Common/File/VFS/ZipFileReader.h @@ -8,19 +8,18 @@ #include #include -#include #include #include "Common/File/VFS/VFS.h" #include "Common/File/FileUtil.h" #include "Common/File/Path.h" -class ZipAssetReader : public AssetReader { +class ZipFileReader : public VFSBackend { public: - ZipAssetReader(const char *zip_file, const char *in_zip_path); - ~ZipAssetReader(); + ZipFileReader(const char *zip_file, const char *in_zip_path); + ~ZipFileReader(); // use delete[] on the returned value. - uint8_t *ReadAsset(const char *path, size_t *size) override; + uint8_t *ReadFile(const char *path, size_t *size) override; bool GetFileListing(const char *path, std::vector *listing, const char *filter) override; bool GetFileInfo(const char *path, File::FileInfo *info) override; std::string toString() const override { @@ -34,19 +33,3 @@ private: std::mutex lock_; char in_zip_path_[256]; }; - -class DirectoryAssetReader : public AssetReader { -public: - explicit DirectoryAssetReader(const Path &path); - // use delete[] - uint8_t *ReadAsset(const char *path, size_t *size) override; - bool GetFileListing(const char *path, std::vector *listing, const char *filter) override; - bool GetFileInfo(const char *path, File::FileInfo *info) override; - std::string toString() const override { - return path_.ToString(); - } - -private: - Path path_; -}; - diff --git a/Qt/QtMain.h b/Qt/QtMain.h index 0177ca929..639806bcf 100644 --- a/Qt/QtMain.h +++ b/Qt/QtMain.h @@ -25,7 +25,7 @@ QTM_USE_NAMESPACE #include "Common/System/Display.h" #include "Common/TimeUtil.h" #include "Common/File/VFS/VFS.h" -#include "Common/File/VFS/AssetReader.h" +#include "Common/File/VFS/DirectoryReader.h" #include "Common/GPU/OpenGL/GLCommon.h" #include "Common/GPU/OpenGL/GLFeatures.h" #include "Common/Input/InputState.h" @@ -191,4 +191,3 @@ private: #endif //SDL #endif - diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 833f8fdd7..e482eca11 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -67,7 +67,8 @@ #include "Common/Profiler/Profiler.h" #include "Common/Data/Encoding/Utf8.h" #include "Common/File/VFS/VFS.h" -#include "Common/File/VFS/AssetReader.h" +#include "Common/File/VFS/ZipFileReader.h" +#include "Common/File/VFS/DirectoryReader.h" #include "Common/CPUDetect.h" #include "Common/File/FileUtil.h" #include "Common/TimeUtil.h" @@ -467,27 +468,27 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch // We want this to be FIRST. #if PPSSPP_PLATFORM(IOS) || PPSSPP_PLATFORM(MAC) // Packed assets are included in app - g_VFS.Register("", new DirectoryAssetReader(Path(external_dir))); + g_VFS.Register("", new DirectoryReader(Path(external_dir))); #endif #if defined(ASSETS_DIR) - g_VFS.Register("", new DirectoryAssetReader(Path(ASSETS_DIR))); + g_VFS.Register("", new DirectoryReader(Path(ASSETS_DIR))); #endif #if !defined(MOBILE_DEVICE) && !defined(_WIN32) && !PPSSPP_PLATFORM(SWITCH) - g_VFS.Register("", new DirectoryAssetReader(File::GetExeDirectory() / "assets")); - g_VFS.Register("", new DirectoryAssetReader(File::GetExeDirectory())); - g_VFS.Register("", new DirectoryAssetReader(Path("/usr/local/share/ppsspp/assets"))); - g_VFS.Register("", new DirectoryAssetReader(Path("/usr/local/share/games/ppsspp/assets"))); - g_VFS.Register("", new DirectoryAssetReader(Path("/usr/share/ppsspp/assets"))); - g_VFS.Register("", new DirectoryAssetReader(Path("/usr/share/games/ppsspp/assets"))); + g_VFS.Register("", new DirectoryReader(File::GetExeDirectory() / "assets")); + g_VFS.Register("", new DirectoryReader(File::GetExeDirectory())); + g_VFS.Register("", new DirectoryReader(Path("/usr/local/share/ppsspp/assets"))); + g_VFS.Register("", new DirectoryReader(Path("/usr/local/share/games/ppsspp/assets"))); + g_VFS.Register("", new DirectoryReader(Path("/usr/share/ppsspp/assets"))); + g_VFS.Register("", new DirectoryReader(Path("/usr/share/games/ppsspp/assets"))); #endif #if PPSSPP_PLATFORM(SWITCH) Path assetPath = Path(user_data_path) / "assets"; - g_VFS.Register("", new DirectoryAssetReader(assetPath)); + g_VFS.Register("", new DirectoryReader(assetPath)); #else - g_VFS.Register("", new DirectoryAssetReader(Path("assets"))); + g_VFS.Register("", new DirectoryReader(Path("assets"))); #endif - g_VFS.Register("", new DirectoryAssetReader(Path(savegame_dir))); + g_VFS.Register("", new DirectoryReader(Path(savegame_dir))); #if (defined(MOBILE_DEVICE) || !defined(USING_QT_UI)) && !PPSSPP_PLATFORM(UWP) if (host == nullptr) { diff --git a/UWP/CommonUWP/CommonUWP.vcxproj b/UWP/CommonUWP/CommonUWP.vcxproj index a0747fc3e..6160d923d 100644 --- a/UWP/CommonUWP/CommonUWP.vcxproj +++ b/UWP/CommonUWP/CommonUWP.vcxproj @@ -306,7 +306,8 @@ - + + @@ -443,7 +444,8 @@ - + + diff --git a/UWP/CommonUWP/CommonUWP.vcxproj.filters b/UWP/CommonUWP/CommonUWP.vcxproj.filters index f8e867943..40b8f80da 100644 --- a/UWP/CommonUWP/CommonUWP.vcxproj.filters +++ b/UWP/CommonUWP/CommonUWP.vcxproj.filters @@ -252,7 +252,10 @@ Data\Format - + + File\VFS + + File\VFS @@ -589,7 +592,10 @@ Data\Format - + + File\VFS + + File\VFS diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index c2995c871..5fabe3a4e 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -11,7 +11,7 @@ #include "Common/Common.h" #include "Common/Input/InputState.h" #include "Common/File/VFS/VFS.h" -#include "Common/File/VFS/AssetReader.h" +#include "Common/File/VFS/DirectoryReader.h" #include "Common/Thread/ThreadUtil.h" #include "Common/Data/Encoding/Utf8.h" #include "Common/DirectXHelper.h" @@ -76,8 +76,8 @@ PPSSPP_UWPMain::PPSSPP_UWPMain(App ^app, const std::shared_ptr Date: Mon, 6 Mar 2023 16:34:52 +0100 Subject: [PATCH 5/6] VFS: Add support for opening zip files through a Content URI --- Common/File/VFS/ZipFileReader.cpp | 35 ++++++++++++++----------------- Common/File/VFS/ZipFileReader.h | 6 +++--- android/jni/app-android.cpp | 4 ++-- 3 files changed, 21 insertions(+), 24 deletions(-) diff --git a/Common/File/VFS/ZipFileReader.cpp b/Common/File/VFS/ZipFileReader.cpp index f058deb48..aea50985b 100644 --- a/Common/File/VFS/ZipFileReader.cpp +++ b/Common/File/VFS/ZipFileReader.cpp @@ -13,6 +13,7 @@ #include "Common/Common.h" #include "Common/Log.h" #include "Common/File/VFS/ZipFileReader.h" +#include "Common/StringUtils.h" static uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size) { // Figure out the file size first. @@ -33,21 +34,17 @@ static uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size) { return contents; } -ZipFileReader::ZipFileReader(const char *zip_file, const char *in_zip_path) { - zip_file_ = zip_open(zip_file, 0, NULL); - strcpy(in_zip_path_, in_zip_path); - if (!zip_file_) { - ERROR_LOG(IO, "Failed to open %s as a zip file", zip_file); +ZipFileReader::ZipFileReader(const Path &zipFile, const char *inZipPath) { + int error = 0; + if (zipFile.Type() == PathType::CONTENT_URI) { + int fd = File::OpenFD(zipFile, File::OPEN_READ); + zip_file_ = zip_fdopen(fd, 0, &error); + } else { + zip_file_ = zip_open(zipFile.c_str(), 0, &error); } - - std::vector info; - GetFileListing("assets", &info, 0); - for (size_t i = 0; i < info.size(); i++) { - if (info[i].isDirectory) { - DEBUG_LOG(IO, "Directory: %s", info[i].name.c_str()); - } else { - DEBUG_LOG(IO, "File: %s", info[i].name.c_str()); - } + truncate_cpy(inZipPath_, inZipPath); + if (!zip_file_) { + ERROR_LOG(IO, "Failed to open %s as a zip file", zipFile.c_str()); } } @@ -58,7 +55,7 @@ ZipFileReader::~ZipFileReader() { uint8_t *ZipFileReader::ReadFile(const char *path, size_t *size) { char temp_path[2048]; - snprintf(temp_path, sizeof(temp_path), "%s%s", in_zip_path_, path); + snprintf(temp_path, sizeof(temp_path), "%s%s", inZipPath_, path); std::lock_guard guard(lock_); return ReadFromZip(zip_file_, temp_path, size); @@ -66,7 +63,7 @@ uint8_t *ZipFileReader::ReadFile(const char *path, size_t *size) { bool ZipFileReader::GetFileListing(const char *orig_path, std::vector *listing, const char *filter = 0) { char path[2048]; - snprintf(path, sizeof(path), "%s%s", in_zip_path_, orig_path); + snprintf(path, sizeof(path), "%s%s", inZipPath_, orig_path); std::set filters; std::string tmp; @@ -94,7 +91,7 @@ bool ZipFileReader::GetFileListing(const char *orig_path, std::vector &file bool ZipFileReader::GetFileInfo(const char *path, File::FileInfo *info) { struct zip_stat zstat; char temp_path[1024]; - snprintf(temp_path, sizeof(temp_path), "%s%s", in_zip_path_, path); + snprintf(temp_path, sizeof(temp_path), "%s%s", inZipPath_, path); if (0 != zip_stat(zip_file_, temp_path, ZIP_FL_NOCASE | ZIP_FL_UNCHANGED, &zstat)) { // ZIP files do not have real directories, so we'll end up here if we // try to stat one. For now that's fine. diff --git a/Common/File/VFS/ZipFileReader.h b/Common/File/VFS/ZipFileReader.h index 0480d9673..9930ea1ba 100644 --- a/Common/File/VFS/ZipFileReader.h +++ b/Common/File/VFS/ZipFileReader.h @@ -16,14 +16,14 @@ class ZipFileReader : public VFSBackend { public: - ZipFileReader(const char *zip_file, const char *in_zip_path); + ZipFileReader(const Path &zipFile, const char *inZipPath); ~ZipFileReader(); // use delete[] on the returned value. uint8_t *ReadFile(const char *path, size_t *size) override; bool GetFileListing(const char *path, std::vector *listing, const char *filter) override; bool GetFileInfo(const char *path, File::FileInfo *info) override; std::string toString() const override { - return in_zip_path_; + return inZipPath_; } private: @@ -31,5 +31,5 @@ private: zip *zip_file_; std::mutex lock_; - char in_zip_path_[256]; + char inZipPath_[256]; }; diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 5fc9b2cba..a85fba04f 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -695,8 +695,8 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init androidVersion = jAndroidVersion; deviceType = jdeviceType; - std::string apkPath = GetJavaString(env, japkpath); - g_VFS.Register("", new ZipFileReader(apkPath.c_str(), "assets/")); + Path apkPath(GetJavaString(env, japkpath)); + g_VFS.Register("", new ZipFileReader(apkPath, "assets/")); systemName = GetJavaString(env, jmodel); langRegion = GetJavaString(env, jlangRegion); From a8bdf11fdcfdf469e203d81aeb740f71ec7d0077 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 6 Mar 2023 16:56:16 +0100 Subject: [PATCH 6/6] Headless buildfix --- headless/Headless.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/headless/Headless.cpp b/headless/Headless.cpp index 5e034ede2..c61e248d0 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -483,10 +483,10 @@ int main(int argc, const char* argv[]) #if PPSSPP_PLATFORM(ANDROID) // For some reason the debugger installs it with this name? if (File::Exists(Path("/data/app/org.ppsspp.ppsspp-2.apk"))) { - g_VFS.Register("", new ZipFileReader("/data/app/org.ppsspp.ppsspp-2.apk", "assets/")); + g_VFS.Register("", new ZipFileReader(Path("/data/app/org.ppsspp.ppsspp-2.apk"), "assets/")); } if (File::Exists(Path("/data/app/org.ppsspp.ppsspp.apk"))) { - g_VFS.Register("", new ZipFileReader("/data/app/org.ppsspp.ppsspp.apk", "assets/")); + g_VFS.Register("", new ZipFileReader(Path("/data/app/org.ppsspp.ppsspp.apk"), "assets/")); } #elif !PPSSPP_PLATFORM(WINDOWS) g_VFS.Register("", new DirectoryReader(g_Config.flash0Directory / ".."));