2020-09-19 08:07:53 +00:00
/*
* * file_grp . cpp
* *
* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* * Copyright 1998 - 2009 Randy Heit
* * Copyright 2005 - 2020 Christoph Oelckers
* * All rights reserved .
* *
* * Redistribution and use in source and binary forms , with or without
* * modification , are permitted provided that the following conditions
* * are met :
* *
* * 1. Redistributions of source code must retain the above copyright
* * notice , this list of conditions and the following disclaimer .
* * 2. Redistributions in binary form must reproduce the above copyright
* * notice , this list of conditions and the following disclaimer in the
* * documentation and / or other materials provided with the distribution .
* * 3. The name of the author may not be used to endorse or promote products
* * derived from this software without specific prior written permission .
* *
* * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ` ` AS IS ' ' AND ANY EXPRESS OR
* * IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES
* * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED .
* * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT , INDIRECT ,
* * INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT
* * NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
* * DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* * THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* * ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
* * THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* *
* *
*/
# include "resourcefile.h"
# include "printf.h"
//==========================================================================
//
// Build GRP file
//
//==========================================================================
class FSSIFile : public FUncompressedFile
{
public :
FSSIFile ( const char * filename , FileReader & file ) ;
bool Open ( bool quiet , int version , int lumpcount , LumpFilterInfo * filter ) ;
} ;
//==========================================================================
//
// Initializes a Build GRP file
//
//==========================================================================
FSSIFile : : FSSIFile ( const char * filename , FileReader & file )
: FUncompressedFile ( filename , file )
{
}
//==========================================================================
//
// Open it
// Note that SSIs can contain embedded GRPs which must be flagged accordingly.
//
//==========================================================================
bool FSSIFile : : Open ( bool quiet , int version , int lumpcount , LumpFilterInfo * )
{
NumLumps = lumpcount * 2 ;
Lumps . Resize ( lumpcount * 2 ) ;
int32_t j = ( version = = 2 ? 267 : 254 ) + ( lumpcount * 121 ) ;
2020-10-17 10:06:58 +00:00
for ( uint32_t i = 0 ; i < NumLumps ; i + = 2 )
2020-09-19 08:07:53 +00:00
{
char fn [ 13 ] ;
int strlength = Reader . ReadUInt8 ( ) ;
if ( strlength > 12 ) strlength = 12 ;
Reader . Read ( fn , 12 ) ;
fn [ strlength ] = 0 ;
int flength = Reader . ReadInt32 ( ) ;
Lumps [ i ] . LumpNameSetup ( fn ) ;
Lumps [ i ] . Position = j ;
Lumps [ i ] . LumpSize = flength ;
Lumps [ i ] . Owner = this ;
if ( strstr ( fn , " .GRP " ) ) Lumps [ i ] . Flags | = LUMPF_EMBEDDED ;
// SSI files can swap the order of the extension's characters - but there's no reliable detection for this and it can be mixed inside the same container,
// so we have no choice but to create another file record for the altered name.
std : : swap ( fn [ strlength - 1 ] , fn [ strlength - 3 ] ) ;
Lumps [ i + 1 ] . LumpNameSetup ( fn ) ;
Lumps [ i + 1 ] . Position = j ;
Lumps [ i + 1 ] . LumpSize = flength ;
Lumps [ i + 1 ] . Owner = this ;
if ( strstr ( fn , " .GRP " ) ) Lumps [ i + 1 ] . Flags | = LUMPF_EMBEDDED ;
j + = flength ;
Reader . Seek ( 104 , FileReader : : SeekCur ) ;
}
return true ;
}
//==========================================================================
//
// File open
//
//==========================================================================
FResourceFile * CheckSSI ( const char * filename , FileReader & file , bool quiet , LumpFilterInfo * filter )
{
char zerobuf [ 72 ] ;
char buf [ 72 ] ;
memset ( zerobuf , 0 , 72 ) ;
2020-10-17 10:06:58 +00:00
auto skipstring = [ & ] ( size_t length )
2020-09-19 08:07:53 +00:00
{
2020-10-17 10:06:58 +00:00
size_t strlength = file . ReadUInt8 ( ) ;
2020-09-19 08:07:53 +00:00
if ( strlength > length ) return false ;
2020-10-17 10:06:58 +00:00
size_t count = file . Read ( buf , length ) ;
2020-09-19 08:07:53 +00:00
buf [ length ] = 0 ;
if ( count ! = length | | strlen ( buf ) ! = strlength ) return false ;
if ( length ! = strlength & & memcmp ( buf + strlength , zerobuf , length - strlength ) ) return false ;
return true ;
} ;
if ( file . GetLength ( ) > = 12 )
{
// check if SSI
// this performs several checks because there is no "SSI" magic
int version = file . ReadInt32 ( ) ;
if ( version = = 1 | | version = = 2 ) // if
{
int numfiles = file . ReadInt32 ( ) ;
if ( ! skipstring ( 32 ) ) return nullptr ;
if ( version = = 2 & & ! skipstring ( 12 ) ) return nullptr ;
for ( int i = 0 ; i < 3 ; i + + )
{
if ( ! skipstring ( 70 ) ) return nullptr ;
}
auto ssi = new FSSIFile ( filename , file ) ;
if ( ssi - > Open ( filename , version , numfiles , filter ) ) return ssi ;
file = std : : move ( ssi - > Reader ) ; // to avoid destruction of reader
delete ssi ;
}
}
return nullptr ;
}