diff --git a/engine/common/filesystem.c b/engine/common/filesystem.c index e93f2bb6..f9520270 100644 --- a/engine/common/filesystem.c +++ b/engine/common/filesystem.c @@ -195,6 +195,10 @@ static zip_t *fs_last_zip; #endif // XASH_NO_ZIP static pack_t *fs_last_pak; +#if XASH_PSP +static fsh_handle_t *fsh_gamedir = NULL; +#endif + static void FS_EnsureOpenFile( file_t *file ) { if( fs_last_readfile == file ) @@ -2337,6 +2341,11 @@ void FS_Init( void ) } stringlistfreecontents( &dirs ); +#if XASH_PSP + fsh_gamedir = FSH_Init( fs_gamedir, 5000 ); + if( !fsh_gamedir ) + Con_Reportf( "FS_Init: FS Helper error\n" ); +#endif Con_Reportf( "FS_Init: done\n" ); } @@ -2362,6 +2371,10 @@ void FS_Shutdown( void ) FS_ClearSearchPath(); // release all wad files too Mem_FreePool( &fs_mempool ); +#if XASH_PSP + FSH_Shutdown( fsh_gamedir ); + fsh_gamedir = NULL; +#endif } /* @@ -2492,7 +2505,7 @@ static file_t *FS_SysOpen( const char *filepath, const char *mode ) #endif #if XASH_PSP file = (file_t *)Mem_Calloc( fs_mempool, sizeof( file_t ) + FILE_BUFF_SIZE + 64 ); - file->buff = (byte *)( ( ( ( u32 )file + sizeof( file_t ) ) & ( ~( 64 - 1 ) ) ) + 64 ); + file->buff = (byte *)(((( u32 )file + sizeof( file_t )) & ( ~( 64 - 1 ))) + 64 ); #else file = (file_t *)Mem_Calloc( fs_mempool, sizeof( *file )); #endif @@ -2501,7 +2514,7 @@ static file_t *FS_SysOpen( const char *filepath, const char *mode ) #endif file->ungetc = EOF; #if XASH_PSP - file->handle = sceIoOpen( filepath, mod|opt, 0666 ); + file->handle = sceIoOpen( filepath, mod|opt, 0666 ); #else file->handle = open( filepath, mod|opt, 0666 ); #endif @@ -2509,7 +2522,11 @@ static file_t *FS_SysOpen( const char *filepath, const char *mode ) #if XASH_PSP file->backup_hold = backup_hold; if( file->handle >= 0 ) + { FS_BackupFileName( file, filepath, mod|opt ); + if( mod == PSP_O_WRONLY || mod == PSP_O_RDWR ) + FSH_AddFilePath( fsh_gamedir, filepath ); + } #elif !XASH_WIN32 if( file->handle < 0 ) { @@ -2668,8 +2685,17 @@ qboolean FS_SysFileExists( const char *path, qboolean caseinsensitive ) close( desc ); return true; #elif XASH_PSP - SceIoStat buf; - if ( sceIoGetstat( path, &buf ) < 0 ) + int result; + SceIoStat buf; + + result = FSH_Find( fsh_gamedir, path ); + if( result >= 0 ) + return true; + if( result == -1 ) + return false; + + result = sceIoGetstat( path, &buf ); + if ( result < 0 ) return false; return FIO_S_ISREG( buf.st_mode ); #else @@ -3813,6 +3839,10 @@ qboolean GAME_EXPORT FS_Delete( const char *path ) COM_FixSlashes( real_path ); iRet = remove( real_path ); +#if XASH_PSP + FSH_RemoveFilePath( fsh_gamedir, real_path ); +#endif + return (iRet == 0); } diff --git a/engine/platform/platform.h b/engine/platform/platform.h index 4939e155..86250a70 100644 --- a/engine/platform/platform.h +++ b/engine/platform/platform.h @@ -44,6 +44,7 @@ SceUID Platform_LoadModule( const char *filename, int mpid, SceSize argsize, voi int Platform_UnloadModule( SceUID modid, int *sce_code ); #include "psp/p5ram_psp.h" +#include "psp/fsh_psp.h" #endif #if XASH_ANDROID const char *Android_GetAndroidID( void ); diff --git a/engine/platform/psp/fsh_psp.c b/engine/platform/psp/fsh_psp.c new file mode 100644 index 00000000..93924f86 --- /dev/null +++ b/engine/platform/psp/fsh_psp.c @@ -0,0 +1,205 @@ +/* +fsh_psp.c - PSP filesystem helper +Copyright (C) 2022 Sergey Galushko + +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, either version 3 of the License, or +(at your option) any later version. + +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 for more details. +*/ +#include +#include "common.h" +#include "fsh_psp.h" + +#define FSH_MAX_PATH 63 + +#define FSH_STATE_USED 0x01 + +typedef struct fsh_path_s +{ + byte state; + char path[FSH_MAX_PATH]; +}fsh_path_t; + +typedef struct fsh_handle_s +{ + qboolean ready; + int count; + char folderpath[FSH_MAX_PATH]; + int folderpath_size; + int pathlist_size; + fsh_path_t *pathlist; +}fsh_handle_t; + +int FSH_AddFilePath( fsh_handle_t *handle, char *path ) +{ + int index; + + if( !handle ) + return -2; + + if( Q_strnicmp( path, handle->folderpath, handle->folderpath_size )) + return -2; + + if( handle->ready && handle->count > 0 ) + { + // see if already added + for( index = 0; index < handle->count; index++ ) + { + if( !Q_stricmp( handle->pathlist[index].path, path )) + return index; + } + + // find empty + for( index = 0; index < handle->count; index++ ) + { + if(!( handle->pathlist[index].state & FSH_STATE_USED )) + { + Q_strncpy( handle->pathlist[index].path, path, FSH_MAX_PATH - 1 ); + handle->pathlist[index].state |= FSH_STATE_USED; + + return index; + } + } + } + + // create new + if( handle->count + 1 >= handle->pathlist_size ) + return -1; + + Q_strncpy( handle->pathlist[handle->count].path, path, FSH_MAX_PATH - 1 ); + handle->pathlist[handle->count].state |= FSH_STATE_USED; + handle->count++; + + return handle->count; +} + +int FSH_RemoveFilePath( fsh_handle_t *handle, char *path ) +{ + int index; + + if( !handle ) + return -2; + + if( Q_strnicmp( path, handle->folderpath, handle->folderpath_size )) + return -2; + + for( index = 0; index < handle->count; index++ ) + { + if( !Q_stricmp( handle->pathlist[index].path, path )) + { + memset( handle->pathlist[index].path, 0, FSH_MAX_PATH) ; + handle->pathlist[index].state &= ~FSH_STATE_USED; + + return index; + } + } + + return -1; +} + +int FSH_Find( fsh_handle_t *handle, char *path ) +{ + int index; + + if( !handle ) + return -2; + + if( !handle->ready || !handle->count || Q_strnicmp( path, handle->folderpath, handle->folderpath_size )) + return -2; + + for( index = 0; index < handle->count; index++ ) + { + if( !Q_stricmp(handle->pathlist[index].path, path )) + return index; + } + + return -1; +} + +static int FSH_ScanDir( fsh_handle_t *handle, char *path ) +{ + SceUID dir; + SceIoDirent entry; + char temp[FSH_MAX_PATH]; + int result; + + if(( dir = sceIoDopen( path )) < 0 ) + return -1; + + result = 0; + + // iterate through the directory + while( 1 ) + { + // zero the dirent, to avoid possible problems with sceIoDread + memset( &entry, 0, sizeof( SceIoDirent )); + if( !sceIoDread( dir, &entry )) + break; + + // ignore the virtual directories + if( !Q_stricmp( entry.d_name, "." ) || !Q_stricmp( entry.d_name, ".." )) + continue; + + sprintf( temp, "%s/%s", path, entry.d_name ); + + if(FIO_S_ISDIR( entry.d_stat.st_mode )) + result = FSH_ScanDir( handle, temp ); + else if(FIO_S_ISREG( entry.d_stat.st_mode )) + result = FSH_AddFilePath( handle, temp ); + else continue; + if( result < 0 ) break; + } + sceIoDclose( dir ); + + return result; +} + +fsh_handle_t *FSH_Init( char *path, int maxfiles ) +{ + fsh_handle_t *handle; + + handle = P5Ram_Alloc( sizeof( fsh_handle_t ), 1); + if( !handle ) + return NULL; + + handle->pathlist_size = maxfiles; + handle->pathlist = P5Ram_Alloc( handle->pathlist_size * sizeof( fsh_path_t ), 1 ); + if( !handle->pathlist ) + { + FSH_Shutdown( handle ); + return NULL; + } + + if( !Q_strnicmp( path, "./", 2 )) + path += 2; + + Q_strncpy( handle->folderpath, path, FSH_MAX_PATH - 1 ); + handle->folderpath_size = Q_strlen( handle->folderpath ); + + if( FSH_ScanDir( handle, handle->folderpath ) < 0 ) + { + FSH_Shutdown( handle ); + return NULL; + } + + handle->ready = true; + + return handle; +} + +void FSH_Shutdown( fsh_handle_t *handle ) +{ + if( !handle ) + return; + + if( handle->pathlist ) + P5Ram_Free( handle->pathlist ); + + P5Ram_Free( handle ); +} diff --git a/engine/platform/psp/fsh_psp.h b/engine/platform/psp/fsh_psp.h new file mode 100644 index 00000000..5a78dfae --- /dev/null +++ b/engine/platform/psp/fsh_psp.h @@ -0,0 +1,34 @@ +/* +fsh_psp.h - PSP filesystem helper header +Copyright (C) 2022 Sergey Galushko + +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, either version 3 of the License, or +(at your option) any later version. + +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 for more details. +*/ +#ifndef FSH_PSP_H +#define FSH_PSP_H + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +typedef struct fsh_handle_s fsh_handle_t; + +int FSH_AddFilePath( fsh_handle_t *handle, char *path ); +int FSH_RemoveFilePath( fsh_handle_t *handle, char *path ); +int FSH_Find( fsh_handle_t *handle, char *path ); +fsh_handle_t *FSH_Init( char *path, int maxfiles ); +void FSH_Shutdown( fsh_handle_t *handle ); + +#ifdef __cplusplus +} +#endif + +#endif // P5RAM_PSP_H