2022-08-04 01:13:26 +02:00
#include <renderd7/FileSystem.hpp>
#include <3ds.h>
#include <cstring>
2022-08-04 02:50:37 +02:00
//Debugging
#include <memory>
#include <renderd7/Ovl.hpp>
#include <renderd7/Toast.hpp>
2022-08-04 01:13:26 +02:00
const char * RenderD7 :: FileSystem :: GetPhysfsError ()
{
return PHYSFS_getErrorByCode ( PHYSFS_getLastErrorCode ());
}
std :: string RenderD7 :: FileSystem :: Normalize ( const std :: string & input )
{
std :: string out ;
bool seenSep = false , isSep = false ;
for ( size_t i = 0 ; i < input . size (); ++ i )
{
isSep = ( input [ i ] == '/' );
if ( ! isSep || ! seenSep )
out += input [ i ];
seenSep = isSep ;
}
return out ;
}
void RenderD7 :: FileSystem :: Initialize ()
{
RenderD7 :: FileSystem :: savePath = "" ;
}
int RenderD7 :: FileSystem :: Init ( const char * argv )
{
2022-08-04 02:50:37 +02:00
int res = PHYSFS_init ( argv );
if ( res != 1 )
{
RenderD7 :: AddOvl ( std :: make_unique < RenderD7 :: Toast > ( "PHYSFS-Error" , RenderD7 :: FileSystem :: GetPhysfsError ()));
}
return res ;
2022-08-04 01:13:26 +02:00
}
bool RenderD7 :: FileSystem :: SetSource ( const char * source )
{
if ( ! PHYSFS_isInit ())
2022-08-04 02:50:37 +02:00
RenderD7 :: AddOvl ( std :: make_unique < RenderD7 :: Toast > ( "PHYSFS-Error" , RenderD7 :: FileSystem :: GetPhysfsError ()));
2022-08-04 01:13:26 +02:00
return false ;
std :: string searchPath = source ;
if ( ! PHYSFS_mount ( searchPath . c_str (), NULL , 1 ))
2022-08-04 02:50:37 +02:00
RenderD7 :: AddOvl ( std :: make_unique < RenderD7 :: Toast > ( "PHYSFS-Error" , RenderD7 :: FileSystem :: GetPhysfsError ()));
2022-08-04 01:13:26 +02:00
return false ;
return true ;
}
bool RenderD7 :: FileSystem :: SetIdentity ( const char * name , bool append )
{
if ( ! PHYSFS_isInit ())
2022-08-04 02:50:37 +02:00
RenderD7 :: AddOvl ( std :: make_unique < RenderD7 :: Toast > ( "PHYSFS-Error" , RenderD7 :: FileSystem :: GetPhysfsError ()));
2022-08-04 01:13:26 +02:00
return false ;
std :: string old = RenderD7 :: FileSystem :: savePath ;
RenderD7 :: FileSystem :: savePath = RenderD7 :: FileSystem :: Normalize ( RenderD7 :: FileSystem :: GetUserDirectory () + "/save/" + name );
printf ( "Save Path set to %s \n " , savePath . c_str ());
if ( ! old . empty ())
PHYSFS_unmount ( old . c_str ());
int success = PHYSFS_mount ( savePath . c_str (), NULL , append );
printf ( "Save Path mounted %d \n " , success );
PHYSFS_setWriteDir ( nullptr );
return true ;
}
std :: string RenderD7 :: FileSystem :: GetSaveDirectory ()
{
return RenderD7 :: FileSystem :: Normalize ( RenderD7 :: FileSystem :: GetUserDirectory () + "/save" );
}
bool RenderD7 :: FileSystem :: SetupWriteDirectory ()
{
if ( ! PHYSFS_isInit ())
2022-08-04 02:50:37 +02:00
RenderD7 :: AddOvl ( std :: make_unique < RenderD7 :: Toast > ( "PHYSFS-Error" , RenderD7 :: FileSystem :: GetPhysfsError ()));
2022-08-04 01:13:26 +02:00
return false ;
if ( RenderD7 :: FileSystem :: savePath . empty ())
2022-08-04 02:50:37 +02:00
RenderD7 :: AddOvl ( std :: make_unique < RenderD7 :: Toast > ( "PHYSFS-Error" , "Path is Empty" ));
2022-08-04 01:13:26 +02:00
return false ;
std :: string tmpWritePath = RenderD7 :: FileSystem :: savePath ;
std :: string tmpDirectoryPath = RenderD7 :: FileSystem :: savePath ;
if ( RenderD7 :: FileSystem :: savePath . find ( RenderD7 :: FileSystem :: GetUserDirectory ()) == 0 )
{
tmpWritePath = RenderD7 :: FileSystem :: GetUserDirectory ();
tmpDirectoryPath = savePath . substr ( RenderD7 :: FileSystem :: GetUserDirectory (). length ());
/* strip leading '/' characters from the path we want to create */
size_t startPosition = tmpDirectoryPath . find_first_not_of ( '/' );
if ( startPosition != std :: string :: npos )
tmpDirectoryPath = tmpDirectoryPath . substr ( startPosition );
}
if ( ! PHYSFS_setWriteDir ( tmpWritePath . c_str ()))
{
printf ( "Failed to set write dir to %s \n " , tmpWritePath . c_str ());
2022-08-04 02:50:37 +02:00
RenderD7 :: AddOvl ( std :: make_unique < RenderD7 :: Toast > ( "PHYSFS-Error" , RenderD7 :: FormatString ( "Failed to set write dir to %s \n " , tmpWritePath . c_str ())));
2022-08-04 01:13:26 +02:00
return false ;
}
if ( ! RenderD7 :: FileSystem :: CreateDirectory ( tmpDirectoryPath . c_str ()))
{
printf ( "Failed to create dir %s \n " , tmpDirectoryPath . c_str ());
/* clear the write directory in case of error */
2022-08-04 02:50:37 +02:00
RenderD7 :: AddOvl ( std :: make_unique < RenderD7 :: Toast > ( "PHYSFS-Error" , RenderD7 :: FormatString ( "Failed to create dir %s \n " , tmpDirectoryPath . c_str ())));
2022-08-04 01:13:26 +02:00
PHYSFS_setWriteDir ( nullptr );
return false ;
}
if ( ! PHYSFS_setWriteDir ( savePath . c_str ()))
{
printf ( "Failed to set write dir to %s \n " , savePath . c_str ());
2022-08-04 02:50:37 +02:00
RenderD7 :: AddOvl ( std :: make_unique < RenderD7 :: Toast > ( "PHYSFS-Error" , RenderD7 :: FormatString ( "Failed to set write dir to %s \n " , savePath . c_str ())));
2022-08-04 01:13:26 +02:00
return false ;
}
if ( ! PHYSFS_mount ( savePath . c_str (), nullptr , 0 ))
{
printf ( "Failed to mount write dir (%s) \n " , RenderD7 :: FileSystem :: GetPhysfsError ());
2022-08-04 02:50:37 +02:00
RenderD7 :: AddOvl ( std :: make_unique < RenderD7 :: Toast > ( "PHYSFS-Error" , RenderD7 :: FormatString ( "Failed to mount write dir (%s) \n " , RenderD7 :: FileSystem :: GetPhysfsError ())));
2022-08-04 01:13:26 +02:00
/* clear the write directory in case of error */
PHYSFS_setWriteDir ( nullptr );
return false ;
}
return true ;
}
std :: string RenderD7 :: FileSystem :: GetUserDirectory ()
{
return RenderD7 :: FileSystem :: Normalize ( PHYSFS_getPrefDir ( "npi-d7" , "renderd7" ));
}
bool RenderD7 :: FileSystem :: GetInfo ( const char * filename , RenderD7 :: FileSystem :: Info & info )
{
if ( ! PHYSFS_isInit ())
2022-08-04 02:50:37 +02:00
RenderD7 :: AddOvl ( std :: make_unique < RenderD7 :: Toast > ( "PHYSFS-Error" , RenderD7 :: FileSystem :: GetPhysfsError ()));
2022-08-04 01:13:26 +02:00
return false ;
PHYSFS_Stat stat = {};
if ( ! PHYSFS_stat ( filename , & stat ))
2022-08-04 02:50:37 +02:00
RenderD7 :: AddOvl ( std :: make_unique < RenderD7 :: Toast > ( "PHYSFS-Error" , RenderD7 :: FileSystem :: GetPhysfsError ()));
2022-08-04 01:13:26 +02:00
return false ;
info . mod_time = std :: min < int64_t > ( stat . modtime , RenderD7 :: FileSystem :: MAX_STAMP );
info . size = std :: min < int64_t > ( stat . filesize , RenderD7 :: FileSystem :: MAX_STAMP );
if ( stat . filetype == PHYSFS_FILETYPE_REGULAR )
info . type = RenderD7 :: FileSystem :: FileType_File ;
else if ( stat . filetype == PHYSFS_FILETYPE_DIRECTORY )
info . type = RenderD7 :: FileSystem :: FileType_Directory ;
else if ( stat . filetype == PHYSFS_FILETYPE_SYMLINK )
info . type = RenderD7 :: FileSystem :: FileType_SymLink ;
else
info . type = RenderD7 :: FileSystem :: FileType_Other ;
return true ;
}
void RenderD7 :: FileSystem :: GetDirectoryItems ( const char * path , std :: vector < std :: string >& items )
{
if ( ! PHYSFS_isInit ())
2022-08-04 02:50:37 +02:00
RenderD7 :: AddOvl ( std :: make_unique < RenderD7 :: Toast > ( "PHYSFS-Error" , RenderD7 :: FileSystem :: GetPhysfsError ()));
2022-08-04 01:13:26 +02:00
return ;
char ** results = PHYSFS_enumerateFiles ( path );
if ( results == nullptr )
2022-08-04 02:50:37 +02:00
RenderD7 :: AddOvl ( std :: make_unique < RenderD7 :: Toast > ( "PHYSFS-Error" , RenderD7 :: FileSystem :: GetPhysfsError ()));
2022-08-04 01:13:26 +02:00
return ;
for ( char ** item = results ; * item != 0 ; item ++ )
items . push_back ( * item );
PHYSFS_freeList ( results );
}
bool RenderD7 :: FileSystem :: OpenFile ( File & file , const char * name , FileMode mode )
{
if ( mode == FileMode_Closed )
2022-08-04 02:50:37 +02:00
RenderD7 :: AddOvl ( std :: make_unique < RenderD7 :: Toast > ( "PHYSFS-Error" , RenderD7 :: FileSystem :: GetPhysfsError ()));
2022-08-04 01:13:26 +02:00
return false ;
if ( ! PHYSFS_isInit ())
2022-08-04 02:50:37 +02:00
RenderD7 :: AddOvl ( std :: make_unique < RenderD7 :: Toast > ( "PHYSFS-Error" , RenderD7 :: FileSystem :: GetPhysfsError ()));
2022-08-04 01:13:26 +02:00
return false ;
if ( file . handle )
RenderD7 :: FileSystem :: CloseFile ( file );
if ( mode == FileMode_Read && ! PHYSFS_exists ( name ))
{
printf ( "Could not open file %s, does not exist. \n " , name );
2022-08-04 02:50:37 +02:00
RenderD7 :: AddOvl ( std :: make_unique < RenderD7 :: Toast > ( "PHYSFS-Error" , RenderD7 :: FormatString ( "Could not open file %s, does not exist. \n " , name )));
2022-08-04 01:13:26 +02:00
return false ;
}
if (( mode == FileMode_Write ) &&
( PHYSFS_getWriteDir () == nullptr && RenderD7 :: FileSystem :: SetupWriteDirectory ()))
{
printf ( "Could not set write directory. \n " );
2022-08-04 02:50:37 +02:00
RenderD7 :: AddOvl ( std :: make_unique < RenderD7 :: Toast > ( "PHYSFS-Error" , RenderD7 :: FormatString ( "Could not set write directory. \n " )));
2022-08-04 01:13:26 +02:00
return false ;
}
PHYSFS_getLastErrorCode ();
switch ( mode )
{
case FileMode_Read :
file . handle = PHYSFS_openRead ( name );
break ;
case FileMode_Write :
file . handle = PHYSFS_openWrite ( name );
break ;
default :
break ;
}
if ( ! file . handle )
{
const char * error = RenderD7 :: FileSystem :: GetPhysfsError ();
if ( error == nullptr )
error = "unknown error" ;
printf ( "Could not open file %s (%s) \n " , name , error );
2022-08-04 02:50:37 +02:00
RenderD7 :: AddOvl ( std :: make_unique < RenderD7 :: Toast > ( "PHYSFS-Error" , RenderD7 :: FormatString ( "Could not open file %s (%s) \n " , name , error )));
2022-08-04 01:13:26 +02:00
return false ;
}
file . mode = mode ;
return true ;
}
bool RenderD7 :: FileSystem :: CloseFile ( File & file )
{
if ( file . handle == nullptr || ! PHYSFS_close ( file . handle ))
return false ;
file . handle = nullptr ;
return true ;
}
bool RenderD7 :: FileSystem :: CreateDirectory ( const char * name )
{
if ( ! PHYSFS_isInit ())
2022-08-04 02:50:37 +02:00
RenderD7 :: AddOvl ( std :: make_unique < RenderD7 :: Toast > ( "PHYSFS-Error" , RenderD7 :: FileSystem :: GetPhysfsError ()));
2022-08-04 01:13:26 +02:00
return false ;
if ( PHYSFS_getWriteDir () == nullptr && ! RenderD7 :: FileSystem :: SetupWriteDirectory ())
2022-08-04 02:50:37 +02:00
RenderD7 :: AddOvl ( std :: make_unique < RenderD7 :: Toast > ( "PHYSFS-Error" , RenderD7 :: FileSystem :: GetPhysfsError ()));
2022-08-04 01:13:26 +02:00
return false ;
if ( ! PHYSFS_mkdir ( name ))
2022-08-04 02:50:37 +02:00
RenderD7 :: AddOvl ( std :: make_unique < RenderD7 :: Toast > ( "PHYSFS-Error" , RenderD7 :: FileSystem :: GetPhysfsError ()));
2022-08-04 01:13:26 +02:00
return false ;
return true ;
}
int64_t RenderD7 :: FileSystem :: ReadFile ( File & file , void * destination , int64_t size )
{
if ( ! file . handle || file . mode != FileMode_Read )
{
printf ( "File is not opened for reading. \n " );
2022-08-04 02:50:37 +02:00
RenderD7 :: AddOvl ( std :: make_unique < RenderD7 :: Toast > ( "PHYSFS-Error" , "File is not opened for reading. \n " ));
2022-08-04 01:13:26 +02:00
return 0 ;
}
if ( size > file . GetSize ())
size = file . GetSize ();
else if ( size < 0 )
{
printf ( "Invalid read size %lld \n " , size );
2022-08-04 02:50:37 +02:00
RenderD7 :: AddOvl ( std :: make_unique < RenderD7 :: Toast > ( "PHYSFS-Error" , RenderD7 :: FormatString ( "Invalid read size %lld \n " , size )));
2022-08-04 01:13:26 +02:00
return 0 ;
}
return PHYSFS_readBytes ( file . handle , destination , ( PHYSFS_uint64 ) size );
}
bool RenderD7 :: FileSystem :: WriteFile ( File & file , const void * data , int64_t size )
{
if ( ! file . handle || file . mode != FileMode_Write )
{
printf ( "File is not opened for writing. \n " );
2022-08-04 02:50:37 +02:00
RenderD7 :: AddOvl ( std :: make_unique < RenderD7 :: Toast > ( "PHYSFS-Error" , "File is not opened for writing. \n " ));
2022-08-04 01:13:26 +02:00
return false ;
}
int64_t written = PHYSFS_writeBytes ( file . handle , data , ( PHYSFS_uint64 ) size );
2022-08-04 02:50:37 +02:00
if ( written != size ){
RenderD7 :: AddOvl ( std :: make_unique < RenderD7 :: Toast > ( "PHYSFS-Error" , RenderD7 :: FileSystem :: GetPhysfsError ()));
2022-08-04 01:13:26 +02:00
return false ;
2022-08-04 02:50:37 +02:00
}
2022-08-04 01:13:26 +02:00
return true ;
}