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
*
*/
2008-09-07 21:46:37 +00:00
# include "kyra/resource.h"
# include "kyra/resource_intern.h"
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"
2007-05-23 12:02:31 +00:00
# include "common/func.h"
2008-09-07 21:46:37 +00:00
# include "common/system.h"
2004-10-15 06:06:47 +00:00
namespace Kyra {
2007-05-23 12:02:31 +00:00
2008-09-07 21:46:37 +00:00
Resource : : Resource ( KyraEngine_v1 * vm ) : _archiveCache ( ) , _files ( ) , _archiveFiles ( new Common : : SearchSet ( ) ) , _protectedFiles ( new Common : : SearchSet ( ) ) , _loaders ( ) , _vm ( vm ) {
2008-02-07 23:13:13 +00:00
initializeLoaders ( ) ;
2008-09-07 21:46:37 +00:00
Common : : SharedPtr < Common : : Archive > path ( new Common : : FSDirectory ( ConfMan . get ( " path " ) ) ) ;
Common : : SharedPtr < Common : : Archive > extrapath ( new Common : : FSDirectory ( ConfMan . get ( " extrapath " ) ) ) ;
2008-09-07 22:35:13 +00:00
2008-09-07 22:41:57 +00:00
_files . add ( " path " , path , 4 ) ;
_files . add ( " extrapath " , extrapath , 4 ) ;
2008-09-07 22:35:13 +00:00
_vm - > _system - > addSysArchivesToSearchSet ( _files , 3 ) ;
2008-09-07 21:46:37 +00:00
// compressed installer archives are added at level '2',
// but that's done in Resource::reset not here
_files . add ( " protected " , _protectedFiles , 1 ) ;
_files . add ( " archives " , _archiveFiles , 0 ) ;
2007-10-09 05:40:20 +00:00
}
Resource : : ~ Resource ( ) {
2008-02-07 23:38:17 +00:00
_loaders . clear ( ) ;
2007-10-09 05:40:20 +00:00
}
bool Resource : : reset ( ) {
unloadAllPakFiles ( ) ;
2008-09-03 11:22:51 +00:00
Common : : FilesystemNode dir ( ConfMan . get ( " path " ) ) ;
2008-01-27 19:47:41 +00:00
2007-10-09 05:40:20 +00:00
if ( ! dir . exists ( ) | | ! dir . isDirectory ( ) )
error ( " invalid game path '%s' " , dir . getPath ( ) . c_str ( ) ) ;
2005-07-30 21:11:48 +00:00
2008-09-07 22:30:34 +00:00
if ( ! loadPakFile ( StaticResource : : staticDataFilename ( ) ) | | ! StaticResource : : checkKyraDat ( this ) ) {
2008-08-02 23:11:31 +00:00
Common : : String errorMessage = " You're missing the ' " + StaticResource : : staticDataFilename ( ) + " ' file or it got corrupted, (re)get it from the ScummVM website " ;
_vm - > GUIErrorMessage ( errorMessage ) ;
error ( errorMessage . c_str ( ) ) ;
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 ;
2008-01-10 23:25:19 +00:00
} else if ( _vm - > game ( ) = = GI_KYRA2 ) {
2008-05-24 16:30:18 +00:00
if ( _vm - > gameFlags ( ) . useInstallerPackage )
2008-09-07 21:46:37 +00:00
_files . add ( " installer " , loadInstallerArchive ( " WESTWOOD " , " %03d " , 6 ) , 2 ) ;
2008-05-24 16:30:18 +00:00
2008-01-10 23:25:19 +00:00
// mouse pointer, fonts, etc. required for initializing
2008-03-20 12:10:30 +00:00
if ( _vm - > gameFlags ( ) . isDemo & & ! _vm - > gameFlags ( ) . isTalkie ) {
2008-01-10 23:25:19 +00:00
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 ) {
2008-08-05 12:13:01 +00:00
if ( _vm - > gameFlags ( ) . useInstallerPackage ) {
if ( ! loadPakFile ( " WESTWOOD.001 " ) )
error ( " couldn't load file: 'WESTWOOD.001' " ) ;
}
2008-05-31 20:48:41 +00:00
2008-08-05 12:13:01 +00:00
if ( ! loadFileList ( " FILEDATA.FDT " ) )
error ( " couldn't load file: 'FILEDATA.FDT' " ) ;
2008-04-12 23:17:21 +00:00
2008-07-31 10:47:15 +00:00
return true ;
} else if ( _vm - > game ( ) = = GI_LOL ) {
2008-08-11 14:47:50 +00:00
if ( _vm - > gameFlags ( ) . useInstallerPackage )
2008-09-07 21:46:37 +00:00
_files . add ( " installer " , loadInstallerArchive ( " WESTWOOD " , " %d " , 0 ) , 2 ) ;
2008-08-11 14:47:50 +00:00
2008-04-12 23:17:21 +00:00
return true ;
2006-05-28 04:08:25 +00:00
}
2006-07-15 20:32:54 +00:00
2008-09-03 11:22:51 +00:00
Common : : FSList fslist ;
if ( ! dir . getChildren ( fslist , Common : : 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
} ;
2008-09-07 21:46:37 +00:00
for ( uint i = 0 ; i < ARRAYSIZE ( list ) ; + + i ) {
Common : : ArchivePtr archive = loadArchive ( list [ i ] ) ;
2008-09-07 22:30:34 +00:00
if ( archive )
_protectedFiles - > add ( list [ i ] , archive , 0 ) ;
2008-02-07 23:14:53 +00:00
}
2006-09-16 14:36:53 +00:00
} else {
2008-09-03 11:22:51 +00:00
for ( Common : : 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 ;
2008-02-07 23:13:13 +00:00
if ( filename = = ( ( _vm - > gameFlags ( ) . lang = = Common : : EN_ANY ) ? " JMC.PAK " : " EMC.PAK " ) )
continue ;
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
}
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
}
2008-09-07 21:46:37 +00:00
bool Resource : : loadPakFile ( Common : : String filename ) {
filename . toUppercase ( ) ;
2008-04-10 22:22:35 +00:00
2008-09-07 21:46:37 +00:00
if ( _archiveFiles - > hasArchive ( filename ) | | _protectedFiles - > hasArchive ( filename ) )
2008-02-09 15:33:04 +00:00
return true ;
2007-09-19 08:40:12 +00:00
2008-09-07 21:46:37 +00:00
Common : : ArchivePtr archive = loadArchive ( filename ) ;
if ( ! archive )
2006-03-18 14:43:18 +00:00
return false ;
2006-07-08 13:56:56 +00:00
2008-09-07 21:46:37 +00:00
_archiveFiles - > add ( filename , archive , 0 ) ;
2008-02-07 23:13:13 +00:00
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 ) {
2008-09-07 22:30:34 +00:00
Common : : SeekableReadStream * f = getFileStream ( filedata ) ;
2008-01-27 19:47:41 +00:00
2008-09-07 22:30:34 +00:00
if ( ! f )
2007-10-09 05:40:20 +00:00
return false ;
uint32 filenameOffset = 0 ;
2008-09-07 22:30:34 +00:00
while ( ( filenameOffset = f - > readUint32LE ( ) ) ! = 0 ) {
uint32 offset = f - > pos ( ) ;
f - > seek ( filenameOffset , SEEK_SET ) ;
2007-10-09 05:40:20 +00:00
2008-04-03 21:42:04 +00:00
uint8 buffer [ 13 ] ;
2008-09-07 22:30:34 +00:00
f - > read ( buffer , sizeof ( buffer ) - 1 ) ;
2008-04-03 21:42:04 +00:00
buffer [ 12 ] = 0 ;
2008-09-07 22:30:34 +00:00
f - > seek ( offset + 16 , SEEK_SET ) ;
2007-10-09 05:40:20 +00:00
2008-09-07 21:46:37 +00:00
Common : : String filename = Common : : String ( ( char * ) buffer ) ;
2007-10-09 05:42:52 +00:00
filename . toUppercase ( ) ;
2007-10-09 05:40:20 +00:00
if ( filename . hasSuffix ( " .PAK " ) ) {
2008-09-07 21:46:37 +00:00
if ( ! exists ( filename . c_str ( ) ) & & _vm - > gameFlags ( ) . isDemo ) {
2008-03-20 11:55:52 +00:00
// the demo version supplied with Kyra3 does not
// contain all pak files listed in filedata.fdt
// so we don't do anything here if they are non
// existant.
2008-03-20 11:58:18 +00:00
} else if ( ! loadPakFile ( filename ) ) {
2008-09-07 22:30:34 +00:00
delete f ;
2007-10-09 05:40:20 +00:00
error ( " couldn't load file '%s' " , filename . c_str ( ) ) ;
return false ;
}
2008-01-27 19:47:41 +00:00
}
2007-10-09 05:40:20 +00:00
}
2008-09-07 22:30:34 +00:00
delete f ;
2007-10-09 05:40:20 +00:00
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 ;
}
2008-09-07 21:46:37 +00:00
void Resource : : unloadPakFile ( Common : : String filename ) {
filename . toUppercase ( ) ;
_archiveFiles - > remove ( filename ) ;
2008-09-07 22:35:13 +00:00
// We do not remove files from '_protectedFiles' here, since
// those are protected against unloading.
2008-05-31 20:48:41 +00:00
}
2008-09-07 21:46:37 +00:00
bool Resource : : isInPakList ( Common : : String filename ) {
filename . toUppercase ( ) ;
return ( _archiveFiles - > hasArchive ( filename ) | | _protectedFiles - > hasArchive ( filename ) ) ;
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 ( ) {
2008-09-07 21:46:37 +00:00
_archiveFiles - > clear ( ) ;
_protectedFiles - > clear ( ) ;
2008-02-24 12:30:12 +00:00
}
2008-04-10 22:18:47 +00:00
uint8 * Resource : : fileData ( const char * file , uint32 * size ) {
2008-02-07 23:13:13 +00:00
Common : : SeekableReadStream * stream = getFileStream ( file ) ;
if ( ! stream )
return 0 ;
2005-07-30 21:11:48 +00:00
2008-02-07 23:13:13 +00:00
uint32 bufferSize = stream - > size ( ) ;
uint8 * buffer = new uint8 [ bufferSize ] ;
assert ( buffer ) ;
2006-07-30 07:51:11 +00:00
if ( size )
2008-02-07 23:13:13 +00:00
* size = bufferSize ;
stream - > read ( buffer , bufferSize ) ;
delete stream ;
return buffer ;
}
2005-07-30 21:11:48 +00:00
2008-04-19 14:31:10 +00:00
bool Resource : : exists ( const char * file , bool errorOutOnFail ) {
2008-09-07 21:46:37 +00:00
if ( _files . hasFile ( file ) )
2008-04-19 14:31:10 +00:00
return true ;
else if ( errorOutOnFail )
error ( " File '%s' can't be found " , file ) ;
return false ;
}
2008-04-10 22:18:47 +00:00
uint32 Resource : : getFileSize ( const char * file ) {
2008-09-07 21:46:37 +00:00
Common : : SeekableReadStream * stream = getFileStream ( file ) ;
if ( ! stream )
return 0 ;
2006-09-16 20:51:05 +00:00
2008-09-07 21:46:37 +00:00
uint32 size = stream - > size ( ) ;
delete stream ;
return size ;
2008-02-07 23:13:13 +00:00
}
2006-07-30 07:51:11 +00:00
2008-02-07 23:13:13 +00:00
bool Resource : : loadFileToBuf ( const char * file , void * buf , uint32 maxSize ) {
Common : : SeekableReadStream * stream = getFileStream ( file ) ;
if ( ! stream )
return false ;
2007-07-02 23:02:54 +00:00
2008-02-07 23:13:13 +00:00
memset ( buf , 0 , maxSize ) ;
2008-05-31 20:48:41 +00:00
stream - > read ( buf , ( maxSize < = stream - > size ( ) ) ? maxSize : stream - > size ( ) ) ;
2008-02-07 23:13:13 +00:00
delete stream ;
return true ;
}
2007-07-02 23:02:54 +00:00
2008-04-10 22:18:47 +00:00
Common : : SeekableReadStream * Resource : : getFileStream ( const Common : : String & file ) {
2008-09-07 21:46:37 +00:00
return _files . openFile ( file ) ;
2006-07-31 16:37:34 +00:00
}
2008-09-07 21:46:37 +00:00
Common : : ArchivePtr Resource : : loadArchive ( const Common : : String & file ) {
ArchiveMap : : iterator cachedArchive = _archiveCache . find ( file ) ;
if ( cachedArchive ! = _archiveCache . end ( ) )
return cachedArchive - > _value ;
2008-02-09 15:08:49 +00:00
2008-09-07 21:46:37 +00:00
Common : : SeekableReadStream * stream = getFileStream ( file ) ;
if ( ! stream )
return Common : : ArchivePtr ( ) ;
Common : : ArchivePtr archive ;
for ( LoaderList : : const_iterator i = _loaders . begin ( ) ; i ! = _loaders . end ( ) ; + + i ) {
if ( ( * i ) - > checkFilename ( file ) ) {
if ( ( * i ) - > isLoadable ( file , * stream ) ) {
stream - > seek ( 0 , SEEK_SET ) ;
archive = Common : : ArchivePtr ( ( * i ) - > load ( this , file , * stream ) ) ;
2008-02-09 15:08:49 +00:00
break ;
} else {
2008-09-07 21:46:37 +00:00
stream - > seek ( 0 , SEEK_SET ) ;
2008-05-24 16:30:18 +00:00
}
}
}
2008-09-07 21:46:37 +00:00
delete stream ;
2008-05-24 16:30:18 +00:00
2008-09-07 21:46:37 +00:00
if ( ! archive )
return Common : : ArchivePtr ( ) ;
2008-05-24 16:30:18 +00:00
2008-09-07 21:46:37 +00:00
_archiveCache [ file ] = archive ;
return archive ;
2008-05-24 16:30:18 +00:00
}
2008-09-07 21:46:37 +00:00
Common : : ArchivePtr Resource : : loadInstallerArchive ( const Common : : String & file , const Common : : String & ext , const uint8 offset ) {
ArchiveMap : : iterator cachedArchive = _archiveCache . find ( file ) ;
if ( cachedArchive ! = _archiveCache . end ( ) )
return cachedArchive - > _value ;
2008-05-24 16:30:18 +00:00
2008-09-07 21:46:37 +00:00
Common : : ArchivePtr archive ( InstallerLoader : : load ( this , file , ext , offset ) ) ;
if ( ! archive )
return Common : : ArchivePtr ( ) ;
2008-05-24 16:30:18 +00:00
2008-09-07 21:46:37 +00:00
_archiveCache [ file ] = archive ;
return archive ;
2008-02-09 15:18:35 +00:00
}
2008-04-17 16:38:26 +00:00
# pragma mark -
2008-02-07 23:13:13 +00:00
void Resource : : initializeLoaders ( ) {
2008-03-28 06:03:59 +00:00
_loaders . push_back ( LoaderList : : value_type ( new ResLoaderPak ( ) ) ) ;
2008-05-24 16:30:18 +00:00
_loaders . push_back ( LoaderList : : value_type ( new ResLoaderInsMalcolm ( ) ) ) ;
2008-04-17 16:38:26 +00:00
_loaders . push_back ( LoaderList : : value_type ( new ResLoaderTlk ( ) ) ) ;
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
2008-03-28 06:03:59 +00:00
2008-05-31 20:48:41 +00:00