mirror of
https://github.com/thug1src/thug.git
synced 2024-12-03 13:26:47 +00:00
320 lines
7.2 KiB
C++
320 lines
7.2 KiB
C++
|
/* Header file functionality...
|
||
|
.Hed files that describe the contents of .Wad files
|
||
|
Written by Ken, stolen by Matt*/
|
||
|
//#include <eetypes.h>
|
||
|
//#include <eekernel.h>
|
||
|
//#include <stdio.h>
|
||
|
//#include <sifdev.h>
|
||
|
//#include <libsdr.h>
|
||
|
//#include <sdrcmd.h>
|
||
|
//#include <sdmacro.h>
|
||
|
//#include <string.h>
|
||
|
//#include <ctype.h>
|
||
|
//#include <sif.h>
|
||
|
//#include <sifrpc.h>
|
||
|
//
|
||
|
//#include <libcdvd.h>
|
||
|
|
||
|
#include <core/macros.h>
|
||
|
#include <core/defines.h>
|
||
|
|
||
|
#include <gel/scripting/script.h>
|
||
|
|
||
|
#include <sys/file/filesys.h>
|
||
|
#include <sys/file/ngc/hed.h>
|
||
|
#include <sys/ngc/p_file.h>
|
||
|
|
||
|
bool sLoadingHed = false;
|
||
|
|
||
|
namespace File
|
||
|
{
|
||
|
|
||
|
static void get_checksums( const char * p_name, uint32 * p_dir, uint32 * p_file )
|
||
|
{
|
||
|
char name[128];
|
||
|
char dir[128];
|
||
|
char file[128];
|
||
|
uint lp;
|
||
|
|
||
|
// Convert / to \\.
|
||
|
for ( lp = 0; lp <= strlen( p_name ); lp++ )
|
||
|
{
|
||
|
name[lp] = p_name[lp];
|
||
|
if ( name[lp] == '/' ) name[lp] = '\\';
|
||
|
}
|
||
|
|
||
|
// Find the directory name and the filename.
|
||
|
for ( lp = strlen( name ) - 1; lp >= 0; lp-- )
|
||
|
{
|
||
|
if ( name[lp] == '\\' )
|
||
|
{
|
||
|
// Found the directory end.
|
||
|
strcpy( file, &name[lp+1] );
|
||
|
name[lp] = '\0';
|
||
|
strcpy( dir, name );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Chop off the extension (if it exists).
|
||
|
if ( file[strlen(file)-4] == '.' )
|
||
|
{
|
||
|
file[strlen(file)-4] = '\0';
|
||
|
}
|
||
|
|
||
|
// Create checksums.
|
||
|
if ( p_dir ) *p_dir = Script::GenerateCRC( dir );
|
||
|
if ( p_file ) *p_file = Script::GenerateCRC( file );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// Searches the hed file for the filename. If not found, returns NULL.
|
||
|
SHedFile *FindFileInHed(const char *pFilename, SHed *pHed)
|
||
|
{
|
||
|
if ( sLoadingHed ) return NULL;
|
||
|
|
||
|
Dbg_MsgAssert(pFilename,("NULL pFilename"));
|
||
|
Dbg_MsgAssert(pHed,("NULL pHed"));
|
||
|
|
||
|
uint32 check_dir;
|
||
|
uint32 check_file;
|
||
|
|
||
|
get_checksums( pFilename, &check_dir, &check_file );
|
||
|
|
||
|
SHed *pHd=pHed;
|
||
|
while ( pHd->numFiles != 0xffffffff )
|
||
|
{
|
||
|
if ( pHd->Checksum == check_dir )
|
||
|
{
|
||
|
SHedFile * pF = pHd->p_fileList;
|
||
|
for ( uint lp2 = 0; lp2 < pHd->numFiles; lp2++ )
|
||
|
{
|
||
|
if ( pF->Checksum == check_file )
|
||
|
{
|
||
|
return pF;
|
||
|
}
|
||
|
pF++;
|
||
|
}
|
||
|
}
|
||
|
pHd++;
|
||
|
}
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
// Searches the hed file for the filename with the same checksum. If not found, returns NULL.
|
||
|
SHedFile *FindFileInHedUsingChecksum( uint32 checksum, SHed *pHed )
|
||
|
{
|
||
|
if ( sLoadingHed ) return NULL;
|
||
|
|
||
|
Dbg_MsgAssert(pHed,("NULL pHed"));
|
||
|
|
||
|
SHed *pHd=pHed;
|
||
|
while ( pHd->numFiles != 0xffffffff )
|
||
|
{
|
||
|
SHedFile * pF = pHd->p_fileList;
|
||
|
for ( uint lp2 = 0; lp2 < pHd->numFiles; lp2++ )
|
||
|
{
|
||
|
if ( pF->Checksum == checksum )
|
||
|
{
|
||
|
return pF;
|
||
|
}
|
||
|
pF++;
|
||
|
}
|
||
|
pHd++;
|
||
|
}
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
//#ifdef __NOPT_CDROM__
|
||
|
//
|
||
|
//extern void StopStreaming( void );
|
||
|
//
|
||
|
//SHed *LoadHed( const char *filename )
|
||
|
//{
|
||
|
// NsFile file;
|
||
|
// SHed *pHed = NULL;
|
||
|
//// int HedId=-1;
|
||
|
// char hedFileName[255];
|
||
|
// char uppercaseFilename[ 255 ];
|
||
|
// int sL = strlen( filename );
|
||
|
// Dbg_MsgAssert( sL < 255,( "Filename %s too long", filename ));
|
||
|
// int i;
|
||
|
// for ( i = 0; i < sL; i++ )
|
||
|
// {
|
||
|
// uppercaseFilename[ i ] = toupper( filename[ i ] );
|
||
|
// }
|
||
|
// uppercaseFilename[ i ] = '\0';
|
||
|
// StopStreaming( );
|
||
|
// sprintf( hedFileName, "cdrom0:\\%s.HED;1", uppercaseFilename );
|
||
|
// while (HedId<0)
|
||
|
// {
|
||
|
// file.open( hedFileName );
|
||
|
//// HedId=sceOpen( hedFileName, SCE_RDONLY );
|
||
|
// if (HedId<0)
|
||
|
// {
|
||
|
// printf("Retrying opening %s\n", hedFileName );
|
||
|
// }
|
||
|
// }
|
||
|
// printf("%s opened successfully\n", uppercaseFilename );
|
||
|
//// long HedSize=sceLseek(HedId, 0, SCE_SEEK_END);
|
||
|
// long HedSize=file.size();
|
||
|
//
|
||
|
// Dbg_MsgAssert(pHed==NULL,("pHed not NULL ?"));
|
||
|
// pHed=(SHed*)Mem::Malloc((HedSize+2047)&~2047);
|
||
|
//
|
||
|
///*
|
||
|
// char *p = (char*) pHed;
|
||
|
// // Hmmm.....
|
||
|
// for (int i=0 ;i < (HedSize+2047)&~2047;i++)
|
||
|
// {
|
||
|
// p[i] = 0x55;
|
||
|
// }
|
||
|
//*/
|
||
|
//
|
||
|
//// sceLseek(HedId, 0, SCE_SEEK_SET);
|
||
|
//// sceRead(HedId,pHed,HedSize);
|
||
|
//// sceClose(HedId);
|
||
|
// file.read( pHed,, HedSize );
|
||
|
// file.close();
|
||
|
// return ( pHed );
|
||
|
// return ( NULL );
|
||
|
//}
|
||
|
//#else
|
||
|
//
|
||
|
SHed *LoadHed( const char *filename )
|
||
|
{
|
||
|
sLoadingHed = true;
|
||
|
|
||
|
int lp;
|
||
|
char tempFileName[255];
|
||
|
sprintf( tempFileName, "%sNGC.HED", filename );
|
||
|
|
||
|
void *fp = File::Open( tempFileName, "rb" );
|
||
|
|
||
|
int fileSize = File::GetFileSize( fp );
|
||
|
|
||
|
uint32 *pHed = (uint32 *)new (Mem::Manager::sHandle().TopDownHeap()) uint8[fileSize];
|
||
|
Dbg_MsgAssert( pHed,( "Failed to allocate memory for hed %s", tempFileName ));
|
||
|
|
||
|
File::Read( pHed, 1, fileSize, fp );
|
||
|
File::Close( fp );
|
||
|
|
||
|
// Convert to more compact list.
|
||
|
int files = 0;
|
||
|
int dirs = 0;
|
||
|
|
||
|
// First, count how many files we have.
|
||
|
uint32 * p32 = pHed;
|
||
|
while ( p32[0] != 0xffffffff )
|
||
|
{
|
||
|
files++;
|
||
|
|
||
|
// Byte order is reversed on NGC.
|
||
|
p32[0] = ( ( p32[0] >> 24 ) & 0xff ) | ( ( p32[0] >> 8 ) & 0xff00 ) | ( ( p32[0] << 8 ) & 0xff0000 ) | ( ( p32[0] << 24 ) & 0xff000000 );
|
||
|
p32[1] = ( ( p32[1] >> 24 ) & 0xff ) | ( ( p32[1] >> 8 ) & 0xff00 ) | ( ( p32[1] << 8 ) & 0xff0000 ) | ( ( p32[1] << 24 ) & 0xff000000 );
|
||
|
|
||
|
int len = strlen( (char *)&p32[2] ) + 1;
|
||
|
len = ( len + 3 ) & ~3;
|
||
|
p32 = (uint32*)(((int)&p32[2]) + len);
|
||
|
}
|
||
|
|
||
|
// Build list of checksums.
|
||
|
uint32 *p_offset = new (Mem::Manager::sHandle().TopDownHeap()) uint32[files];
|
||
|
uint32 *p_size = new (Mem::Manager::sHandle().TopDownHeap()) uint32[files];
|
||
|
uint32 *dir_check = new (Mem::Manager::sHandle().TopDownHeap()) uint32[files];
|
||
|
uint32 *file_check = new (Mem::Manager::sHandle().TopDownHeap()) uint32[files];
|
||
|
int count = 0;
|
||
|
p32 = pHed;
|
||
|
while ( p32[0] != 0xffffffff )
|
||
|
{
|
||
|
p_offset[count] = p32[0];
|
||
|
p_size[count] = p32[1];
|
||
|
get_checksums( (char *)&p32[2], &dir_check[count], &file_check[count] );
|
||
|
count++;
|
||
|
|
||
|
int len = strlen( (char *)&p32[2] ) + 1;
|
||
|
len = ( len + 3 ) & ~3;
|
||
|
p32 = (uint32*)(((int)&p32[2]) + len);
|
||
|
}
|
||
|
|
||
|
// Second, count how many directories we have.
|
||
|
for ( lp = 0; lp < files; lp++ )
|
||
|
{
|
||
|
bool unique = true;
|
||
|
for ( int lp2 = 0; lp2 < lp; lp2++ )
|
||
|
{
|
||
|
if ( dir_check[lp] == dir_check[lp2] )
|
||
|
{
|
||
|
unique = false;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if ( unique ) dirs++;
|
||
|
}
|
||
|
|
||
|
// Now, allocate final piece of memory.
|
||
|
int size = ( sizeof( SHed ) * ( dirs + 1 ) ) + ( sizeof( SHedFile ) * files );
|
||
|
SHed * p_hed = (SHed *)new uint8[size];
|
||
|
|
||
|
// Fill in directory entries.
|
||
|
int dirs_added = 0;
|
||
|
for ( lp = 0; lp < files; lp++ )
|
||
|
{
|
||
|
bool unique = true;
|
||
|
for ( int lp2 = 0; lp2 < dirs_added; lp2++ )
|
||
|
{
|
||
|
if ( p_hed[lp2].Checksum == dir_check[lp] )
|
||
|
{
|
||
|
unique = false;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if ( unique )
|
||
|
{
|
||
|
p_hed[dirs_added].Checksum = dir_check[lp];
|
||
|
dirs_added++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Fill in file entries.
|
||
|
SHedFile * p_hed_file = (SHedFile *)&p_hed[(dirs+1)];
|
||
|
for ( lp = 0; lp < dirs; lp++ )
|
||
|
{
|
||
|
p_hed[lp].p_fileList = p_hed_file;
|
||
|
int files_this_dir = 0;
|
||
|
for ( int lp2 = 0; lp2 < files; lp2++ )
|
||
|
{
|
||
|
if ( dir_check[lp2] == p_hed[lp].Checksum )
|
||
|
{
|
||
|
p_hed_file->Offset = p_offset[lp2];
|
||
|
p_hed_file->FileSize = p_size[lp2];
|
||
|
p_hed_file->Checksum = file_check[lp2];
|
||
|
files_this_dir++;
|
||
|
p_hed_file++;
|
||
|
}
|
||
|
}
|
||
|
p_hed[lp].numFiles = files_this_dir;
|
||
|
}
|
||
|
p_hed[dirs].numFiles = 0xffffffff;
|
||
|
|
||
|
// Get rid of temp data.
|
||
|
delete file_check;
|
||
|
delete dir_check;
|
||
|
delete p_size;
|
||
|
delete p_offset;
|
||
|
delete pHed;
|
||
|
|
||
|
sLoadingHed = false;
|
||
|
|
||
|
return p_hed;
|
||
|
}
|
||
|
//#endif
|
||
|
|
||
|
} // namespace File
|
||
|
|
||
|
|