#include #include #include #include #include #include #include #include // Define this to enable debugging, will later support debugging levels, so only messages greater then a certain level will be displayed //#define DEBUG 8 //For release versions of uLE, DEBUG should not be defined //To avoid slowdown and size bloat // Define this to enable some basic profiling support, each function will display the time it took to run. // #define PROFILING // Misc defintions #define malloc( a ) AllocSysMemory( 0, ( a ), NULL ) #define free( a ) FreeSysMemory( ( a ) ) #define TRUE 1 #define FALSE 0 #define MAX_NAME 32 #define MAX_PATH 1024 // Vmcfs error definitions #define VMCFS_ERR_NO 0 #define VMCFS_ERR_INITIALIZED -1 #define VMCFS_ERR_VMC_OPEN -2 #define VMCFS_ERR_VMC_READ -3 #define VMCFS_ERR_CARD_TYPE -4 #define VMCFS_ERR_NOT_FORMATED -5 #define VMCFS_ERR_VMC_SIZE -6 #define VMCFS_ERR_NOT_MOUNT -7 #define VMCFS_ERR_MOUNT_BUSY -8 #define VMCFS_ERR_IMPLEMENTED -9 // The devctl commands: 0x56 == V, 0x4D == M, 0x43 == C, 0x01, 0x02, ... == command number. #define DEVCTL_VMCFS_CLEAN 0x564D4301 // Set as free all fat cluster corresponding to a none existing object. ( Object are just marked as none existing but not removed from fat table when rmdir or remove fonctions are call. This allow to recover a deleted file. ) #define DEVCTL_VMCFS_CKFREE 0x564D4302 // Check free space available on vmc. // The ioctl commands: 0x56 == V, 0x4D == M, 0x43 == C, 0x01, 0x02, ... == command number. #define IOCTL_VMCFS_RECOVER 0x564D4303 // Recover an object marked as none existing. ( data must be a valid path to an object in vmc file ) // Vmc format enum typedef enum { FORMAT_FULL, FORMAT_FAST } Vmc_Format_Enum; // Memorycard type definitions #define PSX_MEMORYCARD 0x1 #define PS2_MEMORYCARD 0x2 #define PDA_MEMORYCARD 0x3 // Directory Entry Mode Flags #define DF_READ 0x0001 // Read permission. #define DF_WRITE 0x0002 // Write permission. #define DF_EXECUTE 0x0004 // Execute permission. #define DF_PROTECTED 0x0008 // Directory is copy protected. #define DF_FILE 0x0010 // Regular file. #define DF_DIRECTORY 0x0020 // Directory. #define DF_040 0x0040 // Used internally to create directories. #define DF_080 0x0080 // Copied? #define DF_0100 0x0100 // - #define O_CREAT 0x0200 // Used to create files. #define DF_0400 0x0400 // Set when files and directories are created, otherwise ignored. #define DF_POCKETSTN 0x0800 // PocketStation application save file. #define DF_PSX 0x1000 // PlayStation save file. #define DF_HIDDEN 0x2000 // File is hidden. #define DF_04000 0x4000 // - #define DF_EXISTS 0x8000 // This entry is in use. If this flag is clear, then the file or directory has been deleted. // Cluster definitions #define MAX_CLUSTER_SIZE 0x400 #define ROOT_CLUSTER 0x00000000 #define FREE_CLUSTER 0x7FFFFFFF #define EOF_CLUSTER 0xFFFFFFFF #define ERROR_CLUSTER 0xFFFFFFFF #define NOFOUND_CLUSTER 0xFFFFFFFF #define MASK_CLUSTER 0x80000000 // The debugging functions, very very handy #ifdef DEBUG #define DEBUGPRINT( level, args... ) \ if( DEBUG >= level ) printf( args ) #else #define DEBUGPRINT( args... ) #endif // Used for timing functions, use this to optimize stuff #ifdef PROFILING void profilerStart( iop_sys_clock_t *iopclock ); void profilerEnd( const char *function, const char* name, iop_sys_clock_t *iopclock1 ); //This creates 2 variables with the names name1/name2, and starts the profiler #define PROF_START( name ) \ iop_sys_clock_t name;\ profilerStart( &name ); //this takes the 2 variable names and ends the profiler, printing the time taken #define PROF_END( name ) \ profilerEnd( __func__, #name, &name ); #else //define away the profiler functions #define PROF_START( args ) ; #define PROF_END( args ) ; #endif // Global Structures Defintions // General data struct shared by both files / folders that we have opened struct gen_privdata { int fd; unsigned int indir_fat_clusters[ 32 ]; unsigned int first_allocatable; unsigned int last_allocatable; unsigned char dirent_page; }; // the structure used by files that we have opened struct file_privdata { struct gen_privdata gendata; unsigned int file_startcluster; unsigned int file_length; unsigned int file_position; unsigned int file_cluster; unsigned int cluster_offset; unsigned int file_dirpage; }; // the structure used by directories that we have opened struct dir_privdata { struct gen_privdata gendata; unsigned int dir_number; // first or second entry in the cluster? unsigned int dir_cluster; // what cluster we are currently reading directory entries from unsigned int dir_length; // the length of the directory }; // date / time descriptor typedef struct { unsigned char unused0; unsigned char sec; unsigned char min; unsigned char hour; unsigned char day; unsigned char month; unsigned short year; } vmc_datetime; // the structure of a directory entry struct direntry { unsigned short mode; // See directory mode definitions. unsigned char unused0[ 2 ]; // - unsigned int length; // Length in bytes if a file, or entries if a directory. vmc_datetime created; // created time. unsigned int cluster; // First cluster of the file, or 0xFFFFFFFF for an empty file. In "." entries it's the first cluster of the parent directory relative to first_allocatable. unsigned int dir_entry; // Only in "." entries. Entry of this directory in its parent's directory. vmc_datetime modified; // Modification time. unsigned int attr; // User defined attribute. unsigned char unused1[ 28 ]; // - unsigned char name[ 32 ]; // Zero terminated name for this directory entry. unsigned char unused2[ 416 ]; // - }; // A structure containing all of the information about the superblock on a memory card. struct superblock { unsigned char magic[ 40 ]; unsigned short page_size; unsigned short pages_per_cluster; unsigned short pages_per_block; unsigned short unused0; // always 0xFF00 unsigned int clusters_per_card; unsigned int first_allocatable; unsigned int last_allocatable; unsigned int root_cluster; // must be 0 unsigned int backup_block1; // 1023 unsigned int backup_block2; // 1024 unsigned char unused1[ 8 ]; // unused / who knows what it is unsigned int indir_fat_clusters[ 32 ]; unsigned int bad_block_list[ 32 ]; unsigned char mc_type; unsigned char mc_flag; unsigned short unused2; // zero unsigned int cluster_size; // 1024 always, 0x400 unsigned int unused3; // 0x100 unsigned int size_in_megs; // size in megabytes unsigned int unused4; // 0xffffffff unsigned char unused5[ 12 ]; // zero unsigned int max_used; // 97%of total clusters unsigned char unused6[ 8 ]; // zero unsigned int unused7; // 0xffffffff }; // General vmc image structure struct global_vmc { int fd; // global descriptor struct superblock header; // superblock header int formated; // card is formated int ecc_flag; // ecc data found in vmc file unsigned int card_size; // vmc file size unsigned int total_pages; // total number of pages in the vmc file unsigned int cluster_size; // size in byte of a cluster unsigned short erase_byte; // erased blocks have all bits set to 0x0 or 0xFF unsigned int last_idc; // last indirect cluster unsigned int last_cluster; // last cluster unsigned int indirect_cluster[ MAX_CLUSTER_SIZE ]; // indirect fat cluster unsigned int fat_cluster[ MAX_CLUSTER_SIZE ]; // fat cluster unsigned int last_free_cluster; // adress of the last free cluster found when getting free cluster }; extern struct global_vmc g_Vmc_Image[ 2 ]; extern int g_Vmc_Format_Mode; extern int g_Vmc_Remove_Flag; extern int g_Vmc_Initialized; // vmc_fs.c int Vmc_Initialize ( iop_device_t * driver ); int Vmc_Deinitialize ( iop_device_t * driver ); // vmc_io.c int Vmc_Format ( iop_file_t *, const char *dev, const char *blockdev, void *arg, size_t arglen ); int Vmc_Open ( iop_file_t *f, const char *name, int flags, int mode ); int Vmc_Close ( iop_file_t* f ); int Vmc_Read ( iop_file_t* f, void* buffer, int size ); int Vmc_Write ( iop_file_t* f, void* buffer, int size ); int Vmc_Lseek ( iop_file_t* f, unsigned long offset, int whence ); int Vmc_Ioctl ( iop_file_t* f, unsigned long request, void* data ); int Vmc_Remove ( iop_file_t* f, const char* path ); int Vmc_Mkdir ( iop_file_t* f, const char* path1, int mode ); int Vmc_Rmdir ( iop_file_t* f, const char* path1 ); int Vmc_Dopen ( iop_file_t* f, const char* path ); int Vmc_Dclose ( iop_file_t* f ); int Vmc_Dread ( iop_file_t* f, iox_dirent_t *buf ); int Vmc_Getstat ( iop_file_t* f, const char* path, iox_stat_t * stat ); int Vmc_Chstat ( iop_file_t* f, const char* path, iox_stat_t * stat, unsigned int unknown ); int Vmc_Rename ( iop_file_t* f, const char* path, const char* new_name ); int Vmc_Chdir ( iop_file_t* f, const char* path ); int Vmc_Sync ( iop_file_t* f, const char* device, int flag ); int Vmc_Mount ( iop_file_t* f, const char* fsname, const char* devname, int flag, void *arg, unsigned int arg_len ); int Vmc_Umount ( iop_file_t* f, const char* fsname ); int Vmc_Lseek64 ( iop_file_t* f, long long offset, int whence ); int Vmc_Devctl ( iop_file_t* f, const char* path, int cmd, void *arg, unsigned int arglen, void *buf, unsigned int buflen ); int Vmc_Symlink ( iop_file_t* f, const char* old, const char* new ); int Vmc_Readlink ( iop_file_t* f, const char* path, char* buf, unsigned int buf_len ); int Vmc_Ioctl2 ( iop_file_t* f, int cmd, void *arg, unsigned int arglen, void *buf, unsigned int buflen ); int Vmc_Recover ( int unit, const char* path1 ); unsigned int Vmc_Checkfree ( int unit ); int Vmc_Clean ( int unit ); // mcfat.c typedef enum { FAT_VALUE, FAT_MASK } GetFat_Mode; typedef enum { FAT_RESET, FAT_SET } SetFat_Mode; unsigned int getFatEntry ( int fd, unsigned int cluster, unsigned int* indir_fat_clusters, GetFat_Mode Mode ); unsigned int setFatEntry ( int fd, unsigned int cluster, unsigned int value, unsigned int* indir_fat_clusters, SetFat_Mode Mode ); // ps2.c int eraseBlock ( int fd, unsigned int block ); int writePage ( int fd, unsigned char* page, unsigned int pagenum ); int writeCluster ( int fd, unsigned char* cluster, unsigned int clusternum ); int writeClusterPart ( int fd, unsigned char* cluster, unsigned int clusternum, int cluster_offset, int size ); int readPage ( int fd, unsigned char* page, unsigned int pagenum ); int readCluster ( int fd, unsigned char* cluster, unsigned int clusternum ); // misc.c unsigned int getDirentryFromPath ( struct direntry* retval, const char* path, struct gen_privdata* gendata, int unit ); unsigned int addObject ( struct gen_privdata* gendata, unsigned int parentcluster, struct direntry* parent, struct direntry* dirent, int unit ); void removeObject ( struct gen_privdata* gendata, unsigned int dirent_cluster, struct direntry* dirent, int unit ); unsigned int getFreeCluster ( struct gen_privdata* gendata, int unit ); int getPs2Time ( vmc_datetime* tm ); int setDefaultSpec ( int unit ); int buildECC ( int unit, char* Page_Data, char* ECC_Data );