Files
source/Standard Gaming Platform/LibraryDataBase.cpp
T
lalien 0530b53b9c bug fixes from Overhaul:
- Data type changes 
- Templates removed

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@871 3b4a5df2-a311-0410-b5c6-a8a6f20db521
2007-05-09 13:16:37 +00:00

1125 lines
35 KiB
C++

#ifdef JA2_PRECOMPILED_HEADERS
#include "JA2 SGP ALL.H"
#elif defined( WIZ8_PRECOMPILED_HEADERS )
#include "WIZ8 SGP ALL.H"
#else
#include "Types.h"
#include "windows.h"
#include "FileMan.h"
#include "LibraryDataBase.h"
#include "MemMan.h"
#include "stdio.h"
#include "WCheck.h"
#include "Debug.h"
#if defined(JA2) || defined( UTIL )
#include "video.h"
#else
#include "video2.h"
#endif
#endif
//NUMBER_OF_LIBRARIES
#ifdef JA2
#include "Ja2 Libs.cpp"
#include "GameSettings.h"
#elif defined(UTIL)
LibraryInitHeader gGameLibaries[ ] = { 0 };
#else
// We link it as an .obj file
// #include "WizLibs.c"
#endif
//used when doing the binary search of the libraries
INT16 gsCurrentLibrary = -1;
//The location of the cdrom drive
CHAR8 gzCdDirectory[ SGPFILENAME_LEN ];
INT CompareFileNames( CHAR8 **arg1, FileHeaderStruct **arg2 );
BOOLEAN GetFileHeaderFromLibrary( INT16 sLibraryID, STR pstrFileName, FileHeaderStruct **pFileHeader );
void AddSlashToPath( STR pName );
HWFILE CreateLibraryFileHandle( INT16 sLibraryID, UINT32 uiFileNum );
BOOLEAN CheckIfFileIsAlreadyOpen( STR pFileName, INT16 sLibraryID );
INT32 CompareDirEntryFileNames( CHAR8 *arg1[], DIRENTRY **arg2 );
//************************************************************************
//
// InitializeFileDatabase(): Call this function to initialize the file
// database. It will use the gGameLibaries[] array for the list of libraries
// and the define NUMBER_OF_LIBRARIES for the number of libraries. The gGameLibaries
// array is an array of structure, one of the fields determines if the library
// will be initialized and game start.
//
//************************************************************************
BOOLEAN InitializeFileDatabase( )
{
INT16 i;
UINT32 uiSize;
BOOLEAN fLibraryInited = FALSE;
#ifdef JA2
GetCDLocation( );
#else
gzCdDirectory[ 0 ] = '.';
#endif
//if all the libraries exist, set them up
gFileDataBase.usNumberOfLibraries = NUMBER_OF_LIBRARIES;
//allocate memory for the each of the library headers
uiSize = NUMBER_OF_LIBRARIES * sizeof( LibraryHeaderStruct );
if( uiSize )
{
gFileDataBase.pLibraries = (LibraryHeaderStruct *) MemAlloc( uiSize );
CHECKF( gFileDataBase.pLibraries );
//set all the memrory to 0
memset( gFileDataBase.pLibraries, 0, uiSize );
//Load up each library
for( i=0; i< NUMBER_OF_LIBRARIES; i++ )
{
//if you want to init the library at the begining of the game
if( gGameLibaries[i].fInitOnStart )
{
//if the library exists
if( OpenLibrary( i ) )
fLibraryInited = TRUE;
//else the library doesnt exist
else
{
FastDebugMsg( String("Warning in InitializeFileDatabase( ): Library Id #%d (%s) is to be loaded but cannot be found.\n", i, gGameLibaries[i].sLibraryName ));
gFileDataBase.pLibraries[ i ].fLibraryOpen = FALSE;
}
}
}
//signify that the database has been initialized ( only if there was a library loaded )
gFileDataBase.fInitialized = fLibraryInited;
}
//allocate memory for the handles of the 'real files' that will be open
//This is needed because the the code wouldnt be able to tell the difference between a 'real' handle and a made up one
uiSize = INITIAL_NUM_HANDLES * sizeof( RealFileOpenStruct );
gFileDataBase.RealFiles.pRealFilesOpen = (RealFileOpenStruct *) MemAlloc( uiSize );
CHECKF( gFileDataBase.RealFiles.pRealFilesOpen );
//clear the memory
memset( gFileDataBase.RealFiles.pRealFilesOpen, 0, uiSize);
//set the initial number how many files can be opened at the one time
gFileDataBase.RealFiles.iSizeOfOpenFileArray = INITIAL_NUM_HANDLES;
return(TRUE);
}
//*****************************************************************************************
// ReopenCDLibraries
//
// Closes all CD libraries, then reopens them. This function needs to be called when CDs
// are changed.
//
// Returns BOOLEAN - TRUE, always
//
// Created: 3/21/00 Derek Beland
//*****************************************************************************************
BOOLEAN ReopenCDLibraries(void)
{
INT16 i;
//Load up each library
for(i=0; i < NUMBER_OF_LIBRARIES; i++ )
{
if(gFileDataBase.pLibraries[ i ].fLibraryOpen && gGameLibaries[i].fOnCDrom)
CloseLibrary(i);
if(gGameLibaries[i].fOnCDrom)
OpenLibrary( i );
}
return(TRUE);
}
//************************************************************************
//
// ShutDownFileDatabase(): Call this function to close down the file
// database.
//
//************************************************************************
BOOLEAN ShutDownFileDatabase( )
{
UINT16 sLoop1;
// Free up the memory used for each library
for(sLoop1=0; sLoop1 < gFileDataBase.usNumberOfLibraries; sLoop1++)
CloseLibrary( sLoop1 );
//Free up the memory used for all the library headers
if( gFileDataBase.pLibraries )
{
MemFree( gFileDataBase.pLibraries );
gFileDataBase.pLibraries = NULL;
}
//loop through all the 'opened files' ( there should be no files open )
for( sLoop1=0; sLoop1< gFileDataBase.RealFiles.iNumFilesOpen; sLoop1++)
{
FastDebugMsg( String("ShutDownFileDatabase( ): ERROR: real file id still exists, wasnt closed") );
CloseHandle( gFileDataBase.RealFiles.pRealFilesOpen[ sLoop1 ].hRealFileHandle );
}
//Free up the memory used for the real files array for the opened files
if( gFileDataBase.RealFiles.pRealFilesOpen )
{
MemFree( gFileDataBase.RealFiles.pRealFilesOpen );
gFileDataBase.RealFiles.pRealFilesOpen = NULL;
}
return( TRUE );
}
BOOLEAN CheckForLibraryExistence( STR pLibraryName )
{
BOOLEAN fRetVal = FALSE;
HANDLE hFile;
//try to opent the file, if we canm the library exists
hFile = CreateFile( pLibraryName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL );
//if the file was not opened
if( hFile == INVALID_HANDLE_VALUE )
{
//the file wasnt opened
fRetVal = FALSE;
}
else
{
CloseHandle( hFile );
fRetVal = TRUE;
}
return( fRetVal );
}
BOOLEAN InitializeLibrary( STR pLibraryName, LibraryHeaderStruct *pLibHeader, BOOLEAN fCanBeOnCDrom )
{
HANDLE hFile;
UINT16 usNumEntries=0;
UINT32 uiNumBytesRead;
UINT32 uiLoop;
DIRENTRY DirEntry;
LIBHEADER LibFileHeader;
UINT32 uiCount=0;
CHAR8 zTempPath[ SGPFILENAME_LEN ];
//open the library for reading ( if it exists )
hFile = CreateFile( pLibraryName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL );
if( hFile == INVALID_HANDLE_VALUE )
{
//if it failed finding the file on the hard drive, and the file can be on the cdrom
if( fCanBeOnCDrom )
{
// Add the path of the cdrom to the path of the library file
sprintf( zTempPath, "%s%s", gzCdDirectory, pLibraryName );
//look on the cdrom
hFile = CreateFile( zTempPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL );
if( hFile == INVALID_HANDLE_VALUE )
{
UINT32 uiLastError = GetLastError();
char zString[1024];
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, 0, uiLastError, 0, zString, 1024, NULL);
return( FALSE );
}
else
FastDebugMsg( String("CD Library %s opened.", zTempPath));
}
else
{
//error opening the library
return(FALSE);
}
}
// Read in the library header ( at the begining of the library )
if( !ReadFile( hFile, &LibFileHeader, sizeof( LIBHEADER ), (LPDWORD) &uiNumBytesRead, NULL ) )
return( FALSE );
if( uiNumBytesRead != sizeof( LIBHEADER ) )
{
//Error Reading the file database header.
return( FALSE );
}
//place the file pointer at the begining of the file headers ( they are at the end of the file )
SetFilePointer( hFile, -( LibFileHeader.iEntries * (INT32)sizeof(DIRENTRY) ), NULL, FILE_END );
//loop through the library and determine the number of files that are FILE_OK
//ie. so we dont load the old or deleted files
usNumEntries = 0;
for( uiLoop=0; uiLoop<(UINT32)LibFileHeader.iEntries; uiLoop++ )
{
//read in the file header
if( !ReadFile( hFile, &DirEntry, sizeof( DIRENTRY ), (LPDWORD) &uiNumBytesRead, NULL ) )
return( FALSE );
if( DirEntry.ubState == FILE_OK )
usNumEntries++;
}
//Allocate enough memory for the library header
pLibHeader->pFileHeader = (FileHeaderStruct *) MemAlloc( sizeof( FileHeaderStruct ) * usNumEntries );
#ifdef JA2TESTVERSION
pLibHeader->uiTotalMemoryAllocatedForLibrary = sizeof( FileHeaderStruct ) * usNumEntries;
#endif
//place the file pointer at the begining of the file headers ( they are at the end of the file )
SetFilePointer( hFile, -( LibFileHeader.iEntries * (INT32)sizeof(DIRENTRY) ), NULL, FILE_END );
//loop through all the entries
uiCount=0;
for( uiLoop=0; uiLoop<(UINT32)LibFileHeader.iEntries; uiLoop++ )
{
//read in the file header
if( !ReadFile( hFile, &DirEntry, sizeof( DIRENTRY ), (LPDWORD) &uiNumBytesRead, NULL ) )
return( FALSE );
if( DirEntry.ubState == FILE_OK )
{
//Check to see if the file is not longer then it should be
if( ( strlen( DirEntry.sFileName ) + 1 ) >= FILENAME_SIZE )
FastDebugMsg(String("\n*******InitializeLibrary(): Warning!: '%s' from the library '%s' has name whose size (%d) is bigger then it should be (%s)", DirEntry.sFileName, pLibHeader->sLibraryPath, ( strlen( DirEntry.sFileName ) + 1 ), FILENAME_SIZE ) );
//allocate memory for the files name
pLibHeader->pFileHeader[ uiCount ].pFileName = (STR) MemAlloc( strlen( DirEntry.sFileName ) + 1 );
//if we couldnt allocate memory
if( !pLibHeader->pFileHeader[ uiCount ].pFileName )
{
//report an error
return(FALSE);
}
#ifdef JA2TESTVERSION
pLibHeader->uiTotalMemoryAllocatedForLibrary += strlen( DirEntry.sFileName ) + 1;
#endif
//copy the file name, offset and length into the header
strcpy( pLibHeader->pFileHeader[ uiCount ].pFileName, DirEntry.sFileName);
pLibHeader->pFileHeader[ uiCount ].uiFileOffset = DirEntry.uiOffset;
pLibHeader->pFileHeader[ uiCount ].uiFileLength = DirEntry.uiLength;
uiCount++;
}
}
pLibHeader->usNumberOfEntries = usNumEntries;
//allocate memory for the library path
// if( strlen( LibFileHeader.sPathToLibrary ) == 0 )
{
// FastDebugMsg( String("The %s library file does not contain a path. Use 'n' argument to name the library when you create it\n", LibFileHeader.sLibName ) );
// Assert( 0 );
}
//if the library has a path
if( strlen( LibFileHeader.sPathToLibrary ) != 0 )
{
pLibHeader->sLibraryPath = (STR) MemAlloc( strlen( LibFileHeader.sPathToLibrary ) + 1 );
strcpy( pLibHeader->sLibraryPath, LibFileHeader.sPathToLibrary );
}
else
{
//else the library name does not contain a path ( most likely either an error or it is the default path )
pLibHeader->sLibraryPath = (STR) MemAlloc( 1 );
pLibHeader->sLibraryPath[0] = '\0';
}
#ifdef JA2TESTVERSION
pLibHeader->uiTotalMemoryAllocatedForLibrary += strlen( LibFileHeader.sPathToLibrary ) + 1;
#endif
//allocate space for the open files array
pLibHeader->pOpenFiles = (FileOpenStruct *) MemAlloc( INITIAL_NUM_HANDLES * sizeof( FileOpenStruct ) );
if( !pLibHeader->pOpenFiles )
{
//report an error
return(FALSE);
}
memset( pLibHeader->pOpenFiles, 0, INITIAL_NUM_HANDLES * sizeof( FileOpenStruct ) );
#ifdef JA2TESTVERSION
pLibHeader->uiTotalMemoryAllocatedForLibrary += INITIAL_NUM_HANDLES * sizeof( FileOpenStruct );
#endif
pLibHeader->hLibraryHandle = hFile;
pLibHeader->usNumberOfEntries = usNumEntries;
pLibHeader->fLibraryOpen = TRUE;
pLibHeader->iNumFilesOpen = 0;
pLibHeader->iSizeOfOpenFileArray = INITIAL_NUM_HANDLES;
return( TRUE );
}
BOOLEAN LoadDataFromLibrary( INT16 sLibraryID, UINT32 uiFileNum, PTR pData, UINT32 uiBytesToRead, UINT32 *pBytesRead )
{
UINT32 uiOffsetInLibrary, uiLength;
HANDLE hLibraryFile;
UINT32 uiNumBytesRead;
UINT32 uiCurPos;
//get the offset into the library, the length and current position of the file pointer.
uiOffsetInLibrary = gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles[ uiFileNum ].pFileHeader->uiFileOffset;
uiLength = gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles[ uiFileNum ].pFileHeader->uiFileLength;
hLibraryFile = gFileDataBase.pLibraries[ sLibraryID ].hLibraryHandle;
uiCurPos = gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles[ uiFileNum ].uiFilePosInFile;
//set the file pointer to the right location
SetFilePointer( hLibraryFile, ( uiOffsetInLibrary + uiCurPos ), NULL, FILE_BEGIN );
//if we are trying to read more data then the size of the file, return an error
if( uiBytesToRead + uiCurPos > uiLength )
{
*pBytesRead = 0;
return( FALSE );
}
//get the data
if( !ReadFile( hLibraryFile, pData, uiBytesToRead, (LPDWORD) &uiNumBytesRead, NULL ) )
return( FALSE );
if( uiBytesToRead != uiNumBytesRead )
{
// Gets the reason why the function failed
// UINT32 uiLastError = GetLastError();
// char zString[1024];
// FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, 0, uiLastError, 0, zString, 1024, NULL);
return( FALSE );
}
gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles[ uiFileNum ].uiFilePosInFile += uiNumBytesRead;
// CloseHandle( hLibraryFile );
*pBytesRead = uiNumBytesRead;
return( TRUE );
}
//************************************************************************
//
// CheckIfFileExistInLibrary() determines if a file exists in a library.
//
//************************************************************************
BOOLEAN CheckIfFileExistInLibrary( STR pFileName )
{
INT16 sLibraryID;
FileHeaderStruct *pFileHeader;
//get thelibrary that file is in
sLibraryID = GetLibraryIDFromFileName( pFileName );
if( sLibraryID == -1 )
{
//not in any library
return( FALSE );
}
if( GetFileHeaderFromLibrary( sLibraryID, pFileName, &pFileHeader ) )
return( TRUE );
else
return( FALSE );
}
//************************************************************************
//
// This function finds out if the file CAN be in a library. It determines
// if the library that the file MAY be in is open.
// ( eg. File is Laptop\Test.sti, if the Laptop\ library is open, it returns true
//
//************************************************************************
INT16 GetLibraryIDFromFileName( STR pFileName )
{
INT16 sLoop1, sBestMatch=-1;
//loop through all the libraries to check which library the file is in
for( sLoop1=0; sLoop1<gFileDataBase.usNumberOfLibraries; sLoop1++)
{
//if the library is not loaded, dont try to access the array
if( IsLibraryOpened( sLoop1 ) )
{
//if the library path name is of size zero, ( the library is for the default path )
if( strlen( gFileDataBase.pLibraries[ sLoop1 ].sLibraryPath ) == 0 )
{
//determine if there is a directory in the file name
if( strchr( pFileName, '\\' ) == NULL && strchr( pFileName, '//' ) == NULL )
{
//There is no directory in the file name
return( sLoop1 );
}
}
//compare the library name to the file name that is passed in
else
{
// if the directory paths are the same, to the length of the lib's path
if( _strnicmp( gFileDataBase.pLibraries[ sLoop1 ].sLibraryPath, pFileName, strlen( gFileDataBase.pLibraries[ sLoop1 ].sLibraryPath ) ) == 0 )
{
// if we've never matched, or this match's path is longer than the previous match (meaning it's more exact)
if((sBestMatch==(-1)) || (strlen(gFileDataBase.pLibraries[ sLoop1 ].sLibraryPath) > strlen(gFileDataBase.pLibraries[ sBestMatch ].sLibraryPath)))
sBestMatch = sLoop1;
}
}
}
}
//no library was found, return an error
return(sBestMatch);
}
//************************************************************************
//
// GetFileHeaderFromLibrary() performsperforms a binary search of the
// library. It adds the libraries path to the file in the
// library and then string compared that to the name that we are
// searching for.
//
//************************************************************************
BOOLEAN GetFileHeaderFromLibrary( INT16 sLibraryID, STR pstrFileName, FileHeaderStruct **pFileHeader )
{
FileHeaderStruct **ppFileHeader;
CHAR8 sFileNameWithPath[ FILENAME_SIZE ];
//combine the library path to the file name (need it for the search of the library )
strcpy( sFileNameWithPath, pstrFileName);
gsCurrentLibrary = sLibraryID;
/* try to find the filename using a binary search algorithm: */
ppFileHeader = (FileHeaderStruct **) bsearch( &sFileNameWithPath, (FileHeaderStruct *) gFileDataBase.pLibraries[ sLibraryID ].pFileHeader, gFileDataBase.pLibraries[ sLibraryID ].usNumberOfEntries,
sizeof( FileHeaderStruct ), (int (*)(const void*, const void*))CompareFileNames );
if( ppFileHeader )
{
*pFileHeader = ( FileHeaderStruct * ) ppFileHeader;
return( TRUE );
}
else
{
pFileHeader = NULL;
return( FALSE );
}
}
//************************************************************************
//
// CompareFileNames() gets called by the binary search function.
//
//************************************************************************
INT CompareFileNames( CHAR8 *arg1[], FileHeaderStruct **arg2 )
{
CHAR8 sSearchKey[ FILENAME_SIZE ];
CHAR8 sFileNameWithPath[ FILENAME_SIZE ];
FileHeaderStruct *TempFileHeader;
TempFileHeader = ( FileHeaderStruct * ) arg2;
sprintf( sSearchKey, "%s", arg1);
sprintf( sFileNameWithPath, "%s%s", gFileDataBase.pLibraries[ gsCurrentLibrary ].sLibraryPath, TempFileHeader->pFileName );
/* Compare all of both strings: */
return _stricmp( sSearchKey, sFileNameWithPath );
}
void AddSlashToPath( STR pName )
{
UINT32 uiLoop, uiCounter;
BOOLEAN fDone = FALSE;
BOOLEAN fFound = FALSE;
CHAR8 sNewName[ FILENAME_SIZE ];
//find out if there is a '\' in the file name
uiCounter=0;
for( uiLoop=0; uiLoop < strlen( pName ) && !fDone; uiLoop++)
{
if( pName[ uiLoop ] == '\\' )
{
sNewName[ uiCounter ] = pName[ uiLoop ];
uiCounter++;
sNewName[ uiCounter ] = '\\';
}
else
sNewName[ uiCounter ] = pName[ uiLoop ];
uiCounter++;
}
sNewName[ uiCounter ] = '\0';
strcpy( pName, sNewName );
}
//************************************************************************
//
// This function will see if a file is in a library. If it is, the file will be opened and a file
// handle will be created for it.
//
//************************************************************************
HWFILE OpenFileFromLibrary( STR pName )
{
FileHeaderStruct *pFileHeader;
HWFILE hLibFile;
INT16 sLibraryID;
UINT16 uiLoop1;
UINT32 uiFileNum=0;
UINT32 uiNewFilePosition=0;
//Check if the file can be contained from an open library ( the path to the file a library path )
sLibraryID = GetLibraryIDFromFileName( pName );
if( sLibraryID != -1 )
{
//Check if another file is already open in the library ( report a warning if so )
// if( gFileDataBase.pLibraries[ sLibraryID ].fAnotherFileAlreadyOpenedLibrary )
if( gFileDataBase.pLibraries[ sLibraryID ].uiIdOfOtherFileAlreadyOpenedLibrary != 0 )
{
// Temp removed
// FastDebugMsg(String("\n*******\nOpenFileFromLibrary(): Warning!: Trying to load file '%s' from the library '%s' which already has a file open\n", pName, gGameLibaries[ sLibraryID ].sLibraryName ) );
// FastDebugMsg(String("\n*******\nOpenFileFromLibrary(): Warning!: Trying to load file '%s' from the library '%s' which already has a file open ( file open is '%s')\n", pName, gGameLibaries[ sLibraryID ].sLibraryName, gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles[ gFileDataBase.pLibraries[ sLibraryID ].uiIdOfOtherFileAlreadyOpenedLibrary ].pFileHeader->pFileName ) );
}
//check if the file is already open
if( CheckIfFileIsAlreadyOpen( pName, sLibraryID ) )
return( 0 );
//if the file is in a library, get the file
if( GetFileHeaderFromLibrary( sLibraryID, pName, &pFileHeader ) )
{
//increment the number of open files
gFileDataBase.pLibraries[ sLibraryID ].iNumFilesOpen ++;
//if there isnt enough space to put the file, realloc more space
if( gFileDataBase.pLibraries[ sLibraryID ].iNumFilesOpen >= gFileDataBase.pLibraries[ sLibraryID ].iSizeOfOpenFileArray )
{
FileOpenStruct *pOpenFiles;
//reallocate more space for the array
pOpenFiles = (FileOpenStruct *) MemRealloc( gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles,
gFileDataBase.pLibraries[ sLibraryID ].iSizeOfOpenFileArray + NUM_FILES_TO_ADD_AT_A_TIME );
if( !pOpenFiles )
return( 0 );
//increment the number of open files that we can have open
gFileDataBase.pLibraries[ sLibraryID ].iSizeOfOpenFileArray += NUM_FILES_TO_ADD_AT_A_TIME;
gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles = pOpenFiles;
}
//loop through to find a new spot in the array
uiFileNum = 0;
for( uiLoop1=1; uiLoop1 < gFileDataBase.pLibraries[ sLibraryID ].iSizeOfOpenFileArray; uiLoop1++)
{
if( gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles[ uiLoop1 ].uiFileID == 0 )
{
uiFileNum = uiLoop1;
break;
}
}
//if for some reason we couldnt find a spot, return an error
if( uiFileNum == 0 )
return( 0 );
//Create a library handle for the new file
hLibFile = CreateLibraryFileHandle( sLibraryID, uiFileNum );
//Set the current file data into the array of open files
gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles[ uiFileNum ].uiFileID = hLibFile;
gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles[ uiFileNum ].uiFilePosInFile = 0;
gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles[ uiFileNum ].pFileHeader = pFileHeader;
//Save the current file position in the library
gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles[ uiFileNum ].uiActualPositionInLibrary = SetFilePointer( gFileDataBase.pLibraries[ sLibraryID ].hLibraryHandle, 0, NULL, FILE_CURRENT );
//Set the file position in the library to the begining of the 'file' in the library
uiNewFilePosition = SetFilePointer( gFileDataBase.pLibraries[ sLibraryID ].hLibraryHandle, gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles[ uiFileNum ].pFileHeader->uiFileOffset, NULL, FILE_BEGIN );
uiNewFilePosition = GetFileSize( gFileDataBase.pLibraries[ sLibraryID ].hLibraryHandle, NULL );
}
else
{
// Failed to find the file in a library
return( 0 );
}
}
else
{
// Library is not open, or doesnt exist
return( 0 );
}
//Set the fact the a file is currently open in the library
// gFileDataBase.pLibraries[ sLibraryID ].fAnotherFileAlreadyOpenedLibrary = TRUE;
gFileDataBase.pLibraries[ sLibraryID ].uiIdOfOtherFileAlreadyOpenedLibrary = uiFileNum;
return( hLibFile );
}
HWFILE CreateLibraryFileHandle( INT16 sLibraryID, UINT32 uiFileNum )
{
HWFILE hLibFile;
hLibFile = uiFileNum;
hLibFile |= DB_ADD_LIBRARY_ID( sLibraryID );
return( hLibFile );
}
HWFILE CreateRealFileHandle( HANDLE hFile )
{
HWFILE hLibFile;
INT32 iLoop1;
UINT32 uiFileNum=0;
UINT32 uiSize;
//if there isnt enough space to put the file, realloc more space
if( gFileDataBase.RealFiles.iNumFilesOpen >= ( gFileDataBase.RealFiles.iSizeOfOpenFileArray -1 ) )
{
uiSize = ( gFileDataBase.RealFiles.iSizeOfOpenFileArray + NUM_FILES_TO_ADD_AT_A_TIME ) * sizeof( RealFileOpenStruct );
gFileDataBase.RealFiles.pRealFilesOpen = (RealFileOpenStruct *) MemRealloc( gFileDataBase.RealFiles.pRealFilesOpen, uiSize );
CHECKF( gFileDataBase.RealFiles.pRealFilesOpen );
//Clear out the new part of the array
memset( &gFileDataBase.RealFiles.pRealFilesOpen[ gFileDataBase.RealFiles.iSizeOfOpenFileArray ], 0, ( NUM_FILES_TO_ADD_AT_A_TIME * sizeof( RealFileOpenStruct ) ) );
gFileDataBase.RealFiles.iSizeOfOpenFileArray += NUM_FILES_TO_ADD_AT_A_TIME;
}
//loop through to find a new spot in the array
uiFileNum = 0;
for( iLoop1=1; iLoop1 < gFileDataBase.RealFiles.iSizeOfOpenFileArray; iLoop1++)
{
if( gFileDataBase.RealFiles.pRealFilesOpen[ iLoop1 ].uiFileID == 0 )
{
uiFileNum = iLoop1;
break;
}
}
//if for some reason we couldnt find a spot, return an error
if( uiFileNum == 0 )
return( 0 );
hLibFile = uiFileNum;
hLibFile |= DB_ADD_LIBRARY_ID( REAL_FILE_LIBRARY_ID );
gFileDataBase.RealFiles.pRealFilesOpen[ iLoop1 ].uiFileID = hLibFile;
gFileDataBase.RealFiles.pRealFilesOpen[ iLoop1 ].hRealFileHandle = hFile;
gFileDataBase.RealFiles.iNumFilesOpen++;
return( hLibFile );
}
BOOLEAN GetLibraryAndFileIDFromLibraryFileHandle( HWFILE hlibFile, INT16 *pLibraryID, UINT32 *pFileNum )
{
*pFileNum = DB_EXTRACT_FILE_ID( hlibFile );
*pLibraryID = (UINT16)DB_EXTRACT_LIBRARY( hlibFile );
//TEST: qq
/* if( *pLibraryID == LIBRARY_SOUNDS )
{
int q=5;
}
*/
return( TRUE );
}
//************************************************************************
//
// Close an individual file that is contained in the library
//
//************************************************************************
BOOLEAN CloseLibraryFile( INT16 sLibraryID, UINT32 uiFileID )
{
if( IsLibraryOpened( sLibraryID ) )
{
//if the uiFileID is invalid
if( (uiFileID >= (UINT32)gFileDataBase.pLibraries[ sLibraryID ].iSizeOfOpenFileArray ) )
return( FALSE );
//if the file is not opened, dont close it
if( gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles[ uiFileID ].uiFileID != 0 )
{
//reset the variables
gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles[ uiFileID ].uiFileID = 0;
gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles[ uiFileID ].uiFilePosInFile = 0;
gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles[ uiFileID ].pFileHeader = NULL;
//reset the libraries file pointer to the positon it was in prior to opening the current file
SetFilePointer( gFileDataBase.pLibraries[ sLibraryID ].hLibraryHandle, gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles[ uiFileID ].uiActualPositionInLibrary, NULL, FILE_CURRENT);
//decrement the number of files that are open
gFileDataBase.pLibraries[ sLibraryID ].iNumFilesOpen--;
// Reset the fact that a file is accessing the library
// gFileDataBase.pLibraries[ sLibraryID ].fAnotherFileAlreadyOpenedLibrary = FALSE;
gFileDataBase.pLibraries[ sLibraryID ].uiIdOfOtherFileAlreadyOpenedLibrary = 0;
}
}
return( TRUE );
}
BOOLEAN LibraryFileSeek( INT16 sLibraryID, UINT32 uiFileNum, UINT32 uiDistance, UINT8 uiHowToSeek )
{
UINT32 uiCurPos, uiSize;
//if the library is not open, return an error
if( !IsLibraryOpened( sLibraryID ) )
return( FALSE );
uiCurPos = gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles[ uiFileNum ].uiFilePosInFile;
uiSize = gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles[ uiFileNum ].pFileHeader->uiFileLength;
if ( uiHowToSeek == FILE_SEEK_FROM_START )
uiCurPos = uiDistance;
else if ( uiHowToSeek == FILE_SEEK_FROM_END )
uiCurPos = uiSize - uiDistance;
else if ( uiHowToSeek == FILE_SEEK_FROM_CURRENT )
uiCurPos += uiDistance;
else
return(FALSE);
gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles[ uiFileNum ].uiFilePosInFile = uiCurPos;
return( TRUE );
}
//************************************************************************
//
// OpenLibrary() Opens a library from the 'array' of library names
// that was passd in at game initialization. Pass in an enum for the
// library.
//
//************************************************************************
BOOLEAN OpenLibrary( INT16 sLibraryID )
{
//if the library is already opened, report an error
if( gFileDataBase.pLibraries[ sLibraryID ].fLibraryOpen )
return( FALSE );
//if we are trying to do something with an invalid library id
if( sLibraryID >= gFileDataBase.usNumberOfLibraries )
return( FALSE );
//if we cant open the library
if( !InitializeLibrary( gGameLibaries[ sLibraryID ].sLibraryName, &gFileDataBase.pLibraries[ sLibraryID ], gGameLibaries[ sLibraryID ].fOnCDrom ) )
return( FALSE );
return( TRUE );
}
BOOLEAN CloseLibrary( INT16 sLibraryID )
{
UINT32 uiLoop1;
//if the library isnt loaded, dont close it
if( !IsLibraryOpened( sLibraryID ) )
return( FALSE );
#ifdef JA2TESTVERSION
FastDebugMsg( String("ShutDownFileDatabase( ): %d bytes of ram used for the Library #%3d, path '%s', in the File Database System\n", gFileDataBase.pLibraries[ sLibraryID ].uiTotalMemoryAllocatedForLibrary, sLibraryID, gFileDataBase.pLibraries[ sLibraryID ].sLibraryPath ));
gFileDataBase.pLibraries[ sLibraryID ].uiTotalMemoryAllocatedForLibrary = 0;
#endif
//if there are any open files, loop through the library and close down whatever file is still open
if( gFileDataBase.pLibraries[ sLibraryID ].iNumFilesOpen )
{
//loop though the array of open files to see if any are still open
for( uiLoop1=0; uiLoop1<( UINT32 )gFileDataBase.pLibraries[ sLibraryID ].usNumberOfEntries; uiLoop1++)
{
if( CheckIfFileIsAlreadyOpen( gFileDataBase.pLibraries[ sLibraryID ].pFileHeader[ uiLoop1 ].pFileName, sLibraryID ) )
{
FastDebugMsg( String("CloseLibrary(): ERROR: %s library file id still exists, wasnt closed, closing now.", gFileDataBase.pLibraries[ sLibraryID ].pFileHeader[ uiLoop1 ].pFileName ) );
CloseLibraryFile( sLibraryID, uiLoop1 );
// Removed because the memory gets freed in the next for loop. Would only enter here if files were still open
// gFileDataBase.pLibraries[ sLibraryID ].pFileHeader[ uiLoop1 ].pFileName = NULL;
}
}
}
//Free up the memory used for each file name
for( uiLoop1=0; uiLoop1<gFileDataBase.pLibraries[ sLibraryID ].usNumberOfEntries; uiLoop1++)
{
MemFree( gFileDataBase.pLibraries[ sLibraryID ].pFileHeader[ uiLoop1 ].pFileName );
gFileDataBase.pLibraries[ sLibraryID ].pFileHeader[ uiLoop1 ].pFileName = NULL;
}
//Free up the memory needed for the Library File Headers
if( gFileDataBase.pLibraries[ sLibraryID ].pFileHeader )
{
MemFree( gFileDataBase.pLibraries[ sLibraryID ].pFileHeader );
gFileDataBase.pLibraries[ sLibraryID ].pFileHeader = NULL;
}
//Free up the memory used for the library name
if( gFileDataBase.pLibraries[ sLibraryID ].sLibraryPath )
{
MemFree( gFileDataBase.pLibraries[ sLibraryID ].sLibraryPath );
gFileDataBase.pLibraries[ sLibraryID ].sLibraryPath = NULL;
}
//Free up the space requiered for the open files array
if( gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles )
{
MemFree( gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles );
gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles = NULL;
}
//set that the library isnt open
gFileDataBase.pLibraries[ sLibraryID ].fLibraryOpen = FALSE;
//close the file ( note libraries are to be closed by the Windows close function )
CloseHandle( gFileDataBase.pLibraries[ sLibraryID ].hLibraryHandle );
return( TRUE );
}
BOOLEAN IsLibraryOpened( INT16 sLibraryID )
{
//if the database is not initialized
if( !gFileDataBase.fInitialized )
return( FALSE );
//if we are trying to do something with an invalid library id
if( sLibraryID >= gFileDataBase.usNumberOfLibraries )
return( FALSE );
//if the library is opened
if( gFileDataBase.pLibraries[ sLibraryID ].fLibraryOpen )
return( TRUE );
else
return( FALSE );
}
BOOLEAN CheckIfFileIsAlreadyOpen( STR pFileName, INT16 sLibraryID )
{
UINT16 usLoop1=0;
CHAR8 sName[ 60 ];
CHAR8 sPath[ 90 ];
CHAR8 sDrive[ 60 ];
CHAR8 sExt[ 6 ];
CHAR8 sTempName[ 70 ];
_splitpath( pFileName, sDrive, sPath, sName, sExt);
strcpy( sTempName, sName );
strcat( sTempName, sExt );
//loop through all the open files to see if 'new' file to open is already open
for( usLoop1=1; usLoop1 < gFileDataBase.pLibraries[ sLibraryID ].iSizeOfOpenFileArray ; usLoop1++ )
{
//check if the file is open
if( gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles[ usLoop1].uiFileID != 0 )
{
//Check if the file already exists
if( _stricmp( sTempName, gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles[ usLoop1].pFileHeader->pFileName ) == 0 )
return( TRUE );
}
}
return( FALSE );
}
BOOLEAN GetLibraryFileTime( INT16 sLibraryID, UINT32 uiFileNum, SGP_FILETIME *pLastWriteTime )
{
UINT16 usNumEntries=0;
UINT32 uiNumBytesRead;
DIRENTRY *pDirEntry;
LIBHEADER LibFileHeader;
BOOLEAN fDone = FALSE;
// UINT32 cnt;
INT32 iFilePos=0;
DIRENTRY **ppDirEntry;
DIRENTRY *pAllEntries;
memset( pLastWriteTime, 0, sizeof( SGP_FILETIME ) );
SetFilePointer( gFileDataBase.pLibraries[ sLibraryID ].hLibraryHandle, 0, NULL, FILE_BEGIN );
// Read in the library header ( at the begining of the library )
if( !ReadFile( gFileDataBase.pLibraries[ sLibraryID ].hLibraryHandle, &LibFileHeader, sizeof( LIBHEADER ), (LPDWORD) &uiNumBytesRead, NULL ) )
return( FALSE );
if( uiNumBytesRead != sizeof( LIBHEADER ) )
{
//Error Reading the file database header.
return( FALSE );
}
//If the file number is greater then the number in the lirary, return false
if( uiFileNum >= (UINT32)LibFileHeader.iEntries )
return( FALSE );
pAllEntries = (DIRENTRY *) MemAlloc( sizeof( DIRENTRY ) * LibFileHeader.iEntries );
if( pAllEntries == NULL )
return( FALSE );
memset( pAllEntries, 0, sizeof( DIRENTRY ) );
iFilePos = -( LibFileHeader.iEntries * (INT32)sizeof(DIRENTRY) );
//set the file pointer to the right location
SetFilePointer( gFileDataBase.pLibraries[ sLibraryID ].hLibraryHandle, iFilePos, NULL, FILE_END );
// Read in the library header ( at the begining of the library )
if( !ReadFile( gFileDataBase.pLibraries[ sLibraryID ].hLibraryHandle, pAllEntries, ( sizeof( DIRENTRY ) * LibFileHeader.iEntries ), (LPDWORD) &uiNumBytesRead, NULL ) )
return( FALSE );
if( uiNumBytesRead != ( sizeof( DIRENTRY ) * LibFileHeader.iEntries ) )
{
//Error Reading the file database header.
return( FALSE );
}
/* try to find the filename using a binary search algorithm: */
ppDirEntry = (DIRENTRY **) bsearch( gFileDataBase.pLibraries[ sLibraryID ].pOpenFiles[ uiFileNum ].pFileHeader->pFileName,
(DIRENTRY *) pAllEntries,
LibFileHeader.iEntries,
sizeof( DIRENTRY ), (int (*)(const void*, const void*))CompareDirEntryFileNames );
if( ppDirEntry )
pDirEntry = ( DIRENTRY * ) ppDirEntry;
else
return( FALSE );
//Copy the dir entry time over to the passed in time
memcpy( pLastWriteTime, &pDirEntry->sFileTime, sizeof( SGP_FILETIME ) );
MemFree( pAllEntries );
pAllEntries = NULL;
return( TRUE );
}
//************************************************************************
//
// CompareFileNames() gets called by the binary search function.
//
//************************************************************************
INT32 CompareDirEntryFileNames( CHAR8 *arg1[], DIRENTRY **arg2 )
{
CHAR8 sSearchKey[ FILENAME_SIZE ];
CHAR8 sFileNameWithPath[ FILENAME_SIZE ];
DIRENTRY *TempDirEntry;
TempDirEntry = ( DIRENTRY * ) arg2;
sprintf( sSearchKey, "%s", arg1);
sprintf( sFileNameWithPath, "%s", TempDirEntry->sFileName );
/* Compare all of both strings: */
return _stricmp( sSearchKey, sFileNameWithPath );
}