2007-05-30 21:56:52 +00:00
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers , whose names
* are too numerous to list here . Please refer to the COPYRIGHT
* file distributed with this source distribution .
2004-10-15 06:06:47 +00:00
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
2005-10-18 01:30:26 +00:00
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
2004-10-15 06:06:47 +00:00
*
2006-02-09 12:19:53 +00:00
* $ URL $
* $ Id $
2004-10-15 06:06:47 +00:00
*
*/
2007-09-19 08:40:12 +00:00
2006-07-15 20:30:36 +00:00
# include "common/config-manager.h"
2006-03-29 15:59:37 +00:00
# include "common/endian.h"
2004-10-15 06:06:47 +00:00
# include "common/file.h"
2006-07-15 20:30:36 +00:00
# include "common/fs.h"
2006-09-16 20:51:05 +00:00
# include "common/hash-str.h"
2007-05-23 12:02:31 +00:00
# include "common/func.h"
# include "common/algorithm.h"
2006-07-08 12:23:44 +00:00
# include "gui/message.h"
2005-08-19 22:12:09 +00:00
# include "kyra/resource.h"
2005-06-24 16:01:42 +00:00
# include "kyra/script.h"
2005-08-19 22:12:09 +00:00
# include "kyra/wsamovie.h"
2006-02-09 07:37:19 +00:00
# include "kyra/screen.h"
2004-10-15 06:06:47 +00:00
namespace Kyra {
2007-05-23 12:02:31 +00:00
namespace {
2007-07-29 16:33:11 +00:00
struct ResFilenameEqual : public Common : : UnaryFunction < ResourceFile * , bool > {
2007-05-23 12:02:31 +00:00
uint _filename ;
ResFilenameEqual ( uint file ) : _filename ( file ) { }
2007-07-29 16:33:11 +00:00
bool operator ( ) ( const ResourceFile * f ) {
2007-05-23 12:02:31 +00:00
return f - > filename ( ) = = _filename ;
}
} ;
} // end of anonymous namespace
2007-10-09 05:40:20 +00:00
Resource : : Resource ( KyraEngine * vm ) : _vm ( vm ) {
}
Resource : : ~ Resource ( ) {
unloadAllPakFiles ( ) ;
}
bool Resource : : reset ( ) {
unloadAllPakFiles ( ) ;
FilesystemNode dir ( ConfMan . get ( " path " ) ) ;
if ( ! dir . exists ( ) | | ! dir . isDirectory ( ) )
error ( " invalid game path '%s' " , dir . getPath ( ) . c_str ( ) ) ;
2005-07-30 21:11:48 +00:00
2008-01-10 23:25:19 +00:00
if ( _vm - > game ( ) ! = GI_KYRA3 ) {
2008-01-03 15:20:33 +00:00
if ( ! loadPakFile ( StaticResource : : staticDataFilename ( ) ) | | ! StaticResource : : checkKyraDat ( ) ) {
Common : : String errorMessage = " You're missing the ' " + StaticResource : : staticDataFilename ( ) + " ' file or it got corrupted, (re)get it from the ScummVM website " ;
2008-01-03 14:53:18 +00:00
GUI : : MessageDialog errorMsg ( errorMessage ) ;
2006-07-08 12:23:44 +00:00
errorMsg . runModal ( ) ;
2008-01-03 14:53:18 +00:00
error ( errorMessage . c_str ( ) ) ;
2006-05-28 04:08:25 +00:00
}
2008-01-10 23:25:19 +00:00
}
2006-07-15 20:30:36 +00:00
2008-01-10 23:25:19 +00:00
if ( _vm - > game ( ) = = GI_KYRA1 ) {
2006-07-15 20:32:54 +00:00
// We only need kyra.dat for the demo.
2007-04-01 13:10:50 +00:00
if ( _vm - > gameFlags ( ) . isDemo )
2007-10-09 05:40:20 +00:00
return true ;
2006-07-15 20:32:54 +00:00
2006-07-15 20:30:36 +00:00
// only VRM file we need in the *whole* game for kyra1
2007-04-01 13:10:50 +00:00
if ( _vm - > gameFlags ( ) . isTalkie )
2006-07-16 19:44:39 +00:00
loadPakFile ( " CHAPTER1.VRM " ) ;
2008-01-10 23:25:19 +00:00
} else if ( _vm - > game ( ) = = GI_KYRA2 ) {
// mouse pointer, fonts, etc. required for initializing
if ( _vm - > gameFlags ( ) . isDemo ) {
loadPakFile ( " GENERAL.PAK " ) ;
} else {
loadPakFile ( " INTROGEN.PAK " ) ;
loadPakFile ( " OTHER.PAK " ) ;
}
return true ;
2007-04-01 13:10:50 +00:00
} else if ( _vm - > game ( ) = = GI_KYRA3 ) {
2006-07-08 13:56:56 +00:00
// load the installation package file for kyra3
INSFile * insFile = new INSFile ( " WESTWOOD.001 " ) ;
assert ( insFile ) ;
if ( ! insFile - > isValid ( ) )
2007-05-23 12:02:31 +00:00
error ( " 'WESTWOOD.001' file not found or corrupt " ) ;
2006-07-08 13:56:56 +00:00
_pakfiles . push_back ( insFile ) ;
2006-05-28 04:08:25 +00:00
}
2006-07-15 20:32:54 +00:00
2006-07-15 20:30:36 +00:00
FSList fslist ;
2007-06-05 21:02:35 +00:00
if ( ! dir . getChildren ( fslist , FilesystemNode : : kListFilesOnly ) )
2007-10-09 05:40:20 +00:00
error ( " can't list files inside game path '%s' " , dir . getPath ( ) . c_str ( ) ) ;
2004-11-14 20:11:22 +00:00
2007-04-01 13:10:50 +00:00
if ( _vm - > game ( ) = = GI_KYRA1 & & _vm - > gameFlags ( ) . isTalkie ) {
2006-09-16 14:36:53 +00:00
static const char * list [ ] = {
2006-10-24 00:30:48 +00:00
" ADL.PAK " , " CHAPTER1.VRM " , " COL.PAK " , " FINALE.PAK " , " INTRO1.PAK " , " INTRO2.PAK " ,
" INTRO3.PAK " , " INTRO4.PAK " , " MISC.PAK " , " SND.PAK " , " STARTUP.PAK " , " XMI.PAK " ,
2007-05-23 12:02:31 +00:00
" CAVE.APK " , " DRAGON1.APK " , " DRAGON2.APK " , " LAGOON.APK "
2006-09-16 14:36:53 +00:00
} ;
2007-05-23 12:02:31 +00:00
Common : : for_each ( list , list + ARRAYSIZE ( list ) , Common : : bind1st ( Common : : mem_fun ( & Resource : : loadPakFile ) , this ) ) ;
Common : : for_each ( _pakfiles . begin ( ) , _pakfiles . end ( ) , Common : : bind2nd ( Common : : mem_fun ( & ResourceFile : : protect ) , true ) ) ;
2006-09-16 14:36:53 +00:00
} else {
for ( FSList : : const_iterator file = fslist . begin ( ) ; file ! = fslist . end ( ) ; + + file ) {
2007-06-05 21:02:35 +00:00
Common : : String filename = file - > getName ( ) ;
2006-09-16 14:36:53 +00:00
filename . toUppercase ( ) ;
2007-03-24 00:04:08 +00:00
// No real PAK file!
if ( filename = = " TWMUSIC.PAK " )
continue ;
2006-09-16 14:36:53 +00:00
if ( filename . hasSuffix ( " PAK " ) | | filename . hasSuffix ( " APK " ) ) {
2007-06-05 21:02:35 +00:00
if ( ! loadPakFile ( file - > getName ( ) ) )
error ( " couldn't open pakfile '%s' " , file - > getName ( ) . c_str ( ) ) ;
2006-07-15 20:37:32 +00:00
}
2006-07-15 20:30:36 +00:00
}
2007-01-25 14:38:11 +00:00
2007-09-15 14:53:21 +00:00
if ( _vm - > gameFlags ( ) . platform = = Common : : kPlatformFMTowns | | _vm - > gameFlags ( ) . platform = = Common : : kPlatformPC98 ) {
2007-04-01 13:10:50 +00:00
uint unloadHash = ( _vm - > gameFlags ( ) . lang = = Common : : EN_ANY ) ? Common : : hashit_lower ( " JMC.PAK " ) : Common : : hashit_lower ( " EMC.PAK " ) ;
2007-01-25 14:38:11 +00:00
2007-05-23 12:02:31 +00:00
ResIterator file = Common : : find_if ( _pakfiles . begin ( ) , _pakfiles . end ( ) , ResFilenameEqual ( unloadHash ) ) ;
if ( file ! = _pakfiles . end ( ) ) {
delete * file ;
_pakfiles . erase ( file ) ;
2007-01-25 14:38:11 +00:00
}
}
2004-10-15 06:06:47 +00:00
}
2005-07-30 21:11:48 +00:00
2007-10-09 05:40:20 +00:00
return true ;
2005-10-12 19:15:32 +00:00
}
2007-05-23 12:02:31 +00:00
bool Resource : : loadPakFile ( const Common : : String & filename ) {
ResIterator listFile = Common : : find_if ( _pakfiles . begin ( ) , _pakfiles . end ( ) , ResFilenameEqual ( Common : : hashit_lower ( filename ) ) ) ;
if ( listFile ! = _pakfiles . end ( ) ) {
( * listFile ) - > open ( ) ;
return true ;
2006-09-16 20:51:05 +00:00
}
2006-07-08 13:56:56 +00:00
2008-01-03 15:20:33 +00:00
const bool isKyraDat = filename . equalsIgnoreCase ( StaticResource : : staticDataFilename ( ) ) ;
2006-07-08 13:56:56 +00:00
uint32 size = 0 ;
2007-09-19 08:40:12 +00:00
2006-07-08 14:25:23 +00:00
Common : : File handle ;
2006-09-09 17:14:47 +00:00
if ( ! getFileHandle ( filename . c_str ( ) , & size , handle ) ) {
2007-05-23 12:02:31 +00:00
( ! isKyraDat ? error : warning ) ( " couldn't load file: '%s' " , filename . c_str ( ) ) ;
2006-03-18 14:43:18 +00:00
return false ;
2004-10-15 06:06:47 +00:00
}
2006-07-08 13:56:56 +00:00
2007-05-23 12:02:31 +00:00
PAKFile * file = new PAKFile ( filename . c_str ( ) , handle . name ( ) , handle , ( _vm - > gameFlags ( ) . platform = = Common : : kPlatformAmiga ) & & ! isKyraDat ) ;
2006-07-08 14:25:23 +00:00
handle . close ( ) ;
2006-07-08 13:56:56 +00:00
if ( ! file )
return false ;
2007-03-20 21:11:42 +00:00
2006-07-08 14:25:23 +00:00
if ( ! file - > isValid ( ) ) {
2007-05-23 12:02:31 +00:00
error ( " '%s' is no valid pak file " , filename . c_str ( ) ) ;
2006-07-08 14:25:23 +00:00
delete file ;
return false ;
}
2006-07-08 13:56:56 +00:00
_pakfiles . push_back ( file ) ;
2005-10-12 19:15:32 +00:00
return true ;
}
2007-10-09 05:40:20 +00:00
bool Resource : : loadFileList ( const Common : : String & filedata ) {
Common : : File f ;
if ( ! f . open ( filedata ) )
return false ;
uint32 filenameOffset = 0 ;
while ( ( filenameOffset = f . readUint32LE ( ) ) ! = 0 ) {
uint32 offset = f . pos ( ) ;
f . seek ( filenameOffset , SEEK_SET ) ;
uint8 buffer [ 64 ] ;
f . read ( buffer , sizeof ( buffer ) ) ;
f . seek ( offset + 16 , SEEK_SET ) ;
Common : : String filename = ( char * ) buffer ;
2007-10-09 05:42:52 +00:00
filename . toUppercase ( ) ;
2007-10-09 05:40:20 +00:00
if ( filename . hasSuffix ( " .PAK " ) ) {
if ( ! loadPakFile ( filename ) ) {
error ( " couldn't load file '%s' " , filename . c_str ( ) ) ;
return false ;
}
}
}
return true ;
}
2008-01-10 23:25:19 +00:00
bool Resource : : loadFileList ( const char * const * filelist , uint32 numFiles ) {
if ( ! filelist )
return false ;
while ( numFiles - - ) {
if ( ! loadPakFile ( filelist [ numFiles ] ) ) {
error ( " couldn't load file '%s' " , filelist [ numFiles ] ) ;
return false ;
}
}
return true ;
}
2006-06-03 18:30:07 +00:00
void Resource : : unloadPakFile ( const Common : : String & filename ) {
2007-05-23 12:02:31 +00:00
ResIterator pak = Common : : find_if ( _pakfiles . begin ( ) , _pakfiles . end ( ) , ResFilenameEqual ( Common : : hashit_lower ( filename ) ) ) ;
if ( pak ! = _pakfiles . end ( ) )
( * pak ) - > close ( ) ;
2005-10-12 19:15:32 +00:00
}
2007-05-23 12:02:31 +00:00
bool Resource : : isInPakList ( const Common : : String & filename ) const {
return ( Common : : find_if ( _pakfiles . begin ( ) , _pakfiles . end ( ) , ResFilenameEqual ( Common : : hashit_lower ( filename ) ) ) ! = _pakfiles . end ( ) ) ;
2004-11-14 20:11:22 +00:00
}
2005-07-30 21:11:48 +00:00
2007-10-09 05:40:20 +00:00
void Resource : : unloadAllPakFiles ( ) {
for ( ResIterator start = _pakfiles . begin ( ) ; start ! = _pakfiles . end ( ) ; + + start ) {
delete * start ;
* start = 0 ;
}
_pakfiles . clear ( ) ;
}
2007-05-23 12:02:31 +00:00
uint8 * Resource : : fileData ( const char * file , uint32 * size ) const {
2007-03-20 20:46:19 +00:00
Common : : File fileHandle ;
2005-07-30 21:11:48 +00:00
2006-07-30 07:51:11 +00:00
if ( size )
* size = 0 ;
2004-11-14 20:11:22 +00:00
// test to open it in the main dir
2007-03-20 20:46:19 +00:00
if ( fileHandle . open ( file ) ) {
uint32 fileSize = fileHandle . size ( ) ;
uint8 * buffer = new uint8 [ fileSize ] ;
2004-11-14 20:11:22 +00:00
assert ( buffer ) ;
2005-07-30 21:11:48 +00:00
2007-03-20 20:46:19 +00:00
fileHandle . read ( buffer , fileSize ) ;
2006-07-30 08:22:39 +00:00
if ( size )
2007-03-20 20:46:19 +00:00
* size = fileSize ;
2005-07-30 21:11:48 +00:00
2007-03-20 20:46:19 +00:00
return buffer ;
2004-11-14 20:11:22 +00:00
} else {
2007-05-23 12:02:31 +00:00
// opens the file inside a PAK File
2006-09-16 20:51:05 +00:00
uint fileHash = Common : : hashit_lower ( file ) ;
2007-05-23 12:02:31 +00:00
for ( ConstResIterator cur = _pakfiles . begin ( ) ; cur ! = _pakfiles . end ( ) ; + + cur ) {
if ( ! ( * cur ) - > isOpen ( ) )
2006-09-16 20:51:05 +00:00
continue ;
2006-07-30 07:51:11 +00:00
2007-07-02 23:02:54 +00:00
uint8 * result = ( * cur ) - > getFile ( fileHash ) ;
if ( result ) {
uint32 fileSize = ( * cur ) - > getFileSize ( fileHash ) ;
if ( ! fileSize )
continue ;
if ( size )
* size = fileSize ;
return result ;
}
2006-07-30 07:51:11 +00:00
2004-10-15 06:06:47 +00:00
}
2004-11-14 20:11:22 +00:00
}
2005-07-30 21:11:48 +00:00
2007-03-20 20:46:19 +00:00
return 0 ;
2004-11-14 20:11:22 +00:00
}
2005-07-30 21:11:48 +00:00
2006-09-09 17:14:47 +00:00
bool Resource : : getFileHandle ( const char * file , uint32 * size , Common : : File & filehandle ) {
2006-02-10 16:39:56 +00:00
filehandle . close ( ) ;
2007-07-29 17:21:21 +00:00
if ( filehandle . open ( file ) ) {
if ( size )
* size = filehandle . size ( ) ;
2006-02-10 16:39:56 +00:00
return true ;
2007-07-29 17:21:21 +00:00
}
2006-02-10 16:39:56 +00:00
2006-09-16 20:51:05 +00:00
uint fileHash = Common : : hashit_lower ( file ) ;
2007-05-23 12:02:31 +00:00
for ( ResIterator start = _pakfiles . begin ( ) ; start ! = _pakfiles . end ( ) ; + + start ) {
2006-09-16 20:51:05 +00:00
if ( ! ( * start ) - > isOpen ( ) )
continue ;
2007-07-02 23:02:54 +00:00
if ( ( * start ) - > getFileHandle ( fileHash , filehandle ) ) {
2007-07-29 17:21:21 +00:00
uint32 tSize = ( * start ) - > getFileSize ( fileHash ) ;
2007-09-19 08:40:12 +00:00
2007-07-29 17:21:21 +00:00
if ( ! tSize )
2007-07-02 23:02:54 +00:00
continue ;
2006-02-10 16:39:56 +00:00
2007-07-29 17:21:21 +00:00
if ( size )
* size = tSize ;
2006-02-10 16:39:56 +00:00
return true ;
2007-07-02 23:02:54 +00:00
}
2006-02-10 16:39:56 +00:00
}
2007-09-19 08:40:12 +00:00
2006-02-10 16:39:56 +00:00
return false ;
}
2007-05-23 12:02:31 +00:00
uint32 Resource : : getFileSize ( const char * file ) const {
2006-07-31 16:37:34 +00:00
Common : : File temp ;
if ( temp . open ( file ) )
return temp . size ( ) ;
2006-09-16 20:51:05 +00:00
uint fileHash = Common : : hashit_lower ( file ) ;
2007-05-23 12:02:31 +00:00
for ( ConstResIterator start = _pakfiles . begin ( ) ; start ! = _pakfiles . end ( ) ; + + start ) {
2006-09-16 20:51:05 +00:00
if ( ! ( * start ) - > isOpen ( ) )
continue ;
uint32 size = ( * start ) - > getFileSize ( fileHash ) ;
2007-09-19 08:40:12 +00:00
2006-07-31 16:37:34 +00:00
if ( size )
return size ;
}
return 0 ;
}
bool Resource : : loadFileToBuf ( const char * file , void * buf , uint32 maxSize ) {
Common : : File tempHandle ;
uint32 size = 0 ;
2007-03-20 21:11:42 +00:00
2006-09-09 17:14:47 +00:00
if ( ! getFileHandle ( file , & size , tempHandle ) )
2006-07-31 16:37:34 +00:00
return false ;
if ( size > maxSize )
return false ;
memset ( buf , 0 , maxSize ) ;
tempHandle . read ( buf , size ) ;
return true ;
}
2004-10-15 06:06:47 +00:00
///////////////////////////////////////////
// Pak file manager
2006-09-10 13:16:34 +00:00
PAKFile : : PAKFile ( const char * file , const char * physfile , Common : : File & pakfile , bool isAmiga ) : ResourceFile ( ) {
2004-11-14 20:11:22 +00:00
_open = false ;
2005-07-30 21:11:48 +00:00
2006-09-10 13:16:34 +00:00
if ( ! pakfile . isOpen ( ) ) {
2006-06-03 18:30:07 +00:00
debug ( 3 , " couldn't open pakfile '%s' \n " , file ) ;
2004-11-14 20:11:22 +00:00
return ;
}
2004-10-15 06:06:47 +00:00
2006-09-10 13:16:34 +00:00
uint32 off = pakfile . pos ( ) ;
2004-11-14 20:11:22 +00:00
uint32 filesize = pakfile . size ( ) ;
2004-10-15 06:06:47 +00:00
2004-11-14 20:11:22 +00:00
uint32 pos = 0 , startoffset = 0 , endoffset = 0 ;
2004-10-15 06:06:47 +00:00
2007-05-23 12:02:31 +00:00
if ( isAmiga )
2006-09-10 13:16:34 +00:00
startoffset = pakfile . readUint32BE ( ) ;
2007-05-23 12:02:31 +00:00
else
startoffset = pakfile . readUint32LE ( ) ;
2007-03-20 21:11:42 +00:00
if ( startoffset > filesize ) {
warning ( " PAK file '%s' is corrupted " , file ) ;
return ;
2006-03-14 19:48:08 +00:00
}
2007-03-20 21:11:42 +00:00
2004-11-14 20:11:22 +00:00
pos + = 4 ;
2004-10-15 06:06:47 +00:00
2004-11-14 20:11:22 +00:00
while ( pos < filesize ) {
2006-06-03 17:58:13 +00:00
PakChunk chunk ;
2006-09-10 13:16:34 +00:00
uint8 buffer [ 64 ] ;
2006-09-09 12:21:49 +00:00
uint32 nameLength ;
2007-09-19 08:40:12 +00:00
2006-09-09 12:21:49 +00:00
// Move to the position of the next file entry
pakfile . seek ( pos ) ;
2007-09-19 08:40:12 +00:00
2006-09-09 12:21:49 +00:00
// Read in the header
2007-03-20 21:11:42 +00:00
if ( pakfile . read ( & buffer , 64 ) < 5 ) {
warning ( " PAK file '%s' is corrupted " , file ) ;
return ;
}
2007-09-19 08:40:12 +00:00
2006-09-09 12:21:49 +00:00
// Quit now if we encounter an empty string
if ( ! ( * ( ( const char * ) buffer ) ) )
2006-08-08 21:34:19 +00:00
break ;
2006-09-16 20:51:05 +00:00
chunk . _name = Common : : hashit_lower ( ( const char * ) buffer ) ;
2007-09-19 08:40:12 +00:00
nameLength = strlen ( ( const char * ) buffer ) + 1 ;
2004-10-15 06:06:47 +00:00
2007-03-20 21:11:42 +00:00
if ( nameLength > 60 ) {
warning ( " PAK file '%s' is corrupted " , file ) ;
return ;
}
2007-05-23 12:02:31 +00:00
if ( isAmiga )
2006-09-09 12:21:49 +00:00
endoffset = READ_BE_UINT32 ( buffer + nameLength ) ;
2007-05-23 12:02:31 +00:00
else
endoffset = READ_LE_UINT32 ( buffer + nameLength ) ;
2005-07-30 21:11:48 +00:00
2007-03-20 21:11:42 +00:00
if ( ! endoffset ) {
2004-11-14 20:11:22 +00:00
endoffset = filesize ;
2007-03-20 21:11:42 +00:00
} else if ( endoffset > filesize | | startoffset > endoffset ) {
warning ( " PAK file '%s' is corrupted " , file ) ;
return ;
2004-11-14 20:11:22 +00:00
}
2004-10-15 06:06:47 +00:00
2007-03-20 21:11:42 +00:00
if ( startoffset ! = endoffset ) {
chunk . _start = startoffset ;
chunk . _size = endoffset - startoffset ;
2004-10-15 06:06:47 +00:00
2007-03-20 21:11:42 +00:00
_files . push_back ( chunk ) ;
}
2005-07-30 21:11:48 +00:00
2004-11-14 20:11:22 +00:00
if ( endoffset = = filesize )
break ;
2004-11-11 13:37:35 +00:00
2004-11-14 20:11:22 +00:00
startoffset = endoffset ;
2006-09-09 12:21:49 +00:00
pos + = nameLength + 4 ;
2004-10-16 22:28:29 +00:00
}
2006-07-08 13:56:56 +00:00
2007-09-19 08:40:12 +00:00
_open = true ;
2006-09-16 20:51:05 +00:00
_filename = Common : : hashit_lower ( file ) ;
2006-07-08 14:25:23 +00:00
_physfile = physfile ;
_physOffset = off ;
2006-07-08 13:56:56 +00:00
}
2006-09-10 13:16:34 +00:00
2004-11-14 20:11:22 +00:00
PAKFile : : ~ PAKFile ( ) {
2006-07-08 14:25:23 +00:00
_physfile . clear ( ) ;
2004-11-14 20:11:22 +00:00
_open = false ;
2004-10-15 06:06:47 +00:00
2006-06-03 17:58:13 +00:00
_files . clear ( ) ;
2004-11-14 20:11:22 +00:00
}
2004-10-15 06:06:47 +00:00
2007-05-23 12:02:31 +00:00
uint8 * PAKFile : : getFile ( uint hash ) const {
ConstPakIterator file = Common : : find_if ( _files . begin ( ) , _files . end ( ) , Common : : bind2nd ( Common : : EqualTo < uint > ( ) , hash ) ) ;
if ( file = = _files . end ( ) )
return 0 ;
Common : : File pakfile ;
if ( ! openFile ( pakfile ) )
return false ;
pakfile . seek ( file - > _start , SEEK_CUR ) ;
uint8 * buffer = new uint8 [ file - > _size ] ;
assert ( buffer ) ;
pakfile . read ( buffer , file - > _size ) ;
return buffer ;
2004-11-14 20:11:22 +00:00
}
2004-10-15 06:06:47 +00:00
2007-05-23 12:02:31 +00:00
bool PAKFile : : getFileHandle ( uint hash , Common : : File & filehandle ) const {
2006-02-10 16:39:56 +00:00
filehandle . close ( ) ;
2007-05-23 12:02:31 +00:00
ConstPakIterator file = Common : : find_if ( _files . begin ( ) , _files . end ( ) , Common : : bind2nd ( Common : : EqualTo < uint > ( ) , hash ) ) ;
if ( file = = _files . end ( ) )
return false ;
2007-03-20 21:11:42 +00:00
2007-05-23 12:02:31 +00:00
if ( ! openFile ( filehandle ) )
return false ;
filehandle . seek ( file - > _start , SEEK_CUR ) ;
return true ;
2006-02-10 16:39:56 +00:00
}
2007-05-23 12:02:31 +00:00
uint32 PAKFile : : getFileSize ( uint hash ) const {
ConstPakIterator file = Common : : find_if ( _files . begin ( ) , _files . end ( ) , Common : : bind2nd ( Common : : EqualTo < uint > ( ) , hash ) ) ;
return ( file ! = _files . end ( ) ) ? file - > _size : 0 ;
2004-11-14 20:11:22 +00:00
}
2006-02-09 07:37:19 +00:00
2007-05-23 12:02:31 +00:00
bool PAKFile : : openFile ( Common : : File & filehandle ) const {
2006-07-08 14:25:23 +00:00
filehandle . close ( ) ;
2007-03-20 21:11:42 +00:00
if ( ! filehandle . open ( _physfile ) )
2006-07-08 14:25:23 +00:00
return false ;
2006-09-10 13:16:34 +00:00
filehandle . seek ( _physOffset , SEEK_CUR ) ;
2006-07-08 14:25:23 +00:00
return true ;
}
2006-07-08 13:56:56 +00:00
///////////////////////////////////////////
// Ins file manager
INSFile : : INSFile ( const char * file ) : ResourceFile ( ) , _files ( ) {
Common : : File pakfile ;
_open = false ;
if ( ! pakfile . open ( file ) ) {
debug ( 3 , " couldn't open insfile '%s' \n " , file ) ;
return ;
}
// thanks to eriktorbjorn for this code (a bit modified though)
// skip first three bytes
pakfile . seek ( 3 ) ;
// first file is the index table
uint32 filesize = pakfile . readUint32LE ( ) ;
Common : : String temp = " " ;
for ( uint i = 0 ; i < filesize ; + + i ) {
byte c = pakfile . readByte ( ) ;
if ( c = = ' \\ ' ) {
temp = " " ;
} else if ( c = = 0x0D ) {
// line endings are CRLF
c = pakfile . readByte ( ) ;
assert ( c = = 0x0A ) ;
+ + i ;
FileEntry newEntry ;
2006-09-16 20:51:05 +00:00
newEntry . _name = Common : : hashit_lower ( temp . c_str ( ) ) ;
2006-07-08 13:56:56 +00:00
newEntry . _start = 0 ;
newEntry . _size = 0 ;
_files . push_back ( newEntry ) ;
temp = " " ;
} else {
temp + = ( char ) c ;
}
}
pakfile . seek ( 3 ) ;
2007-05-23 12:02:31 +00:00
for ( FileIterator start = _files . begin ( ) ; start ! = _files . end ( ) ; + + start ) {
2006-07-08 13:56:56 +00:00
filesize = pakfile . readUint32LE ( ) ;
start - > _size = filesize ;
start - > _start = pakfile . pos ( ) ;
pakfile . seek ( filesize , SEEK_CUR ) ;
}
2006-09-16 20:51:05 +00:00
_filename = Common : : hashit_lower ( file ) ;
_physfile = file ;
2006-07-08 13:56:56 +00:00
_open = true ;
}
INSFile : : ~ INSFile ( ) {
_open = false ;
_files . clear ( ) ;
}
2007-05-23 12:02:31 +00:00
uint8 * INSFile : : getFile ( uint hash ) const {
ConstFileIterator file = Common : : find_if ( _files . begin ( ) , _files . end ( ) , Common : : bind2nd ( Common : : EqualTo < uint > ( ) , hash ) ) ;
if ( file = = _files . end ( ) )
return 0 ;
Common : : File pakfile ;
if ( ! pakfile . open ( _physfile ) )
return false ;
pakfile . seek ( file - > _start ) ;
uint8 * buffer = new uint8 [ file - > _size ] ;
assert ( buffer ) ;
pakfile . read ( buffer , file - > _size ) ;
return buffer ;
2006-07-08 13:56:56 +00:00
}
2007-05-23 12:02:31 +00:00
bool INSFile : : getFileHandle ( uint hash , Common : : File & filehandle ) const {
ConstFileIterator file = Common : : find_if ( _files . begin ( ) , _files . end ( ) , Common : : bind2nd ( Common : : EqualTo < uint > ( ) , hash ) ) ;
2007-03-20 21:11:42 +00:00
2007-05-23 12:02:31 +00:00
if ( file = = _files . end ( ) )
return false ;
2007-09-19 08:40:12 +00:00
if ( ! filehandle . open ( _physfile ) )
2007-05-23 12:02:31 +00:00
return false ;
filehandle . seek ( file - > _start , SEEK_CUR ) ;
return true ;
2006-07-08 13:56:56 +00:00
}
2007-05-23 12:02:31 +00:00
uint32 INSFile : : getFileSize ( uint hash ) const {
ConstFileIterator file = Common : : find_if ( _files . begin ( ) , _files . end ( ) , Common : : bind2nd ( Common : : EqualTo < uint > ( ) , hash ) ) ;
return ( file ! = _files . end ( ) ) ? file - > _size : 0 ;
2006-07-08 13:56:56 +00:00
}
2004-10-15 06:06:47 +00:00
} // end of namespace Kyra
2007-04-15 16:41:20 +00:00