2003-12-16 02:10:15 +00:00
/* ScummVM - Scumm Interpreter
2004-01-06 12:45:34 +00:00
* Copyright ( C ) 2003 - 2004 The ScummVM project
2003-12-16 02:10:15 +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
* Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*
* $ Header $
*
*/
# include "stdafx.h"
# include "scummsys.h"
2004-10-21 12:37:13 +00:00
# include "sword1/memman.h"
# include "sword1/resman.h"
# include "sword1/sworddefs.h"
2003-12-16 02:10:15 +00:00
# include "base/engine.h"
2004-07-11 04:41:48 +00:00
# include "common/config-manager.h"
2003-12-16 02:10:15 +00:00
# include "common/util.h"
2004-07-11 04:41:48 +00:00
# include "common/str.h"
2004-10-21 12:37:13 +00:00
# include "sword1/swordres.h"
2003-12-16 02:10:15 +00:00
2004-07-11 04:41:48 +00:00
# include "gui/message.h"
# include "gui/newgui.h"
2004-01-11 15:47:41 +00:00
namespace Sword1 {
2004-07-11 04:41:48 +00:00
void guiFatalError ( char * msg ) {
// Displays a dialog on-screen before terminating the engine.
// TODO: We really need to setup a special palette for cases when
// the engine is erroring before setting one... otherwise invisible cursor :)
GUI : : MessageDialog dialog ( msg ) ;
dialog . runModal ( ) ;
error ( msg ) ;
}
2004-01-11 15:47:41 +00:00
2003-12-16 02:10:15 +00:00
# define MAX_PATH_LEN 260
ResMan : : ResMan ( const char * resFile , MemMan * pMemoMan ) {
_memMan = pMemoMan ;
loadCluDescript ( resFile ) ;
}
ResMan : : ~ ResMan ( void ) {
2004-11-09 04:06:10 +00:00
#if 0
for ( uint32 clusCnt = 0 ; clusCnt < _prj . noClu ; clusCnt + + ) {
Clu * cluster = _prj . clu [ clusCnt ] ;
if ( cluster ) {
for ( uint32 grpCnt = 0 ; grpCnt < cluster - > noGrp ; grpCnt + + ) {
Grp * group = cluster - > grp [ grpCnt ] ;
if ( group ) {
for ( uint32 resCnt = 0 ; resCnt < group - > noRes ; resCnt + + ) {
if ( group - > resHandle [ resCnt ] . cond = = MEM_DONT_FREE ) {
warning ( " ResMan::~ResMan: Resource %02X.%04X.%02X is still open " ,
clusCnt + 1 , grpCnt , resCnt ) ;
}
}
}
}
}
}
debug ( 0 , " ResMan closed \n " ) ;
# endif
2003-12-16 02:10:15 +00:00
freeCluDescript ( ) ;
}
void ResMan : : loadCluDescript ( const char * fileName ) {
File resFile ;
resFile . open ( fileName ) ;
2004-07-11 04:41:48 +00:00
if ( ! resFile . isOpen ( ) ) {
char msg [ 512 ] ;
sprintf ( msg , " Couldn't open CLU description '%s' \n \n If you are running from CD, please ensure you have read the ScummVM documentation regarding multi-cd games. " , fileName ) ;
guiFatalError ( msg ) ;
}
2003-12-16 02:10:15 +00:00
_prj . noClu = resFile . readUint32LE ( ) ;
2004-01-11 15:47:41 +00:00
_prj . clu = new Clu * [ _prj . noClu ] ;
2003-12-16 02:10:15 +00:00
uint32 * cluIndex = ( uint32 * ) malloc ( _prj . noClu * 4 ) ;
resFile . read ( cluIndex , _prj . noClu * 4 ) ;
for ( uint32 clusCnt = 0 ; clusCnt < _prj . noClu ; clusCnt + + )
if ( cluIndex [ clusCnt ] ) {
2004-01-11 15:47:41 +00:00
Clu * cluster = _prj . clu [ clusCnt ] = new Clu ;
2003-12-16 02:10:15 +00:00
resFile . read ( cluster - > label , MAX_LABEL_SIZE ) ;
cluster - > noGrp = resFile . readUint32LE ( ) ;
2004-01-11 15:47:41 +00:00
cluster - > grp = new Grp * [ cluster - > noGrp ] ;
2003-12-16 02:10:15 +00:00
uint32 * grpIndex = ( uint32 * ) malloc ( cluster - > noGrp * 4 ) ;
resFile . read ( grpIndex , cluster - > noGrp * 4 ) ;
for ( uint32 grpCnt = 0 ; grpCnt < cluster - > noGrp ; grpCnt + + )
if ( grpIndex [ grpCnt ] ) {
2004-01-11 15:47:41 +00:00
Grp * group = cluster - > grp [ grpCnt ] = new Grp ;
2003-12-16 02:10:15 +00:00
group - > noRes = resFile . readUint32LE ( ) ;
2004-01-11 15:47:41 +00:00
group - > resHandle = new MemHandle [ group - > noRes ] ;
2003-12-16 02:10:15 +00:00
group - > offset = new uint32 [ group - > noRes ] ;
group - > length = new uint32 [ group - > noRes ] ;
uint32 * resIdIdx = ( uint32 * ) malloc ( group - > noRes * 4 ) ;
resFile . read ( resIdIdx , group - > noRes * 4 ) ;
for ( uint32 resCnt = 0 ; resCnt < group - > noRes ; resCnt + + ) {
if ( resIdIdx [ resCnt ] ) {
group - > offset [ resCnt ] = resFile . readUint32LE ( ) ;
group - > length [ resCnt ] = resFile . readUint32LE ( ) ;
_memMan - > initHandle ( group - > resHandle + resCnt ) ;
} else {
group - > offset [ resCnt ] = 0xFFFFFFFF ;
group - > length [ resCnt ] = 0 ;
_memMan - > initHandle ( group - > resHandle + resCnt ) ;
}
}
2003-12-19 14:07:12 +00:00
free ( resIdIdx ) ;
2003-12-16 02:10:15 +00:00
} else
cluster - > grp [ grpCnt ] = NULL ;
free ( grpIndex ) ;
} else
_prj . clu [ clusCnt ] = NULL ;
free ( cluIndex ) ;
2003-12-20 16:30:58 +00:00
if ( _prj . clu [ 3 ] - > grp [ 5 ] - > noRes = = 29 )
2003-12-28 19:03:35 +00:00
for ( uint8 cnt = 0 ; cnt < 29 ; cnt + + )
2003-12-20 16:30:58 +00:00
_srIdList [ cnt ] = 0x04050000 | cnt ;
2003-12-16 02:10:15 +00:00
}
void ResMan : : freeCluDescript ( void ) {
for ( uint32 clusCnt = 0 ; clusCnt < _prj . noClu ; clusCnt + + )
2004-01-11 15:47:41 +00:00
if ( Clu * cluster = _prj . clu [ clusCnt ] ) {
2003-12-16 02:10:15 +00:00
for ( uint32 grpCnt = 0 ; grpCnt < cluster - > noGrp ; grpCnt + + )
2004-01-11 15:47:41 +00:00
if ( Grp * group = cluster - > grp [ grpCnt ] ) {
2003-12-20 09:12:54 +00:00
for ( uint32 resCnt = 0 ; resCnt < group - > noRes ; resCnt + + )
_memMan - > freeNow ( group - > resHandle + resCnt ) ;
2003-12-16 02:10:15 +00:00
delete [ ] group - > resHandle ;
delete [ ] group - > offset ;
delete [ ] group - > length ;
delete group ;
}
delete [ ] cluster - > grp ;
delete cluster ;
}
delete [ ] _prj . clu ;
}
2003-12-20 09:12:54 +00:00
void ResMan : : flush ( void ) {
for ( uint32 clusCnt = 0 ; clusCnt < _prj . noClu ; clusCnt + + )
2004-01-11 15:47:41 +00:00
if ( Clu * cluster = _prj . clu [ clusCnt ] )
2003-12-20 09:12:54 +00:00
for ( uint32 grpCnt = 0 ; grpCnt < cluster - > noGrp ; grpCnt + + )
2004-01-11 15:47:41 +00:00
if ( Grp * group = cluster - > grp [ grpCnt ] )
2003-12-20 09:12:54 +00:00
for ( uint32 resCnt = 0 ; resCnt < group - > noRes ; resCnt + + )
if ( group - > resHandle [ resCnt ] . cond ! = MEM_FREED ) {
_memMan - > setCondition ( group - > resHandle + resCnt , MEM_CAN_FREE ) ;
group - > resHandle [ resCnt ] . refCount = 0 ;
}
}
2003-12-16 02:10:15 +00:00
void * ResMan : : fetchRes ( uint32 id ) {
2004-01-11 15:47:41 +00:00
MemHandle * memHandle = resHandle ( id ) ;
2003-12-16 02:10:15 +00:00
if ( ! memHandle - > data )
error ( " fetchRes:: resource %d is not open! " , id ) ;
return memHandle - > data ;
}
void * ResMan : : openFetchRes ( uint32 id ) {
resOpen ( id ) ;
return fetchRes ( id ) ;
}
void ResMan : : dumpRes ( uint32 id ) {
char outn [ 30 ] ;
sprintf ( outn , " DUMP%08X.BIN " , id ) ;
2004-01-11 16:27:36 +00:00
File outf ;
2004-06-27 22:14:35 +00:00
if ( outf . open ( outn , File : : kFileWriteMode , " " ) ) {
2004-01-11 16:27:36 +00:00
resOpen ( id ) ;
MemHandle * memHandle = resHandle ( id ) ;
outf . write ( memHandle - > data , memHandle - > size ) ;
outf . close ( ) ;
resClose ( id ) ;
}
2003-12-16 02:10:15 +00:00
}
Header * ResMan : : lockScript ( uint32 scrID ) {
if ( ! _scriptList [ scrID / ITM_PER_SEC ] )
error ( " Script id %d not found. \n " , scrID ) ;
scrID = _scriptList [ scrID / ITM_PER_SEC ] ;
# ifdef SCUMM_BIG_ENDIAN
2004-01-11 15:47:41 +00:00
MemHandle * memHandle = resHandle ( scrID ) ;
2003-12-16 02:10:15 +00:00
if ( memHandle - > cond = = MEM_FREED )
openScriptResourceBigEndian ( scrID ) ;
else
resOpen ( scrID ) ;
# else
resOpen ( scrID ) ;
# endif
return ( Header * ) resHandle ( scrID ) - > data ;
}
void ResMan : : unlockScript ( uint32 scrID ) {
resClose ( _scriptList [ scrID / ITM_PER_SEC ] ) ;
}
void * ResMan : : cptResOpen ( uint32 id ) {
# ifdef SCUMM_BIG_ENDIAN
2004-01-11 15:47:41 +00:00
MemHandle * memHandle = resHandle ( id ) ;
2003-12-16 02:10:15 +00:00
if ( memHandle - > cond = = MEM_FREED )
openCptResourceBigEndian ( id ) ;
else
resOpen ( id ) ;
# else
resOpen ( id ) ;
# endif
return resHandle ( id ) - > data ;
}
void ResMan : : resOpen ( uint32 id ) { // load resource ID into memory
2004-01-11 15:47:41 +00:00
MemHandle * memHandle = resHandle ( id ) ;
2003-12-16 02:10:15 +00:00
if ( memHandle - > cond = = MEM_FREED ) { // memory has been freed
uint32 size = resLength ( id ) ;
_memMan - > alloc ( memHandle , size ) ;
File * clusFile = openClusterFile ( id ) ;
clusFile - > seek ( resOffset ( id ) ) ;
clusFile - > read ( memHandle - > data , size ) ;
if ( clusFile - > ioFailed ( ) )
error ( " Can't read %d bytes from cluster %d \n " , size , id ) ;
clusFile - > close ( ) ;
delete clusFile ;
} else
_memMan - > setCondition ( memHandle , MEM_DONT_FREE ) ;
memHandle - > refCount + + ;
if ( memHandle - > refCount > 20 ) {
debug ( 1 , " %d references to id %d. Guess there's something wrong. " , memHandle - > refCount , id ) ;
}
}
void ResMan : : resClose ( uint32 id ) {
2004-01-11 15:47:41 +00:00
MemHandle * handle = resHandle ( id ) ;
2003-12-16 02:10:15 +00:00
if ( ! handle - > refCount ) {
warning ( " Resource Manager fail: unlocking object with refCount 0. Id: %d \n " , id ) ;
2003-12-20 09:12:54 +00:00
} else {
2003-12-16 02:10:15 +00:00
handle - > refCount - - ;
2003-12-20 09:12:54 +00:00
if ( ! handle - > refCount )
_memMan - > setCondition ( handle , MEM_CAN_FREE ) ;
}
2003-12-16 02:10:15 +00:00
}
FrameHeader * ResMan : : fetchFrame ( void * resourceData , uint32 frameNo ) {
uint8 * frameFile = ( uint8 * ) resourceData ;
2003-12-19 14:07:12 +00:00
uint8 * idxData = frameFile + sizeof ( Header ) ;
2003-12-16 02:10:15 +00:00
if ( frameNo > = READ_LE_UINT32 ( idxData ) )
error ( " fetchFrame:: frame %d doesn't exist in resource. " , frameNo ) ;
frameFile + = READ_LE_UINT32 ( idxData + ( frameNo + 1 ) * 4 ) ;
return ( FrameHeader * ) frameFile ;
}
File * ResMan : : openClusterFile ( uint32 id ) {
2003-12-17 01:47:47 +00:00
File * clusFile = new File ( ) ;
2003-12-16 02:10:15 +00:00
char fileName [ 15 ] ;
sprintf ( fileName , " %s.CLU " , _prj . clu [ ( id > > 24 ) - 1 ] - > label ) ;
clusFile - > open ( fileName ) ;
2004-07-11 04:41:48 +00:00
if ( ! clusFile - > isOpen ( ) ) {
char msg [ 512 ] ;
sprintf ( msg , " Couldn't open game cluster file '%s' \n \n If you are running from CD, please ensure you have read the ScummVM documentation regarding multi-cd games. " , fileName ) ;
guiFatalError ( msg ) ;
}
2003-12-16 02:10:15 +00:00
return clusFile ;
}
2004-01-11 15:47:41 +00:00
MemHandle * ResMan : : resHandle ( uint32 id ) {
2003-12-20 16:30:58 +00:00
if ( ( id > > 16 ) = = 0x0405 )
id = _srIdList [ id & 0xFFFF ] ;
2003-12-29 15:54:06 +00:00
uint8 cluster = ( uint8 ) ( ( id > > 24 ) - 1 ) ;
uint8 group = ( uint8 ) ( id > > 16 ) ;
2003-12-16 02:10:15 +00:00
return & ( _prj . clu [ cluster ] - > grp [ group ] - > resHandle [ id & 0xFFFF ] ) ;
}
uint32 ResMan : : resLength ( uint32 id ) {
2003-12-20 16:30:58 +00:00
if ( ( id > > 16 ) = = 0x0405 )
id = _srIdList [ id & 0xFFFF ] ;
2003-12-29 15:54:06 +00:00
uint8 cluster = ( uint8 ) ( ( id > > 24 ) - 1 ) ;
uint8 group = ( uint8 ) ( id > > 16 ) ;
2003-12-16 02:10:15 +00:00
return _prj . clu [ cluster ] - > grp [ group ] - > length [ id & 0xFFFF ] ;
}
uint32 ResMan : : resOffset ( uint32 id ) {
2003-12-20 16:30:58 +00:00
if ( ( id > > 16 ) = = 0x0405 )
id = _srIdList [ id & 0xFFFF ] ;
2003-12-29 15:54:06 +00:00
uint8 cluster = ( uint8 ) ( ( id > > 24 ) - 1 ) ;
uint8 group = ( uint8 ) ( id > > 16 ) ;
2003-12-16 02:10:15 +00:00
return _prj . clu [ cluster ] - > grp [ group ] - > offset [ id & 0xFFFF ] ;
}
void ResMan : : openCptResourceBigEndian ( uint32 id ) {
resOpen ( id ) ;
2004-01-11 15:47:41 +00:00
MemHandle * handle = resHandle ( id ) ;
2003-12-16 02:10:15 +00:00
uint32 totSize = handle - > size ;
2003-12-18 01:15:15 +00:00
uint32 * data = ( uint32 * ) ( ( uint8 * ) handle - > data + sizeof ( Header ) ) ;
2003-12-16 02:10:15 +00:00
totSize - = sizeof ( Header ) ;
2003-12-18 01:15:15 +00:00
if ( totSize & 3 )
error ( " Illegal compact size for id %d: %d " , id , totSize ) ;
totSize / = 4 ;
for ( uint32 cnt = 0 ; cnt < totSize ; cnt + + ) {
* data = READ_LE_UINT32 ( data ) ;
data + + ;
2003-12-16 02:10:15 +00:00
}
}
void ResMan : : openScriptResourceBigEndian ( uint32 id ) {
resOpen ( id ) ;
2004-01-11 15:47:41 +00:00
MemHandle * handle = resHandle ( id ) ;
2003-12-16 09:43:08 +00:00
// uint32 totSize = handle->size;
2003-12-16 02:10:15 +00:00
Header * head = ( Header * ) handle - > data ;
2004-10-21 13:23:52 +00:00
head - > comp_length = FROM_LE_32 ( head - > comp_length ) ;
head - > decomp_length = FROM_LE_32 ( head - > decomp_length ) ;
head - > version = FROM_LE_16 ( head - > version ) ;
2003-12-16 02:10:15 +00:00
uint32 * data = ( uint32 * ) ( ( uint8 * ) handle - > data + sizeof ( Header ) ) ;
uint32 size = handle - > size - sizeof ( Header ) ;
if ( size & 3 )
error ( " Odd size during script endian conversion. Resource ID =%d, size = %d " , id , size ) ;
size > > = 2 ;
for ( uint32 cnt = 0 ; cnt < size ; cnt + + ) {
* data = READ_LE_UINT32 ( data ) ;
data + + ;
}
}
2003-12-20 16:30:58 +00:00
uint32 ResMan : : _srIdList [ 29 ] = { // the file numbers differ for the control panel file IDs, so we need this array
2003-12-29 16:08:05 +00:00
OTHER_SR_FONT , // SR_FONT
0x04050000 , // SR_BUTTON
OTHER_SR_REDFONT , // SR_REDFONT
0x04050001 , // SR_PALETTE
0x04050002 , // SR_PANEL_ENGLISH
0x04050003 , // SR_PANEL_FRENCH
0x04050004 , // SR_PANEL_GERMAN
0x04050005 , // SR_PANEL_ITALIAN
0x04050006 , // SR_PANEL_SPANISH
0x04050007 , // SR_PANEL_AMERICAN
0x04050008 , // SR_TEXT_BUTTON
0x04050009 , // SR_SPEED
0x0405000A , // SR_SCROLL1
0x0405000B , // SR_SCROLL2
0x0405000C , // SR_CONFIRM
0x0405000D , // SR_VOLUME
0x0405000E , // SR_VLIGHT
0x0405000F , // SR_VKNOB
0x04050010 , // SR_WINDOW
0x04050011 , // SR_SLAB1
0x04050012 , // SR_SLAB2
0x04050013 , // SR_SLAB3
0x04050014 , // SR_SLAB4
0x04050015 , // SR_BUTUF
0x04050016 , // SR_BUTUS
0x04050017 , // SR_BUTDS
0x04050018 , // SR_BUTDF
0x04050019 , // SR_DEATHPANEL
2003-12-20 16:30:58 +00:00
0 ,
} ;
2004-01-11 15:47:41 +00:00
} // End of namespace Sword1