Path: blob/master/Core/FileSystems/VirtualDiscFileSystem.h
3187 views
// Copyright (c) 2012- PPSSPP Project.12// This program is free software: you can redistribute it and/or modify3// it under the terms of the GNU General Public License as published by4// the Free Software Foundation, version 2.0 or later versions.56// This program is distributed in the hope that it will be useful,7// but WITHOUT ANY WARRANTY; without even the implied warranty of8// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the9// GNU General Public License 2.0 for more details.1011// A copy of the GPL 2.0 should have been included with the program.12// If not, see http://www.gnu.org/licenses/1314// Official git repository and contact information can be found at15// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.1617#pragma once1819// TODO: Remove the Windows-specific code, FILE is fine there too.2021#include <map>2223#include "Common/File/Path.h"24#include "Core/FileSystems/FileSystem.h"25#include "Core/FileSystems/DirectoryFileSystem.h"2627extern const std::string INDEX_FILENAME;2829class VirtualDiscFileSystem: public IFileSystem {30public:31VirtualDiscFileSystem(IHandleAllocator *_hAlloc, const Path &_basePath);32~VirtualDiscFileSystem();3334void DoState(PointerWrap &p) override;35int OpenFile(std::string filename, FileAccess access, const char *devicename = nullptr) override;36size_t SeekFile(u32 handle, s32 position, FileMove type) override;37size_t ReadFile(u32 handle, u8 *pointer, s64 size) override;38size_t ReadFile(u32 handle, u8 *pointer, s64 size, int &usec) override;39void CloseFile(u32 handle) override;40PSPFileInfo GetFileInfo(std::string filename) override;41PSPFileInfo GetFileInfoByHandle(u32 handle) override;42bool OwnsHandle(u32 handle) override;43int Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) override;44PSPDevType DevType(u32 handle) override;45std::vector<PSPFileInfo> GetDirListing(const std::string &path, bool *exists = nullptr) override;46FileSystemFlags Flags() const override { return FileSystemFlags::UMD; }47u64 FreeDiskSpace(const std::string &path) override { return 0; }4849// unsupported operations50size_t WriteFile(u32 handle, const u8 *pointer, s64 size) override;51size_t WriteFile(u32 handle, const u8 *pointer, s64 size, int &usec) override;52bool MkDir(const std::string &dirname) override;53bool RmDir(const std::string &dirname) override;54int RenameFile(const std::string &from, const std::string &to) override;55bool RemoveFile(const std::string &filename) override;5657bool ComputeRecursiveDirSizeIfFast(const std::string &path, int64_t *size) override { return false; }5859void Describe(char *buf, size_t size) const override { snprintf(buf, size, "VirtualDisc: %s", basePath.ToVisualString().c_str()); } // TODO: Ask the fileLoader about the origins6061private:62void LoadFileListIndex();63// Warning: modifies input string.64int getFileListIndex(std::string &fileName);65int getFileListIndex(u32 accessBlock, u32 accessSize, bool blockMode = false) const;66Path GetLocalPath(std::string localpath) const;6768typedef void *HandlerLibrary;69typedef int HandlerHandle;70typedef s64 HandlerOffset;71typedef void (*HandlerLogFunc)(void *arg, HandlerHandle handle, LogLevel level, const char *msg);7273static void HandlerLogger(void *arg, HandlerHandle handle, LogLevel level, const char *msg);7475// The primary purpose of handlers is to make it easier to work with large archives.76// However, they have other uses as well, such as patching individual files.77struct Handler {78Handler(const char *filename, VirtualDiscFileSystem *const sys);79~Handler();8081typedef bool (*InitFunc)(HandlerLogFunc logger, void *loggerArg);82typedef void (*ShutdownFunc)();83typedef void (*ShutdownV2Func)(void *loggerArg);84typedef HandlerHandle (*OpenFunc)(const char *basePath, const char *filename);85typedef HandlerOffset (*SeekFunc)(HandlerHandle handle, HandlerOffset offset, FileMove origin);86typedef HandlerOffset (*ReadFunc)(HandlerHandle handle, void *data, HandlerOffset size);87typedef void (*CloseFunc)(HandlerHandle handle);88typedef int (*VersionFunc)();8990HandlerLibrary library;91VirtualDiscFileSystem *const sys_;92InitFunc Init;93ShutdownFunc Shutdown;94ShutdownV2Func ShutdownV2;95OpenFunc Open;96SeekFunc Seek;97ReadFunc Read;98CloseFunc Close;99100bool IsValid() const { return library != nullptr; }101};102103struct HandlerFileHandle {104Handler *handler;105HandlerHandle handle;106107HandlerFileHandle() : handler(nullptr), handle(0) {}108HandlerFileHandle(Handler *handler_) : handler(handler_), handle(-1) {}109110bool Open(const std::string& basePath, const std::string& fileName, FileAccess access) {111// Ignore access, read only.112handle = handler->Open(basePath.c_str(), fileName.c_str());113return handle > 0;114}115size_t Read(u8 *data, s64 size) {116return (size_t)handler->Read(handle, data, size);117}118size_t Seek(s32 position, FileMove type) {119return (size_t)handler->Seek(handle, position, type);120}121void Close() {122handler->Close(handle);123}124125bool IsValid() {126return handler != nullptr && handler->IsValid();127}128129HandlerFileHandle &operator =(Handler *_handler) {130handler = _handler;131return *this;132}133};134135typedef enum { VFILETYPE_NORMAL, VFILETYPE_LBN, VFILETYPE_ISO } VirtualFileType;136137struct OpenFileEntry {138OpenFileEntry() {}139OpenFileEntry(FileSystemFlags fileSystemFlags) {140hFile = DirectoryFileHandle(DirectoryFileHandle::SKIP_REPLAY, fileSystemFlags);141}142143DirectoryFileHandle hFile;144HandlerFileHandle handler;145VirtualFileType type = VFILETYPE_NORMAL;146u32 fileIndex = 0;147u64 curOffset = 0;148u64 startOffset = 0; // only used by lbn files149u64 size = 0; // only used by lbn files150151bool Open(const Path &basePath, std::string& fileName, FileAccess access) {152// Ignored, we're read only.153u32 err;154if (handler.IsValid()) {155return handler.Open(basePath.ToString(), fileName, access);156} else {157return hFile.Open(basePath, fileName, access, err);158}159}160size_t Read(u8 *data, s64 size) {161if (handler.IsValid()) {162return handler.Read(data, size);163} else {164return hFile.Read(data, size);165}166}167size_t Seek(s32 position, FileMove type) {168if (handler.IsValid()) {169return handler.Seek(position, type);170} else {171return hFile.Seek(position, type);172}173}174void Close() {175if (handler.IsValid()) {176return handler.Close();177} else {178return hFile.Close();179}180}181};182183typedef std::map<u32, OpenFileEntry> EntryMap;184185EntryMap entries;186IHandleAllocator *hAlloc;187Path basePath;188189struct FileListEntry {190std::string fileName;191u32 firstBlock;192u32 totalSize;193Handler *handler;194};195196std::vector<FileListEntry> fileList;197u32 currentBlockIndex;198u32 lastReadBlock_;199200std::map<std::string, Handler *> handlers;201};202203204