2013-07-27 23:46:26 -07:00
// Copyright (c) 2012- PPSSPP Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
# pragma once
// TODO: Remove the Windows-specific code, FILE is fine there too.
# include <map>
2021-05-06 01:31:38 +02:00
# include "Common/File/Path.h"
2013-07-27 23:46:26 -07:00
# include "Core/FileSystems/FileSystem.h"
# include "Core/FileSystems/DirectoryFileSystem.h"
2024-02-02 09:02:40 +01:00
extern const std : : string INDEX_FILENAME ;
2013-07-28 10:31:42 -07:00
class VirtualDiscFileSystem : public IFileSystem {
2013-07-27 23:46:26 -07:00
public :
2021-05-09 18:38:48 +02:00
VirtualDiscFileSystem ( IHandleAllocator * _hAlloc , const Path & _basePath ) ;
2013-07-27 23:46:26 -07:00
~ VirtualDiscFileSystem ( ) ;
2014-12-08 15:14:35 -05:00
void DoState ( PointerWrap & p ) override ;
2019-10-20 11:03:37 -07:00
int OpenFile ( std : : string filename , FileAccess access , const char * devicename = nullptr ) override ;
2014-12-08 15:14:35 -05:00
size_t SeekFile ( u32 handle , s32 position , FileMove type ) override ;
size_t ReadFile ( u32 handle , u8 * pointer , s64 size ) override ;
2013-12-27 16:36:51 -08:00
size_t ReadFile ( u32 handle , u8 * pointer , s64 size , int & usec ) override ;
2014-12-08 15:14:35 -05:00
void CloseFile ( u32 handle ) override ;
PSPFileInfo GetFileInfo ( std : : string filename ) override ;
bool OwnsHandle ( u32 handle ) override ;
int Ioctl ( u32 handle , u32 cmd , u32 indataPtr , u32 inlen , u32 outdataPtr , u32 outlen , int & usec ) override ;
2020-05-21 17:57:41 -07:00
PSPDevType DevType ( u32 handle ) override ;
2022-10-09 09:08:18 -07:00
std : : vector < PSPFileInfo > GetDirListing ( const std : : string & path , bool * exists = nullptr ) override ;
2024-11-26 00:28:22 +01:00
FileSystemFlags Flags ( ) const override { return FileSystemFlags : : UMD ; }
2024-10-11 11:55:27 +02:00
u64 FreeDiskSpace ( const std : : string & path ) override { return 0 ; }
2013-07-27 23:46:26 -07:00
// unsupported operations
2014-12-08 15:14:35 -05:00
size_t WriteFile ( u32 handle , const u8 * pointer , s64 size ) override ;
2013-12-27 16:36:51 -08:00
size_t WriteFile ( u32 handle , const u8 * pointer , s64 size , int & usec ) override ;
2014-12-08 15:14:35 -05:00
bool MkDir ( const std : : string & dirname ) override ;
bool RmDir ( const std : : string & dirname ) override ;
int RenameFile ( const std : : string & from , const std : : string & to ) override ;
bool RemoveFile ( const std : : string & filename ) override ;
2013-07-27 23:46:26 -07:00
2021-09-11 17:18:39 +02:00
bool ComputeRecursiveDirSizeIfFast ( const std : : string & path , int64_t * size ) override { return false ; }
2024-11-26 00:28:22 +01:00
void Describe ( char * buf , size_t size ) const override { snprintf ( buf , size , " VirtualDisc: %s " , basePath . ToVisualString ( ) . c_str ( ) ) ; } // TODO: Ask the fileLoader about the origins
2013-07-27 23:46:26 -07:00
private :
2013-07-28 02:48:31 -07:00
void LoadFileListIndex ( ) ;
2016-05-30 00:38:20 -07:00
// Warning: modifies input string.
int getFileListIndex ( std : : string & fileName ) ;
2024-11-25 23:03:15 +01:00
int getFileListIndex ( u32 accessBlock , u32 accessSize , bool blockMode = false ) const ;
Path GetLocalPath ( std : : string localpath ) const ;
2013-07-27 23:46:26 -07:00
2013-07-28 10:31:42 -07:00
typedef void * HandlerLibrary ;
typedef int HandlerHandle ;
typedef s64 HandlerOffset ;
2023-08-25 11:33:48 +02:00
typedef void ( * HandlerLogFunc ) ( void * arg , HandlerHandle handle , LogLevel level , const char * msg ) ;
2013-07-28 11:49:02 -07:00
2023-08-25 11:33:48 +02:00
static void HandlerLogger ( void * arg , HandlerHandle handle , LogLevel level , const char * msg ) ;
2013-07-28 10:31:42 -07:00
// The primary purpose of handlers is to make it easier to work with large archives.
// However, they have other uses as well, such as patching individual files.
struct Handler {
2013-07-28 13:09:00 -07:00
Handler ( const char * filename , VirtualDiscFileSystem * const sys ) ;
2013-07-28 10:31:42 -07:00
~ Handler ( ) ;
2013-07-28 13:09:00 -07:00
typedef bool ( * InitFunc ) ( HandlerLogFunc logger , void * loggerArg ) ;
2013-07-28 11:49:02 -07:00
typedef void ( * ShutdownFunc ) ( ) ;
2023-03-26 14:35:54 -07:00
typedef void ( * ShutdownV2Func ) ( void * loggerArg ) ;
2013-07-28 11:49:02 -07:00
typedef HandlerHandle ( * OpenFunc ) ( const char * basePath , const char * filename ) ;
typedef HandlerOffset ( * SeekFunc ) ( HandlerHandle handle , HandlerOffset offset , FileMove origin ) ;
typedef HandlerOffset ( * ReadFunc ) ( HandlerHandle handle , void * data , HandlerOffset size ) ;
typedef void ( * CloseFunc ) ( HandlerHandle handle ) ;
2023-03-26 14:35:54 -07:00
typedef int ( * VersionFunc ) ( ) ;
2013-07-28 11:49:02 -07:00
2013-07-28 10:31:42 -07:00
HandlerLibrary library ;
2023-03-26 14:35:54 -07:00
VirtualDiscFileSystem * const sys_ ;
2013-07-28 11:49:02 -07:00
InitFunc Init ;
ShutdownFunc Shutdown ;
2023-03-26 14:35:54 -07:00
ShutdownV2Func ShutdownV2 ;
2013-07-28 11:49:02 -07:00
OpenFunc Open ;
SeekFunc Seek ;
ReadFunc Read ;
CloseFunc Close ;
2021-07-24 18:16:12 +02:00
bool IsValid ( ) const { return library ! = nullptr ; }
2013-07-28 10:31:42 -07:00
} ;
struct HandlerFileHandle {
Handler * handler ;
HandlerHandle handle ;
2021-07-24 18:16:12 +02:00
HandlerFileHandle ( ) : handler ( nullptr ) , handle ( 0 ) { }
HandlerFileHandle ( Handler * handler_ ) : handler ( handler_ ) , handle ( - 1 ) { }
2013-07-28 11:49:02 -07:00
2021-05-06 01:31:38 +02:00
bool Open ( const std : : string & basePath , const std : : string & fileName , FileAccess access ) {
2013-07-28 10:31:42 -07:00
// Ignore access, read only.
handle = handler - > Open ( basePath . c_str ( ) , fileName . c_str ( ) ) ;
return handle > 0 ;
}
size_t Read ( u8 * data , s64 size ) {
return ( size_t ) handler - > Read ( handle , data , size ) ;
}
size_t Seek ( s32 position , FileMove type ) {
return ( size_t ) handler - > Seek ( handle , position , type ) ;
}
void Close ( ) {
handler - > Close ( handle ) ;
}
2013-07-28 11:49:02 -07:00
bool IsValid ( ) {
2021-07-24 18:16:12 +02:00
return handler ! = nullptr & & handler - > IsValid ( ) ;
2013-07-28 11:49:02 -07:00
}
HandlerFileHandle & operator = ( Handler * _handler ) {
handler = _handler ;
return * this ;
}
2013-07-28 10:31:42 -07:00
} ;
2013-07-27 23:46:26 -07:00
typedef enum { VFILETYPE_NORMAL , VFILETYPE_LBN , VFILETYPE_ISO } VirtualFileType ;
struct OpenFileEntry {
2021-07-24 18:16:12 +02:00
OpenFileEntry ( ) { }
OpenFileEntry ( FileSystemFlags fileSystemFlags ) {
hFile = DirectoryFileHandle ( DirectoryFileHandle : : SKIP_REPLAY , fileSystemFlags ) ;
}
DirectoryFileHandle hFile ;
2013-07-28 10:31:42 -07:00
HandlerFileHandle handler ;
2021-07-24 18:16:12 +02:00
VirtualFileType type = VFILETYPE_NORMAL ;
u32 fileIndex = 0 ;
u64 curOffset = 0 ;
u64 startOffset = 0 ; // only used by lbn files
u64 size = 0 ; // only used by lbn files
2013-07-28 11:49:02 -07:00
2021-05-06 01:31:38 +02:00
bool Open ( const Path & basePath , std : : string & fileName , FileAccess access ) {
2014-11-02 12:40:31 -08:00
// Ignored, we're read only.
u32 err ;
2013-07-28 11:49:02 -07:00
if ( handler . IsValid ( ) ) {
2021-05-06 01:31:38 +02:00
return handler . Open ( basePath . ToString ( ) , fileName , access ) ;
2013-07-28 11:49:02 -07:00
} else {
2014-11-02 12:40:31 -08:00
return hFile . Open ( basePath , fileName , access , err ) ;
2013-07-28 11:49:02 -07:00
}
}
size_t Read ( u8 * data , s64 size ) {
if ( handler . IsValid ( ) ) {
return handler . Read ( data , size ) ;
} else {
return hFile . Read ( data , size ) ;
}
}
size_t Seek ( s32 position , FileMove type ) {
if ( handler . IsValid ( ) ) {
return handler . Seek ( position , type ) ;
} else {
return hFile . Seek ( position , type ) ;
}
}
void Close ( ) {
if ( handler . IsValid ( ) ) {
return handler . Close ( ) ;
} else {
return hFile . Close ( ) ;
}
}
2013-07-27 23:46:26 -07:00
} ;
typedef std : : map < u32 , OpenFileEntry > EntryMap ;
2021-07-24 18:16:12 +02:00
2013-07-27 23:46:26 -07:00
EntryMap entries ;
IHandleAllocator * hAlloc ;
2021-05-06 01:31:38 +02:00
Path basePath ;
2013-07-27 23:46:26 -07:00
2013-07-28 11:49:02 -07:00
struct FileListEntry {
2013-07-27 23:46:26 -07:00
std : : string fileName ;
u32 firstBlock ;
u32 totalSize ;
2013-07-28 11:49:02 -07:00
Handler * handler ;
} ;
2013-07-27 23:46:26 -07:00
std : : vector < FileListEntry > fileList ;
u32 currentBlockIndex ;
2013-12-27 16:49:35 -08:00
u32 lastReadBlock_ ;
2013-07-28 10:31:42 -07:00
2013-07-28 11:49:02 -07:00
std : : map < std : : string , Handler * > handlers ;
2013-07-27 23:46:26 -07:00
} ;