mirror of
https://github.com/thug1src/thug.git
synced 2024-12-02 21:07:12 +00:00
592 lines
19 KiB
C++
592 lines
19 KiB
C++
|
/*****************************************************************************
|
||
|
** **
|
||
|
** Neversoft Entertainment **
|
||
|
** **
|
||
|
** Copyright (C) 1999 - All Rights Reserved **
|
||
|
** **
|
||
|
******************************************************************************
|
||
|
** **
|
||
|
** Project: System Library **
|
||
|
** **
|
||
|
** Module: File IO (File) **
|
||
|
** **
|
||
|
** File name: p_filesys.cpp **
|
||
|
** **
|
||
|
** Created by: 09/25/00 - dc **
|
||
|
** **
|
||
|
** Description: XBox File System **
|
||
|
** **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Includes **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
#include <xtl.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#include <core/defines.h>
|
||
|
#include <core/support.h>
|
||
|
#include <sys/file/filesys.h>
|
||
|
#include <sys/file/AsyncFilesys.h>
|
||
|
#include <sys/file/PRE.h>
|
||
|
#include <sys/file/xbox/p_streamer.h>
|
||
|
#include <sys/config/config.h>
|
||
|
|
||
|
#include <gfx/xbox/nx/nx_init.h>
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** DBG Information **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
namespace File
|
||
|
{
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Externals **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Defines **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
#define READBUFFERSIZE 10240
|
||
|
#define PREPEND_START_POS 8
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Private Types **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Private Data **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Public Data **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
BOOL OkayToUseUtilityDrive = FALSE;
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Private Prototypes **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Private Functions **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* prefopen */
|
||
|
/* Same as fopen() except it will prepend the data root directory */
|
||
|
/* For Xbox, path is always relative to location of .xbe image */
|
||
|
/* and default path from that location is d:\ */
|
||
|
/* So incoming files of the form: */
|
||
|
/* c:\skate3\data\foo... become d:\data\foo... */
|
||
|
/* foo... become d:\data\foo... */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
static void* prefopen( const char *filename, const char *mode )
|
||
|
{
|
||
|
// Used for prepending the root data directory on filesystem calls.
|
||
|
char nameConversionBuffer[256] = "d:\\data\\";
|
||
|
int index = PREPEND_START_POS;
|
||
|
const char* p_skip;
|
||
|
|
||
|
if(( filename[0] == 'c' ) && ( filename[1] == ':' ))
|
||
|
{
|
||
|
// Filename is of the form c:\skate4\data\foo...
|
||
|
p_skip = filename + 15;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Filename is of the form foo...
|
||
|
p_skip = filename;
|
||
|
}
|
||
|
|
||
|
while( nameConversionBuffer[index] = *p_skip )
|
||
|
{
|
||
|
// Switch forward slash directory separators to the supported backslash.
|
||
|
if( nameConversionBuffer[index] == '/' )
|
||
|
{
|
||
|
nameConversionBuffer[index] = '\\';
|
||
|
}
|
||
|
++index;
|
||
|
++p_skip;
|
||
|
}
|
||
|
nameConversionBuffer[index] = 0;
|
||
|
|
||
|
// If this is a .tex file, switch to a .txx file.
|
||
|
if((( nameConversionBuffer[index - 1] ) == 'x' ) &&
|
||
|
(( nameConversionBuffer[index - 2] ) == 'e' ) &&
|
||
|
(( nameConversionBuffer[index - 3] ) == 't' ))
|
||
|
{
|
||
|
nameConversionBuffer[index - 2] = 'x';
|
||
|
}
|
||
|
|
||
|
// If this is a .pre file, switch to a .prx file.
|
||
|
if(((( nameConversionBuffer[index - 1] ) == 'e' ) || (( nameConversionBuffer[index - 1] ) == 'x' )) &&
|
||
|
(( nameConversionBuffer[index - 2] ) == 'r' ) &&
|
||
|
(( nameConversionBuffer[index - 3] ) == 'p' ))
|
||
|
{
|
||
|
# ifdef __PAL_BUILD__
|
||
|
// Switch to a .prf, .prg or .prx file, depending on language.
|
||
|
switch( Config::GetLanguage())
|
||
|
{
|
||
|
case Config::LANGUAGE_FRENCH:
|
||
|
{
|
||
|
nameConversionBuffer[index - 1] = 'f';
|
||
|
break;
|
||
|
}
|
||
|
case Config::LANGUAGE_GERMAN:
|
||
|
{
|
||
|
nameConversionBuffer[index - 1] = 'g';
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
{
|
||
|
nameConversionBuffer[index - 1] = 'x';
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
# else
|
||
|
nameConversionBuffer[index - 1] = 'x';
|
||
|
# endif // __PLAT_BUILD__
|
||
|
}
|
||
|
|
||
|
// First we try reading the file from the utility partition (z:\) on the HD, rather than the DVD.
|
||
|
HANDLE h_file = INVALID_HANDLE_VALUE;
|
||
|
if( OkayToUseUtilityDrive )
|
||
|
{
|
||
|
nameConversionBuffer[0] = 'Z';
|
||
|
h_file = CreateFile( nameConversionBuffer, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
|
||
|
}
|
||
|
|
||
|
if( h_file == INVALID_HANDLE_VALUE )
|
||
|
{
|
||
|
// Not on the utility partition, so load it from the DVD.
|
||
|
nameConversionBuffer[0] = 'D';
|
||
|
h_file = CreateFile( nameConversionBuffer, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
|
||
|
|
||
|
// Deal with various error returns.
|
||
|
if( h_file == INVALID_HANDLE_VALUE )
|
||
|
{
|
||
|
DWORD error = GetLastError();
|
||
|
|
||
|
// Need to exclude this error from the test, since screenshot and other code sometimes check to see if a file exists, and it
|
||
|
// is valid to just return the error code if it doesn't.
|
||
|
if( error != ERROR_FILE_NOT_FOUND )
|
||
|
{
|
||
|
// Catch-all error indicating a fatal problem. Can't continue at this point.
|
||
|
// The ideal solution would be a catch/throw exception mechanism, but we don't include exception handling at the moment.
|
||
|
// For now just call this NxXbox function, which is slightly messy since it means we have to include a gfx\ file.
|
||
|
printf( "FatalFileError: %x %s\n", error, nameConversionBuffer );
|
||
|
NxXbox::FatalFileError((uint32)INVALID_HANDLE_VALUE );
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// All is well.
|
||
|
return h_file;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return h_file;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Public Functions **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
static CThreadedLevelLoader *pLoader;
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
void InstallFileSystem( void )
|
||
|
{
|
||
|
# if 0
|
||
|
// This is where we start the thread that will deal with copying commonly used data from the DVD to the utility
|
||
|
// region (z:\) on the HD.
|
||
|
pLoader = new CThreadedLevelLoader();
|
||
|
|
||
|
SLevelDesc level_descs[] = {{ "pre\\alc.prx" },
|
||
|
{ "pre\\alccol.prx" },
|
||
|
{ "pre\\alcscn.prx" },
|
||
|
{ "pre\\anims.prx" },
|
||
|
{ "pre\\bits.prx" },
|
||
|
{ "pre\\cnv.prx" },
|
||
|
{ "pre\\cnvcol.prx" },
|
||
|
{ "pre\\cnvscn.prx" },
|
||
|
{ "pre\\fonts.prx" },
|
||
|
{ "pre\\jnk.prx" },
|
||
|
{ "pre\\jnkcol.prx" },
|
||
|
{ "pre\\jnkscn.prx" },
|
||
|
{ "pre\\kon.prx" },
|
||
|
{ "pre\\koncol.prx" },
|
||
|
{ "pre\\konscn.prx" },
|
||
|
{ "pre\\lon.prx" },
|
||
|
{ "pre\\loncol.prx" },
|
||
|
{ "pre\\lonscn.prx" },
|
||
|
{ "pre\\qb.prx" },
|
||
|
{ "pre\\sch.prx" },
|
||
|
{ "pre\\schcol.prx" },
|
||
|
{ "pre\\schscn.prx" },
|
||
|
{ "pre\\sf2.prx" },
|
||
|
{ "pre\\sf2col.prx" },
|
||
|
{ "pre\\sf2scn.prx" },
|
||
|
{ "pre\\skaterparts.prx" },
|
||
|
{ "pre\\skater_sounds.prx" },
|
||
|
{ "pre\\skateshop.prx" },
|
||
|
{ "pre\\skateshopcol.prx" },
|
||
|
{ "pre\\skateshopscn.prx" },
|
||
|
{ "pre\\skeletons.prx" },
|
||
|
{ "pre\\zoo.prx" },
|
||
|
{ "pre\\zoocol.prx" },
|
||
|
{ "pre\\zooscn.prx" }};
|
||
|
|
||
|
static BYTE data_buffer[32 * 1024];
|
||
|
pLoader->Initialize( level_descs, 34, data_buffer, 32 * 1024, &OkayToUseUtilityDrive );
|
||
|
pLoader->AsyncStreamLevel( 0 );
|
||
|
# endif
|
||
|
|
||
|
// Initialise the async file system.
|
||
|
File::CAsyncFileLoader::sInit();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
long GetFileSize( void* pFP )
|
||
|
{
|
||
|
Dbg_MsgAssert( pFP, ( "NULL pFP sent to GetFileSize" ));
|
||
|
|
||
|
if( PreMgr::sPreEnabled())
|
||
|
{
|
||
|
int retval = PreMgr::pre_get_file_size( (PreFile::FileHandle *) pFP );
|
||
|
if( PreMgr::sPreExecuteSuccess())
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
LARGE_INTEGER li;
|
||
|
GetFileSizeEx((HANDLE)pFP, &li );
|
||
|
return (long)li.LowPart;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
long GetFilePosition( void *pFP )
|
||
|
{
|
||
|
Dbg_MsgAssert( pFP, ( "NULL pFP sent to GetFilePosition" ));
|
||
|
|
||
|
if( PreMgr::sPreEnabled())
|
||
|
{
|
||
|
int retval = PreMgr::pre_get_file_position((PreFile::FileHandle*)pFP );
|
||
|
if( PreMgr::sPreExecuteSuccess())
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
long pos = SetFilePointer( (HANDLE)pFP, // Handle to file
|
||
|
0, // Bytes to move pointer
|
||
|
0, // High bytes to move pointer
|
||
|
FILE_CURRENT ); // Starting point
|
||
|
return pos;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
void InitQuickFileSystem( void )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
uint32 CanFileBeLoadedQuickly( const char* filename )
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
bool LoadFileQuicklyPlease( const char* filename, uint8 *addr )
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
void StopStreaming( void )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
void UninstallFileSystem( void )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////
|
||
|
// Our versions of the ANSI file IO functions. They call
|
||
|
// the PreMgr first to see if the file is in a PRE file.
|
||
|
////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
bool Exist( const char *filename )
|
||
|
{
|
||
|
if (PreMgr::sPreEnabled())
|
||
|
{
|
||
|
bool retval = PreMgr::pre_fexist(filename);
|
||
|
if (PreMgr::sPreExecuteSuccess())
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
void *p_result = prefopen( filename, "rb" );
|
||
|
if( p_result != NULL )
|
||
|
{
|
||
|
Close( p_result );
|
||
|
}
|
||
|
|
||
|
return( p_result != NULL );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
void * Open( const char *filename, const char *access )
|
||
|
{
|
||
|
if (PreMgr::sPreEnabled())
|
||
|
{
|
||
|
void * retval = PreMgr::pre_fopen(filename, access);
|
||
|
if (PreMgr::sPreExecuteSuccess())
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
return prefopen( filename, access );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
int Close( void *pFP )
|
||
|
{
|
||
|
if (PreMgr::sPreEnabled())
|
||
|
{
|
||
|
int retval = PreMgr::pre_fclose((PreFile::FileHandle *) pFP);
|
||
|
if (PreMgr::sPreExecuteSuccess())
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
CloseHandle((HANDLE)pFP );
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
size_t Read( void *addr, size_t size, size_t count, void *pFP )
|
||
|
{
|
||
|
if (PreMgr::sPreEnabled())
|
||
|
{
|
||
|
size_t retval = PreMgr::pre_fread( addr, size, count, (PreFile::FileHandle*)pFP );
|
||
|
if( PreMgr::sPreExecuteSuccess())
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
DWORD bytes_read;
|
||
|
if( ReadFile((HANDLE)pFP, addr, size * count, &bytes_read, NULL ))
|
||
|
{
|
||
|
// All is well.
|
||
|
return bytes_read;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Read error.
|
||
|
DWORD last_error = GetLastError();
|
||
|
|
||
|
if( last_error == ERROR_HANDLE_EOF )
|
||
|
{
|
||
|
// Continue in this case.
|
||
|
return bytes_read;
|
||
|
}
|
||
|
|
||
|
NxXbox::FatalFileError( last_error );
|
||
|
return bytes_read;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* Read an Integer in little endian format. Just read it directly */
|
||
|
/* into memory... */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
size_t ReadInt( void *addr, void *pFP )
|
||
|
{
|
||
|
return Read( addr, 4, 1, pFP );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
size_t Write( const void *addr, size_t size, size_t count, void *pFP )
|
||
|
{
|
||
|
if (PreMgr::sPreEnabled())
|
||
|
{
|
||
|
size_t retval = PreMgr::pre_fwrite(addr, size, count, (PreFile::FileHandle *) pFP);
|
||
|
if (PreMgr::sPreExecuteSuccess())
|
||
|
return retval;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
char * GetS( char *buffer, int maxlen, void *pFP )
|
||
|
{
|
||
|
if (PreMgr::sPreEnabled())
|
||
|
{
|
||
|
char * retval = PreMgr::pre_fgets(buffer, maxlen, (PreFile::FileHandle *) pFP);
|
||
|
if (PreMgr::sPreExecuteSuccess())
|
||
|
return retval;
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
int PutS( const char *buffer, void *pFP )
|
||
|
{
|
||
|
if (PreMgr::sPreEnabled())
|
||
|
{
|
||
|
int retval = PreMgr::pre_fputs(buffer, (PreFile::FileHandle *) pFP);
|
||
|
if (PreMgr::sPreExecuteSuccess())
|
||
|
return retval;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
int Eof( void *pFP )
|
||
|
{
|
||
|
if (PreMgr::sPreEnabled())
|
||
|
{
|
||
|
int retval = PreMgr::pre_feof((PreFile::FileHandle *) pFP);
|
||
|
if (PreMgr::sPreExecuteSuccess())
|
||
|
return retval;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
int Seek( void *pFP, long offset, int origin )
|
||
|
{
|
||
|
if( PreMgr::sPreEnabled())
|
||
|
{
|
||
|
int retval = PreMgr::pre_fseek((PreFile::FileHandle *) pFP, offset, origin);
|
||
|
if( PreMgr::sPreExecuteSuccess())
|
||
|
return retval;
|
||
|
}
|
||
|
return SetFilePointer((HANDLE)pFP, offset, NULL, ( origin == SEEK_CUR ) ? FILE_CURRENT : (( origin == SEEK_SET ) ? FILE_BEGIN : FILE_END ));
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
int Flush( void *pFP )
|
||
|
{
|
||
|
if (PreMgr::sPreEnabled())
|
||
|
{
|
||
|
int retval = PreMgr::pre_fflush((PreFile::FileHandle *) pFP);
|
||
|
if (PreMgr::sPreExecuteSuccess())
|
||
|
return retval;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
} // namespace File
|
||
|
|
||
|
|