diff options
Diffstat (limited to 'engines/kyra')
-rw-r--r-- | engines/kyra/kyra.cpp | 12 | ||||
-rw-r--r-- | engines/kyra/kyra.h | 142 | ||||
-rw-r--r-- | engines/kyra/resource.cpp | 8 | ||||
-rw-r--r-- | engines/kyra/resource.h | 173 | ||||
-rw-r--r-- | engines/kyra/script_v1.cpp | 2 | ||||
-rw-r--r-- | engines/kyra/sequences_v1.cpp | 3 | ||||
-rw-r--r-- | engines/kyra/staticres.cpp | 852 | ||||
-rw-r--r-- | engines/kyra/text.cpp | 10 | ||||
-rw-r--r-- | engines/kyra/text.h | 2 |
9 files changed, 763 insertions, 441 deletions
diff --git a/engines/kyra/kyra.cpp b/engines/kyra/kyra.cpp index f208d35238..f41ef760ed 100644 --- a/engines/kyra/kyra.cpp +++ b/engines/kyra/kyra.cpp @@ -228,7 +228,8 @@ KyraEngine::KyraEngine(GameDetector *detector, OSystem *system) _thePoison_Size = _fluteString_Size = _wispJewelStrings_Size = 0; _magicJewelString_Size = _flaskFull_Size = _fullFlask_Size = 0; - _defaultShapeTable = _healingShapeTable = _healingShape2Table = 0; + _defaultShapeTable = 0; + _healingShapeTable = _healingShape2Table = 0; _defaultShapeTableSize = _healingShapeTableSize = _healingShape2TableSize = 0; _posionDeathShapeTable = _fluteAnimShapeTable = 0; _posionDeathShapeTableSize = _fluteAnimShapeTableSize = 0; @@ -236,6 +237,7 @@ KyraEngine::KyraEngine(GameDetector *detector, OSystem *system) _winterScrollTableSize = _winterScroll1TableSize = _winterScroll2TableSize = 0; _drinkAnimationTable = _brandonToWispTable = _magicAnimationTable = _brandonStoneTable = 0; _drinkAnimationTableSize = _brandonToWispTableSize = _magicAnimationTableSize = _brandonStoneTableSize = 0; + memset(&_specialPalettes, 0, sizeof(_specialPalettes)); // Setup mixer if (!_mixer->isReady()) { @@ -369,6 +371,10 @@ int KyraEngine::init(GameDetector &detector) { assert(*_animator); _text = new TextDisplayer(_screen); assert(_text); + _staticres = new StaticResource(this); + assert(_staticres); + assert(_staticres->init()); + initStaticResource(); _paletteChanged = 1; _currentCharacter = 0; @@ -482,7 +488,6 @@ int KyraEngine::init(GameDetector &detector) { _kyragemFadingState.gOffset = 0x13; _kyragemFadingState.bOffset = 0x13; - memset(_specialPalettes, 0, sizeof(_specialPalettes)); _mousePressFlag = false; _targetName = detector._targetName; @@ -555,7 +560,6 @@ int KyraEngine::go() { _quitFlag = false; uint32 sz; - res_loadResources(); if (_features & GF_FLOPPY && !(_features & GF_AMIGA)) { _screen->loadFont(Screen::FID_6_FNT, _res->fileData("6.FNT", &sz)); } @@ -709,8 +713,6 @@ void KyraEngine::mainLoop() { void KyraEngine::quitGame() { debugC(9, kDebugLevelMain, "KyraEngine::quitGame()"); - res_unloadResources(RES_ALL); - for (int i = 0; i < ARRAYSIZE(_movieObjects); ++i) { _movieObjects[i]->close(); delete _movieObjects[i]; diff --git a/engines/kyra/kyra.h b/engines/kyra/kyra.h index a308c56ae9..96c3468da1 100644 --- a/engines/kyra/kyra.h +++ b/engines/kyra/kyra.h @@ -42,6 +42,7 @@ class Debugger; class ScreenAnimator; class TextDisplayer; class KyraEngine; +class StaticResource; struct ScriptState; struct ScriptData; @@ -255,6 +256,7 @@ public: ScreenAnimator *animator() { return _animator; } TextDisplayer *text() { return _text; } Sound *sound() { return _sound; } + StaticResource *staticres() { return _staticres; } uint32 tickLength() const { return _tickLength; } Movie *createWSAMovie(); @@ -273,13 +275,13 @@ public: typedef void (KyraEngine::*IntroProc)(); typedef int (KyraEngine::*OpcodeProc)(ScriptState *script); - const char **seqWSATable() { return const_cast<const char **>(_seq_WSATable); } - const char **seqCPSTable() { return const_cast<const char **>(_seq_CPSTable); } - const char **seqCOLTable() { return const_cast<const char **>(_seq_COLTable); } - const char **seqTextsTable() { return const_cast<const char **>(_seq_textsTable); } + const char **seqWSATable() { return _seq_WSATable; } + const char **seqCPSTable() { return _seq_CPSTable; } + const char **seqCOLTable() { return _seq_COLTable; } + const char **seqTextsTable() { return _seq_textsTable; } - const uint8 **palTable1() { return const_cast<const uint8 **>(&_specialPalettes[0]); } - const uint8 **palTable2() { return const_cast<const uint8 **>(&_specialPalettes[29]); } + const uint8 **palTable1() { return &_specialPalettes[0]; } + const uint8 **palTable2() { return &_specialPalettes[29]; } bool seq_skipSequence() const; void delay(uint32 millis, bool update = false, bool mainLoop = false); @@ -292,8 +294,8 @@ public: void snd_playSoundEffect(int track); void snd_playWanderScoreViaMap(int command, int restart); - void drawSentenceCommand(char *sentence, int unk1); - void updateSentenceCommand(char *str1, char *str2, int unk1); + void drawSentenceCommand(const char *sentence, int unk1); + void updateSentenceCommand(const char *str1, const char *str2, int unk1); void updateTextFade(); void updateGameTimers(); @@ -483,8 +485,8 @@ protected: void backupChatPartnerAnimFrame(int8 charNum); void restoreChatPartnerAnimFrame(int8 charNum); void endCharacterChat(int8 charNum, int16 arg_4); - void waitForChatToFinish(int16 chatDuration, char *str, uint8 charNum); - void characterSays(char *chatStr, int8 charNum, int8 chatDuration); + void waitForChatToFinish(int16 chatDuration, const char *str, uint8 charNum); + void characterSays(const char *chatStr, int8 charNum, int8 chatDuration); void setCharactersPositions(int character); int setGameFlag(int flag); @@ -591,21 +593,6 @@ protected: static OpcodeProc _opcodeTable[]; static const int _opcodeTableSize; - enum { - RES_ALL = 0, - RES_INTRO = (1 << 0), - RES_INGAME = (1 << 1), - RES_OUTRO = (1 << 2) - }; - - void res_loadResources(int type = RES_ALL); - void res_unloadResources(int type = RES_ALL); - void res_loadLangTable(const char *filename, PAKFile *res, byte ***loadTo, int *size, bool nativ); - void res_loadTable(const byte *src, byte ***loadTo, int *size); - void res_loadRoomTable(const byte *src, Room **loadTo, int *size); - void res_loadShapeTable(const byte *src, Shape **loadTo, int *size); - void res_freeLangTable(char ***sting, int *size); - void waitForEvent(); void loadPalette(const char *filename, uint8 *palData); void loadMouseShapes(); @@ -809,6 +796,7 @@ protected: TextDisplayer *_text; ScriptHelper *_scriptInterpreter; Debugger *_debugger; + StaticResource *_staticres; Common::SaveFileManager *_saveFileMan; ScriptState *_scriptMain; @@ -843,46 +831,50 @@ protected: uint32 timerCount; } _kyragemFadingState; - uint8 *_seq_Forest; - uint8 *_seq_KallakWriting; - uint8 *_seq_KyrandiaLogo; - uint8 *_seq_KallakMalcolm; - uint8 *_seq_MalcolmTree; - uint8 *_seq_WestwoodLogo; - uint8 *_seq_Demo1; - uint8 *_seq_Demo2; - uint8 *_seq_Demo3; - uint8 *_seq_Demo4; - uint8 *_seq_Reunion; - - char **_seq_WSATable; - char **_seq_CPSTable; - char **_seq_COLTable; - char **_seq_textsTable; + // TODO: get rid of all variables having pointers to the static resources if possible + // i.e. let them directly use the _staticres functions + void initStaticResource(); + + const uint8 *_seq_Forest; + const uint8 *_seq_KallakWriting; + const uint8 *_seq_KyrandiaLogo; + const uint8 *_seq_KallakMalcolm; + const uint8 *_seq_MalcolmTree; + const uint8 *_seq_WestwoodLogo; + const uint8 *_seq_Demo1; + const uint8 *_seq_Demo2; + const uint8 *_seq_Demo3; + const uint8 *_seq_Demo4; + const uint8 *_seq_Reunion; + + const char **_seq_WSATable; + const char **_seq_CPSTable; + const char **_seq_COLTable; + const char **_seq_textsTable; int _seq_WSATable_Size; int _seq_CPSTable_Size; int _seq_COLTable_Size; int _seq_textsTable_Size; - char **_itemList; - char **_takenList; - char **_placedList; - char **_droppedList; - char **_noDropList; - char **_putDownFirst; - char **_waitForAmulet; - char **_blackJewel; - char **_poisonGone; - char **_healingTip; - char **_thePoison; - char **_fluteString; - char **_wispJewelStrings; - char **_magicJewelString; - char **_flaskFull; - char **_fullFlask; - char **_veryClever; - char **_homeString; + const char **_itemList; + const char **_takenList; + const char **_placedList; + const char **_droppedList; + const char **_noDropList; + const char **_putDownFirst; + const char **_waitForAmulet; + const char **_blackJewel; + const char **_poisonGone; + const char **_healingTip; + const char **_thePoison; + const char **_fluteString; + const char **_wispJewelStrings; + const char **_magicJewelString; + const char **_flaskFull; + const char **_fullFlask; + const char **_veryClever; + const char **_homeString; int _itemList_Size; int _takenList_Size; @@ -903,50 +895,50 @@ protected: int _veryClever_Size; int _homeString_Size; - char **_characterImageTable; + const char **_characterImageTable; int _characterImageTableSize; Shape *_defaultShapeTable; int _defaultShapeTableSize; - Shape *_healingShapeTable; + const Shape *_healingShapeTable; int _healingShapeTableSize; - Shape *_healingShape2Table; + const Shape *_healingShape2Table; int _healingShape2TableSize; - Shape *_posionDeathShapeTable; + const Shape *_posionDeathShapeTable; int _posionDeathShapeTableSize; - Shape *_fluteAnimShapeTable; + const Shape *_fluteAnimShapeTable; int _fluteAnimShapeTableSize; - Shape *_winterScrollTable; + const Shape *_winterScrollTable; int _winterScrollTableSize; - Shape *_winterScroll1Table; + const Shape *_winterScroll1Table; int _winterScroll1TableSize; - Shape *_winterScroll2Table; + const Shape *_winterScroll2Table; int _winterScroll2TableSize; - Shape *_drinkAnimationTable; + const Shape *_drinkAnimationTable; int _drinkAnimationTableSize; - Shape *_brandonToWispTable; + const Shape *_brandonToWispTable; int _brandonToWispTableSize; - Shape *_magicAnimationTable; + const Shape *_magicAnimationTable; int _magicAnimationTableSize; - Shape *_brandonStoneTable; + const Shape *_brandonStoneTable; int _brandonStoneTableSize; Room *_roomTable; - int _roomTableSize; - char **_roomFilenameTable; + int _roomTableSize; + const char **_roomFilenameTable; int _roomFilenameTableSize; - uint8 *_amuleteAnim; + const uint8 *_amuleteAnim; - uint8 *_specialPalettes[33]; + const uint8 **_specialPalettes; Timer _timers[34]; uint32 _timerNextRun; diff --git a/engines/kyra/resource.cpp b/engines/kyra/resource.cpp index c5b40db281..4e95ba1db1 100644 --- a/engines/kyra/resource.cpp +++ b/engines/kyra/resource.cpp @@ -117,6 +117,11 @@ Resource::Resource(KyraEngine *engine) { debug(3, "couldn't load file '%s' correctly", usedFilelist[tmp]); } } + + // we're loading KYRA.DAT here too + if (!loadPakFile("KYRA.DAT")) { + error("couldn't open Kyrandia resource file ('KYRA.DAT') make sure you got one file for your version"); + } } Resource::~Resource() { @@ -133,7 +138,8 @@ bool Resource::loadPakFile(const char *filename) { return true; PAKFile *file = new PAKFile(filename); if (!file) { - error("couldn't load file: '%s'", filename); + warning("couldn't load file: '%s'", filename); + return false; } PakFileEntry newPak; newPak._file = file; diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h index 6319e31477..6520fe609f 100644 --- a/engines/kyra/resource.h +++ b/engines/kyra/resource.h @@ -61,13 +61,8 @@ private: Common::List<PakChunk*> _files; // the entries }; -// some resource types -class Movie; -class VMContext; - class Resource { public: - Resource(KyraEngine *engine); ~Resource(); @@ -91,6 +86,174 @@ protected: Common::List<PakFileEntry> _pakfiles; }; +// TODO?: maybe prefix all things here with 'kKyra1' instead of 'k' +enum kKyraResources { + kLoadAll = -1, + + kForestSeq, + kKallakWritingSeq, + kKyrandiaLogoSeq, + kKallakMalcolmSeq, + kMalcolmTreeSeq, + kWestwoodLogoSeq, + + kDemo1Seq, + kDemo2Seq, + kDemo3Seq, + kDemo4Seq, + + kAmuleteAnimSeq, + + kOutroReunionSeq, + + kIntroCPSStrings, + kIntroCOLStrings, + kIntroWSAStrings, + kIntroStrings, + + kOutroHomeString, + + kRoomFilenames, + kRoomList, + + kCharacterImageFilenames, + + kItemNames, + kTakenStrings, + kPlacedStrings, + kDroppedStrings, + kNoDropStrings, + + kPutDownString, + kWaitAmuletString, + kBlackJewelString, + kPoisonGoneString, + kHealingTipString, + kWispJewelStrings, + kMagicJewelStrings, + + kThePoisonStrings, + kFluteStrings, + + kFlaskFullString, + kFullFlaskString, + + kVeryCleverString, + + kDefaultShapes, + kHealing1Shapes, + kHealing2Shapes, + kPoisonDeathShapes, + kFluteShapes, + kWinter1Shapes, + kWinter2Shapes, + kWinter3Shapes, + kDrinkShapes, + kWispShapes, + kMagicAnimShapes, + kBranStoneShapes, + + kPaletteList, + + kMaxResIDs +}; + +struct Shape; +struct Room; + +class StaticResource { +public: + StaticResource(KyraEngine *engine) : _engine(engine), _resList(), _fileLoader(0), _builtIn(0), _filenameTable(0) {} + ~StaticResource() { deinit(); } + + bool init(); + void deinit(); + + const char **loadStrings(int id, int &strings); + const uint8 *loadRawData(int id, int &size); + const Shape *loadShapeTable(int id, int &entries); + const Room *loadRoomTable(int id, int &entries); + const uint8 **loadPaletteTable(int id, int &entries); + + // use '-1' to prefetch/unload all ids + // prefetchId retruns false if only on of the resources + // can't be loaded and it breaks then the first res + // can't be loaded + bool prefetchId(int id); + void unloadId(int id); +private: + KyraEngine *_engine; + + struct FilenameTable; + struct ResData; + struct FileType; + + bool checkResList(int id, int &type, const void *&ptr, int &size); + const void *checkForBuiltin(int id, int &type, int &size); + const FilenameTable *searchFile(int id); + const FileType *getFiletype(int type); + const void *getData(int id, int requesttype, int &size); + + bool loadLanguageTable(const char *filename, void *&ptr, int &size); + bool loadStringTable(const char *filename, void *&ptr, int &size); + bool loadRawData(const char *filename, void *&ptr, int &size); + bool loadShapeTable(const char *filename, void *&ptr, int &size); + bool loadRoomTable(const char *filename, void *&ptr, int &size); + bool loadPaletteTable(const char *filename, void *&ptr, int &size); + + void freeRawData(void *&ptr, int &size); + void freeStringTable(void *&ptr, int &size); + void freeShapeTable(void *&ptr, int &size); + void freeRoomTable(void *&ptr, int &size); + void freePaletteTable(void *&ptr, int &size); + + uint8 *getFile(const char *name, int &size); + + enum kResTypes { + kLanguageList, + kStringList, + kRoomList, + kShapeList, + kRawData, + kPaletteTable + }; + + struct BuiltinRes { + int id; + int type; + int size; + const void *data; + }; + + struct FilenameTable { + int id; + int type; + const char *filename; + }; + + struct FileType { + int type; + typedef bool (StaticResource::*LoadFunc)(const char *filename, void *&ptr, int &size); + typedef void (StaticResource::*FreeFunc)(void *&ptr, int &size); + + LoadFunc load; + FreeFunc free; + }; + + struct ResData { + int id; + int type; + int size; + void *data; + }; + + Common::List<ResData> _resList; + + const FileType *_fileLoader; + const BuiltinRes *_builtIn; + const FilenameTable *_filenameTable; +}; + } // end of namespace Kyra #endif diff --git a/engines/kyra/script_v1.cpp b/engines/kyra/script_v1.cpp index 3f29038948..920d730858 100644 --- a/engines/kyra/script_v1.cpp +++ b/engines/kyra/script_v1.cpp @@ -1221,7 +1221,7 @@ int KyraEngine::cmd_setFireberryGlowPalette(ScriptState *script) { palIndex = 14; } } - uint8 *palette = _specialPalettes[palIndex]; + const uint8 *palette = _specialPalettes[palIndex]; memcpy(&_screen->_currentPalette[684], palette, 44); _screen->setScreenPalette(_screen->_currentPalette); return 0; diff --git a/engines/kyra/sequences_v1.cpp b/engines/kyra/sequences_v1.cpp index 1077a4a62c..2e68e1966f 100644 --- a/engines/kyra/sequences_v1.cpp +++ b/engines/kyra/sequences_v1.cpp @@ -121,7 +121,6 @@ void KyraEngine::seq_intro() { if (_features & GF_TALKIE) { _res->unloadPakFile("INTRO.VRM"); } - res_unloadResources(RES_INTRO | RES_OUTRO); } void KyraEngine::seq_introLogos() { @@ -982,8 +981,6 @@ void KyraEngine::seq_brandonToStone() { void KyraEngine::seq_playEnding() { debugC(9, kDebugLevelMain, "KyraEngine::seq_playEnding()"); _screen->hideMouse(); - res_unloadResources(RES_INGAME); - res_loadResources(RES_OUTRO); loadBitmap("REUNION.CPS", 3, 3, _screen->_currentPalette); _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0); _screen->_curPage = 0; diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index 26f2165d1f..ddbdbd5d93 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -32,14 +32,6 @@ namespace Kyra { #define GAME_FLAGS (GF_FLOPPY | GF_TALKIE | GF_DEMO | GF_AUDIOCD) #define LANGUAGE_FLAGS (GF_ENGLISH | GF_FRENCH | GF_GERMAN | GF_SPANISH | GF_LNGUNK) -byte *getFile(PAKFile &res, const char *filename) { - uint32 size = 0; - size = res.getFileSize(filename); - if (!size) - return 0; - return res.getFile(filename); -} - struct LanguageTypes { uint32 flags; const char *ext; @@ -53,34 +45,107 @@ static LanguageTypes languages[] = { { 0, 0 } }; -void KyraEngine::res_loadResources(int type) { - debugC(9, kDebugLevelMain, "KyraEngine::res_loadResources(%d)", type); - PAKFile resFile("KYRA.DAT"); - if (!resFile.isValid() || !resFile.isOpen()) { - error("couldn't open Kyrandia resource file ('KYRA.DAT') make sure you got one file for your version"); - } - - uint32 version = 0; - uint32 gameID = 0; - uint32 featuresValue = 0; - bool loadNativeLanguage = true; - - byte *temp = 0; - - if (_features & GF_TALKIE) { - temp = getFile(resFile, "INDEX.CD"); - } else if (_features & GF_DEMO) { - temp = getFile(resFile, "INDEX.DEM"); +bool StaticResource::init() { +#define proc(x) &StaticResource::x + static const FileType fileTypeTable[] = { + { kLanguageList, proc(loadLanguageTable), proc(freeStringTable) }, + { kStringList, proc(loadStringTable), proc(freeStringTable) }, + { StaticResource::kRoomList, proc(loadRoomTable), proc(freeRoomTable) }, + { kShapeList, proc(loadShapeTable), proc(freeShapeTable) }, + { kRawData, proc(loadRawData), proc(freeRawData) }, + { kPaletteTable, proc(loadPaletteTable), proc(freePaletteTable) }, + { 0, 0, 0 } + }; +#undef proc + _fileLoader = fileTypeTable; + + // Kyrandia 1 Filenames + static const FilenameTable kyra1StaticRes[] = { + // INTRO / OUTRO sequences + { kForestSeq, kRawData, "FOREST.SEQ" }, + { kKallakWritingSeq, kRawData, "KALLAK-WRITING.SEQ" }, + { kKyrandiaLogoSeq, kRawData, "KYRANDIA-LOGO.SEQ" }, + { kKallakMalcolmSeq, kRawData, "KALLAK-MALCOLM.SEQ" }, + { kMalcolmTreeSeq, kRawData, "MALCOLM-TREE.SEQ" }, + { kWestwoodLogoSeq, kRawData, "WESTWOOD-LOGO.SEQ" }, + { kDemo1Seq, kRawData, "DEMO1.SEQ" }, + { kDemo2Seq, kRawData, "DEMO2.SEQ" }, + { kDemo3Seq, kRawData, "DEMO3.SEQ" }, + { kDemo4Seq, kRawData, "DEMO4.SEQ" }, + { kOutroReunionSeq, kRawData, "REUNION.SEQ" }, + + // INTRO / OUTRO strings + { kIntroCPSStrings, kStringList, "INTRO-CPS.TXT" }, + { kIntroCOLStrings, kStringList, "INTRO-COL.TXT" }, + { kIntroWSAStrings, kStringList, "INTRO-WSA.TXT" }, + { kIntroStrings, kLanguageList, "INTRO-STRINGS." }, + { kOutroHomeString, kLanguageList, "HOME." }, + + // INGAME strings + { kItemNames, kLanguageList, "ITEMLIST." }, + { kTakenStrings, kLanguageList, "TAKEN." }, + { kPlacedStrings, kLanguageList, "PLACED." }, + { kDroppedStrings, kLanguageList, "DROPPED." }, + { kNoDropStrings, kLanguageList, "NODROP." }, + { kPutDownString, kLanguageList, "PUTDOWN." }, + { kWaitAmuletString, kLanguageList, "WAITAMUL." }, + { kBlackJewelString, kLanguageList, "BLACKJEWEL." }, + { kPoisonGoneString, kLanguageList, "POISONGONE." }, + { kHealingTipString, kLanguageList, "HEALINGTIP." }, + { kThePoisonStrings, kLanguageList, "THEPOISON." }, + { kFluteStrings, kLanguageList, "FLUTE." }, + { kWispJewelStrings, kLanguageList, "WISPJEWEL." }, + { kMagicJewelStrings, kLanguageList, "MAGICJEWEL." }, + { kFlaskFullString, kLanguageList, "FLASKFULL." }, + { kFullFlaskString, kLanguageList, "FULLFLASK." }, + { kVeryCleverString, kLanguageList, "VERYCLEVER." }, + + // ROOM table/filenames + { Kyra::kRoomList, StaticResource::kRoomList, "ROOM-TABLE.ROOM" }, + { kRoomFilenames, kStringList, "ROOM-FILENAMES.TXT" }, + + // SHAPE tables + { kDefaultShapes, kShapeList, "SHAPES-DEFAULT.SHP" }, + { kHealing1Shapes, kShapeList, "HEALING.SHP" }, + { kHealing2Shapes, kShapeList, "HEALING2.SHP" }, + { kPoisonDeathShapes, kShapeList, "POISONDEATH.SHP" }, + { kFluteShapes, kShapeList, "FLUTE.SHP" }, + { kWinter1Shapes, kShapeList, "WINTER1.SHP" }, + { kWinter2Shapes, kShapeList, "WINTER2.SHP" }, + { kWinter3Shapes, kShapeList, "WINTER3.SHP" }, + { kDrinkShapes, kShapeList, "DRINK.SHP" }, + { kWispShapes, kShapeList, "WISP.SHP" }, + { kMagicAnimShapes, kShapeList, "MAGICANIM.SHP" }, + { kBranStoneShapes, kShapeList, "BRANSTONE.SHP" }, + + // IMAGE filename table + { kCharacterImageFilenames, kStringList, "CHAR-IMAGE.TXT" }, + + // AMULET anim + { kAmuleteAnimSeq, kRawData, "AMULETEANIM.SEQ" }, + + // PALETTE table + { kPaletteList, kPaletteTable, "1 33 PALTABLE" }, + + { 0, 0, 0 } + }; + + if (_engine->game() == GI_KYRA1) { + _builtIn = 0; + _filenameTable = kyra1StaticRes; } else { - temp = getFile(resFile, "INDEX"); + error("unknown game ID"); } + + int tempSize = 0; + uint8 *temp = getFile("INDEX", tempSize); if (!temp) { error("no matching INDEX file found"); } - version = READ_BE_UINT32(temp); - gameID = READ_BE_UINT32((temp+4)); - featuresValue = READ_BE_UINT32((temp+8)); + uint32 version = READ_BE_UINT32(temp); + uint32 gameID = READ_BE_UINT32((temp+4)); + uint32 featuresValue = READ_BE_UINT32((temp+8)); delete [] temp; temp = 0; @@ -88,370 +153,467 @@ void KyraEngine::res_loadResources(int type) { if (version < RESFILE_VERSION) { error("invalid KYRA.DAT file version (%d, required %d)", version, RESFILE_VERSION); } - if (gameID != _game) { + if (gameID != _engine->game()) { error("invalid game id (%d)", gameID); } - if ((featuresValue & GAME_FLAGS) != (_features & GAME_FLAGS)) { - error("your data file has a different game flags (0x%.08X has the data and your version has 0x%.08X)", (featuresValue & GAME_FLAGS), (_features & GAME_FLAGS)); + if ((featuresValue & GAME_FLAGS) != (_engine->features() & GAME_FLAGS)) { + error("your data file has a different game flags (0x%.08X has the data and your version has 0x%.08X)", (featuresValue & GAME_FLAGS), (_engine->features() & GAME_FLAGS)); } - - if (!((featuresValue & LANGUAGE_FLAGS) & (_features & LANGUAGE_FLAGS))) { - char buffer[240]; - sprintf(buffer, "your data file has support for:"); - if (featuresValue & GF_ENGLISH) { - sprintf(buffer + strlen(buffer), " English"); - } - if (featuresValue & GF_FRENCH) { - sprintf(buffer + strlen(buffer), " French"); - } - if (featuresValue & GF_GERMAN) { - sprintf(buffer + strlen(buffer), " German"); + + // load all tables for now + if (!prefetchId(-1)) { + error("couldn't load all needed resources from 'KYRA.DAT'"); + } + return true; +} + +void StaticResource::deinit() { + unloadId(-1); +} + +const char **StaticResource::loadStrings(int id, int &strings) { + const char **temp = (const char**)getData(id, kStringList, strings); + if (temp) + return temp; + return (const char**)getData(id, kLanguageList, strings); +} + +const uint8 *StaticResource::loadRawData(int id, int &size) { + return (const uint8*)getData(id, kRawData, size); +} + +const Shape *StaticResource::loadShapeTable(int id, int &entries) { + return (const Shape*)getData(id, kShapeList, entries); +} + +const Room *StaticResource::loadRoomTable(int id, int &entries) { + return (const Room*)getData(id, StaticResource::kRoomList, entries); +} + +const uint8 **StaticResource::loadPaletteTable(int id, int &entries) { + return (const uint8**)getData(id, kPaletteTable, entries); +} + +bool StaticResource::prefetchId(int id) { + if (id == -1) { + for (int i = 0; _filenameTable[i].filename; ++i) { + prefetchId(_filenameTable[i].id); } - if (featuresValue & GF_SPANISH) { - sprintf(buffer + strlen(buffer), " Spanish"); + return true; + } + const void *ptr = 0; + int type = -1, size = -1; + + if (checkResList(id, type, ptr, size)) { + return true; + } + + if (checkForBuiltin(id, type, size)) { + return true; + } + + const FilenameTable *filename = searchFile(id); + if (!filename) + return false; + const FileType *filetype = getFiletype(filename->type); + if (!filetype) + return false; + + ResData data; + data.id = id; + data.type = filetype->type; + if (!(this->*(filetype->load))(filename->filename, data.data, data.size)) { + return false; + } + _resList.push_back(data); + + return true; +} + +void StaticResource::unloadId(int id) { + Common::List<ResData>::iterator pos = _resList.begin(); + for (; pos != _resList.end(); ++pos) { + if (pos->id == id || id == -1) { + const FileType *filetype = getFiletype(pos->type); + (this->*(filetype->free))(pos->data, pos->size); + if (id != -1) + break; } - sprintf(buffer + strlen(buffer), " but not your language ("); - if (_features & GF_ENGLISH) { - sprintf(buffer + strlen(buffer), "English"); - } else if (_features & GF_FRENCH) { - sprintf(buffer + strlen(buffer), "French"); - } else if (_features & GF_GERMAN) { - sprintf(buffer + strlen(buffer), "German"); - } else if (_features & GF_SPANISH) { - sprintf(buffer + strlen(buffer), "Spanish"); - } else { - sprintf(buffer + strlen(buffer), "unknown"); + } +} + +bool StaticResource::checkResList(int id, int &type, const void *&ptr, int &size) { + Common::List<ResData>::iterator pos = _resList.begin(); + for (; pos != _resList.end(); ++pos) { + if (pos->id == id) { + size = pos->size; + type = pos->type; + ptr = pos->data; + return true; } - sprintf(buffer + strlen(buffer), ")"); - warning(buffer); - loadNativeLanguage = false; } - -#define getFileEx(x, y) \ - if (_features & GF_TALKIE) { \ - temp = getFile(x, y ".CD"); \ - } else if (_features & GF_DEMO) { \ - temp = getFile(x, y ".DEM"); \ - } else { \ - temp = getFile(x, y); \ - } -#define loadRawFile(x, y, z) \ - getFileEx(x, y) \ - if (temp) { \ - z = temp; \ - temp = 0; \ - } -#define loadTable(x, y, z, a) \ - getFileEx(x, y) \ - if (temp) { \ - res_loadTable(temp, z, a); \ - delete [] temp; \ - temp = 0; \ - } -#define loadRooms(x, y, z, a) \ - getFileEx(x, y) \ - if (temp) { \ - res_loadRoomTable(temp, z, a); \ - delete [] temp; \ - temp = 0; \ - } -#define loadShapes(x, y, z, a) \ - getFileEx(x, y) \ - if (temp) { \ - res_loadShapeTable(temp, z, a); \ - delete [] temp; \ - temp = 0; \ + return false; +} + +const void *StaticResource::checkForBuiltin(int id, int &type, int &size) { + if (!_builtIn) + return 0; + + for (int i = 0; _builtIn[i].data; ++i) { + if (_builtIn[i].id == id) { + size = _builtIn[i].size; + type = _builtIn[i].type; + return _builtIn[i].data; + } } - - - if ((type & RES_INTRO) || (type & RES_OUTRO) || type == RES_ALL) { - loadRawFile(resFile, "FOREST.SEQ", _seq_Forest); - loadRawFile(resFile, "KALLAK-WRITING.SEQ", _seq_KallakWriting); - loadRawFile(resFile, "KYRANDIA-LOGO.SEQ", _seq_KyrandiaLogo); - loadRawFile(resFile, "KALLAK-MALCOLM.SEQ", _seq_KallakMalcolm); - loadRawFile(resFile, "MALCOLM-TREE.SEQ", _seq_MalcolmTree); - loadRawFile(resFile, "WESTWOOD-LOGO.SEQ", _seq_WestwoodLogo); - loadRawFile(resFile, "DEMO1.SEQ", _seq_Demo1); - loadRawFile(resFile, "DEMO2.SEQ", _seq_Demo2); - loadRawFile(resFile, "DEMO3.SEQ", _seq_Demo3); - loadRawFile(resFile, "DEMO4.SEQ", _seq_Demo4); - - loadTable(resFile, "INTRO-CPS.TXT", (byte***)&_seq_CPSTable, &_seq_CPSTable_Size); - loadTable(resFile, "INTRO-COL.TXT", (byte***)&_seq_COLTable, &_seq_COLTable_Size); - loadTable(resFile, "INTRO-WSA.TXT", (byte***)&_seq_WSATable, &_seq_WSATable_Size); - - res_loadLangTable("INTRO-STRINGS.", &resFile, (byte***)&_seq_textsTable, &_seq_textsTable_Size, loadNativeLanguage); - - loadRawFile(resFile, "REUNION.SEQ", _seq_Reunion); - - res_loadLangTable("HOME.", &resFile, (byte***)&_homeString, &_homeString_Size, loadNativeLanguage); + + return 0; +} + +const StaticResource::FilenameTable *StaticResource::searchFile(int id) { + if (!_filenameTable) + return 0; + + for (int i = 0; _filenameTable[i].filename; ++i) { + if (_filenameTable[i].id == id) + return &_filenameTable[i]; } - - if ((type & RES_INGAME) || type == RES_ALL) { - loadTable(resFile, "ROOM-FILENAMES.TXT", (byte***)&_roomFilenameTable, &_roomFilenameTableSize); - loadRooms(resFile, "ROOM-TABLE.ROOM", &_roomTable, &_roomTableSize); - - loadTable(resFile, "CHAR-IMAGE.TXT", (byte***)&_characterImageTable, &_characterImageTableSize); - - loadShapes(resFile, "SHAPES-DEFAULT.SHP", &_defaultShapeTable, &_defaultShapeTableSize); - - res_loadLangTable("ITEMLIST.", &resFile, (byte***)&_itemList, &_itemList_Size, loadNativeLanguage); - res_loadLangTable("TAKEN.", &resFile, (byte***)&_takenList, &_takenList_Size, loadNativeLanguage); - res_loadLangTable("PLACED.", &resFile, (byte***)&_placedList, &_placedList_Size, loadNativeLanguage); - res_loadLangTable("DROPPED.", &resFile, (byte***)&_droppedList, &_droppedList_Size, loadNativeLanguage); - res_loadLangTable("NODROP.", &resFile, (byte***)&_noDropList, &_noDropList_Size, loadNativeLanguage); - - loadRawFile(resFile, "AMULETEANIM.SEQ", _amuleteAnim); - - for (int i = 1; i <= 33; ++i) { - char buffer[32]; - sprintf(buffer, "PALTABLE%d.PAL", i); - if (_features & GF_TALKIE) { - strcat(buffer, ".CD"); - } else if (_features & GF_DEMO) { - strcat(buffer, ".DEM"); - } - temp = getFile(resFile, buffer); - if (temp) { - _specialPalettes[i-1] = temp; - temp = 0; - } + + return 0; +} + +const StaticResource::FileType *StaticResource::getFiletype(int type) { + if (!_fileLoader) + return 0; + + for (int i = 0; _fileLoader[i].load; ++i) { + if (_fileLoader[i].type == type) { + return &_fileLoader[i]; } - - res_loadLangTable("PUTDOWN.", &resFile, (byte***)&_putDownFirst, &_putDownFirst_Size, loadNativeLanguage); - res_loadLangTable("WAITAMUL.", &resFile, (byte***)&_waitForAmulet, &_waitForAmulet_Size, loadNativeLanguage); - res_loadLangTable("BLACKJEWEL.", &resFile, (byte***)&_blackJewel, &_blackJewel_Size, loadNativeLanguage); - res_loadLangTable("POISONGONE.", &resFile, (byte***)&_poisonGone, &_poisonGone_Size, loadNativeLanguage); - res_loadLangTable("HEALINGTIP.", &resFile, (byte***)&_healingTip, &_healingTip_Size, loadNativeLanguage); - - loadShapes(resFile, "HEALING.SHP", &_healingShapeTable, &_healingShapeTableSize); - loadShapes(resFile, "HEALING2.SHP", &_healingShape2Table, &_healingShape2TableSize); - - res_loadLangTable("THEPOISON.", &resFile, (byte***)&_thePoison, &_thePoison_Size, loadNativeLanguage); - res_loadLangTable("FLUTE.", &resFile, (byte***)&_fluteString, &_fluteString_Size, loadNativeLanguage); - - loadShapes(resFile, "POISONDEATH.SHP", &_posionDeathShapeTable, &_posionDeathShapeTableSize); - loadShapes(resFile, "FLUTE.SHP", &_fluteAnimShapeTable, &_fluteAnimShapeTableSize); - - loadShapes(resFile, "WINTER1.SHP", &_winterScrollTable, &_winterScrollTableSize); - loadShapes(resFile, "WINTER2.SHP", &_winterScroll1Table, &_winterScroll1TableSize); - loadShapes(resFile, "WINTER3.SHP", &_winterScroll2Table, &_winterScroll2TableSize); - loadShapes(resFile, "DRINK.SHP", &_drinkAnimationTable, &_drinkAnimationTableSize); - loadShapes(resFile, "WISP.SHP", &_brandonToWispTable, &_brandonToWispTableSize); - loadShapes(resFile, "MAGICANIM.SHP", &_magicAnimationTable, &_magicAnimationTableSize); - loadShapes(resFile, "BRANSTONE.SHP", &_brandonStoneTable, &_brandonStoneTableSize); - - res_loadLangTable("WISPJEWEL.", &resFile, (byte***)&_wispJewelStrings, &_wispJewelStrings_Size, loadNativeLanguage); - res_loadLangTable("MAGICJEWEL.", &resFile, (byte***)&_magicJewelString, &_magicJewelString_Size, loadNativeLanguage); - - res_loadLangTable("FLASKFULL.", &resFile, (byte***)&_flaskFull, &_fullFlask_Size, loadNativeLanguage); - res_loadLangTable("FULLFLASK.", &resFile, (byte***)&_fullFlask, &_fullFlask_Size, loadNativeLanguage); - - res_loadLangTable("VERYCLEVER.", &resFile, (byte***)&_veryClever, &_veryClever_Size, loadNativeLanguage); } -#undef loadRooms -#undef loadTable -#undef loadRawFile -#undef getFileEx + return 0; } -void KyraEngine::res_unloadResources(int type) { - debugC(9, kDebugLevelMain, "KyraEngine::res_unloadResources(%d)", type); - if ((type & RES_INTRO) || (type & RES_OUTRO) || type & RES_ALL) { - res_freeLangTable(&_seq_WSATable, &_seq_WSATable_Size); - res_freeLangTable(&_seq_CPSTable, &_seq_CPSTable_Size); - res_freeLangTable(&_seq_COLTable, &_seq_COLTable_Size); - res_freeLangTable(&_seq_textsTable, &_seq_textsTable_Size); - - delete [] _seq_Forest; _seq_Forest = 0; - delete [] _seq_KallakWriting; _seq_KallakWriting = 0; - delete [] _seq_KyrandiaLogo; _seq_KyrandiaLogo = 0; - delete [] _seq_KallakMalcolm; _seq_KallakMalcolm = 0; - delete [] _seq_MalcolmTree; _seq_MalcolmTree = 0; - delete [] _seq_WestwoodLogo; _seq_WestwoodLogo = 0; - delete [] _seq_Demo1; _seq_Demo1 = 0; - delete [] _seq_Demo2; _seq_Demo2 = 0; - delete [] _seq_Demo3; _seq_Demo3 = 0; - delete [] _seq_Demo4; _seq_Demo4 = 0; - - delete [] _seq_Reunion; _seq_Reunion = 0; - res_freeLangTable(&_homeString, &_homeString_Size); +const void *StaticResource::getData(int id, int requesttype, int &size) { + const void *ptr = 0; + int type = -1; + + if (checkResList(id, type, ptr, size)) { + if (type == requesttype) + return ptr; + return 0; } - - if ((type & RES_INGAME) || type & RES_ALL) { - res_freeLangTable(&_roomFilenameTable, &_roomFilenameTableSize); - - delete [] _roomTable; _roomTable = 0; - _roomTableSize = 0; - - res_freeLangTable(&_characterImageTable, &_characterImageTableSize); - - delete [] _defaultShapeTable; - _defaultShapeTable = 0; - _defaultShapeTableSize = 0; - - res_freeLangTable(&_itemList, &_itemList_Size); - res_freeLangTable(&_takenList, &_takenList_Size); - res_freeLangTable(&_placedList, &_placedList_Size); - res_freeLangTable(&_droppedList, &_droppedList_Size); - res_freeLangTable(&_noDropList, &_noDropList_Size); - - delete [] _amuleteAnim; - _amuleteAnim = 0; - - for (int i = 0; i < 33; ++i) { - delete [] _specialPalettes[i]; - _specialPalettes[i] = 0; - } - - res_freeLangTable(&_putDownFirst, &_putDownFirst_Size); - res_freeLangTable(&_waitForAmulet, &_waitForAmulet_Size); - res_freeLangTable(&_blackJewel, &_blackJewel_Size); - res_freeLangTable(&_poisonGone, &_poisonGone_Size); - res_freeLangTable(&_healingTip, &_healingTip_Size); - - delete [] _healingShapeTable; - _healingShapeTable = 0; - _healingShapeTableSize = 0; - - delete [] _healingShape2Table; - _healingShape2Table = 0; - _healingShape2TableSize = 0; - - res_freeLangTable(&_thePoison, &_thePoison_Size); - res_freeLangTable(&_fluteString, &_fluteString_Size); - - delete [] _posionDeathShapeTable; - _posionDeathShapeTable = 0; - _posionDeathShapeTableSize = 0; - - delete [] _fluteAnimShapeTable; - _fluteAnimShapeTable = 0; - _fluteAnimShapeTableSize = 0; - - delete [] _winterScrollTable; - _winterScrollTable = 0; - _winterScrollTableSize = 0; - - delete [] _winterScroll1Table; - _winterScroll1Table = 0; - _winterScroll1TableSize = 0; - - delete [] _winterScroll2Table; - _winterScroll2Table = 0; - _winterScroll2TableSize = 0; - - delete [] _drinkAnimationTable; - _drinkAnimationTable = 0; - _drinkAnimationTableSize = 0; - - delete [] _brandonToWispTable; - _brandonToWispTable = 0; - _brandonToWispTableSize = 0; - - delete [] _magicAnimationTable; - _magicAnimationTable = 0; - _magicAnimationTableSize = 0; - - delete [] _brandonStoneTable; - _brandonStoneTable = 0; - _brandonStoneTableSize = 0; - - res_freeLangTable(&_flaskFull, &_flaskFull_Size); - res_freeLangTable(&_fullFlask, &_fullFlask_Size); - - res_freeLangTable(&_veryClever, &_veryClever_Size); + + ptr = checkForBuiltin(id, type, size); + if (ptr) { + if (type == requesttype) + return ptr; + return 0; + } + + if (!prefetchId(id)) + return 0; + + if (checkResList(id, type, ptr, size)) { + if (type == requesttype) + return ptr; } + + return 0; } -void KyraEngine::res_loadLangTable(const char *filename, PAKFile *res, byte ***loadTo, int *size, bool nativ) { - char file[36]; +bool StaticResource::loadLanguageTable(const char *filename, void *&ptr, int &size) { + char file[64]; for (int i = 0; languages[i].ext; ++i) { - if (languages[i].flags != (_features & LANGUAGE_FLAGS) && nativ) { - continue; + if (languages[i].flags != (_engine->features() & LANGUAGE_FLAGS)) { + continue; } strcpy(file, filename); strcat(file, languages[i].ext); - if (_features & GF_TALKIE) { - strcat(file, ".CD"); - } else if (_features & GF_DEMO) { - strcat(file, ".DEM"); - } - byte *temp = getFile(*res, file); - if (temp) { - res_loadTable(temp, loadTo, size); - delete [] temp; - temp = 0; - } else { - if (!nativ) - continue; - } - break; + if (loadStringTable(file, ptr, size)) + return true; + } + + strcpy(file, filename); + strcat(file, languages[0].ext); + if (loadStringTable(file, ptr, size)) { + warning("coudln't find specific language table for your version, using English now"); + return true; } + + return false; } -void KyraEngine::res_loadTable(const byte *src, byte ***loadTo, int *size) { +bool StaticResource::loadStringTable(const char *filename, void *&ptr, int &size) { + uint8 *filePtr = getFile(filename, size); + if (!filePtr) + return false; + uint8 *src = filePtr; + uint32 count = READ_BE_UINT32(src); src += 4; - *size = count; - *loadTo = new byte*[count]; + size = count; + char **output = new char*[count]; + assert(output); const char *curPos = (const char*)src; for (uint32 i = 0; i < count; ++i) { int strLen = strlen(curPos); - (*loadTo)[i] = new byte[strLen+1]; - memcpy((*loadTo)[i], curPos, strLen+1); + output[i] = new char[strLen+1]; + assert(output[i]); + memcpy(output[i], curPos, strLen+1); curPos += strLen+1; } + + delete [] filePtr; + ptr = output; + + return true; } -void KyraEngine::res_loadRoomTable(const byte *src, Room **loadTo, int *size) { +bool StaticResource::loadRawData(const char *filename, void *&ptr, int &size) { + ptr = getFile(filename, size); + if (!ptr) + return false; + return true; +} + +bool StaticResource::loadShapeTable(const char *filename, void *&ptr, int &size) { + uint8 *filePtr = getFile(filename, size); + if (!filePtr) + return false; + uint8 *src = filePtr; + uint32 count = READ_BE_UINT32(src); src += 4; - *size = count; - *loadTo = new Room[count]; + size = count; + Shape *loadTo = new Shape[count]; + assert(loadTo); for (uint32 i = 0; i < count; ++i) { - (*loadTo)[i].nameIndex = *src++; - (*loadTo)[i].northExit = READ_BE_UINT16(src); src += 2; - (*loadTo)[i].eastExit = READ_BE_UINT16(src); src += 2; - (*loadTo)[i].southExit = READ_BE_UINT16(src); src += 2; - (*loadTo)[i].westExit = READ_BE_UINT16(src); src += 2; - memset(&(*loadTo)[i].itemsTable[0], 0xFF, sizeof(byte)*6); - memset(&(*loadTo)[i].itemsTable[6], 0, sizeof(byte)*6); - memset((*loadTo)[i].itemsXPos, 0, sizeof(uint16)*12); - memset((*loadTo)[i].itemsYPos, 0, sizeof(uint8)*12); - memset((*loadTo)[i].needInit, 0, sizeof((*loadTo)[i].needInit)); + loadTo[i].imageIndex = *src++; + loadTo[i].x = *src++; + loadTo[i].y = *src++; + loadTo[i].w = *src++; + loadTo[i].h = *src++; + loadTo[i].xOffset = *src++; + loadTo[i].yOffset = *src++; } + + delete [] filePtr; + ptr = loadTo; + + return true; } -void KyraEngine::res_loadShapeTable(const byte *src, Shape **loadTo, int *size) { +bool StaticResource::loadRoomTable(const char *filename, void *&ptr, int &size) { + uint8 *filePtr = getFile(filename, size); + if (!filePtr) + return false; + uint8 *src = filePtr; + uint32 count = READ_BE_UINT32(src); src += 4; - *size = count; - *loadTo = new Shape[count]; + size = count; + Room *loadTo = new Room[count]; + assert(loadTo); for (uint32 i = 0; i < count; ++i) { - (*loadTo)[i].imageIndex = *src++; - (*loadTo)[i].x = *src++; - (*loadTo)[i].y = *src++; - (*loadTo)[i].w = *src++; - (*loadTo)[i].h = *src++; - (*loadTo)[i].xOffset = *src++; - (*loadTo)[i].yOffset = *src++; + loadTo[i].nameIndex = *src++; + loadTo[i].northExit = READ_BE_UINT16(src); src += 2; + loadTo[i].eastExit = READ_BE_UINT16(src); src += 2; + loadTo[i].southExit = READ_BE_UINT16(src); src += 2; + loadTo[i].westExit = READ_BE_UINT16(src); src += 2; + memset(&loadTo[i].itemsTable[0], 0xFF, sizeof(byte)*6); + memset(&loadTo[i].itemsTable[6], 0, sizeof(byte)*6); + memset(loadTo[i].itemsXPos, 0, sizeof(uint16)*12); + memset(loadTo[i].itemsYPos, 0, sizeof(uint8)*12); + memset(loadTo[i].needInit, 0, sizeof(loadTo[i].needInit)); + } + + delete [] filePtr; + ptr = loadTo; + + return true; +} + +bool StaticResource::loadPaletteTable(const char *filename, void *&ptr, int &size) { + const char *temp = filename; + int start = atoi(temp); + temp = strstr(temp, " "); + if (temp == NULL) + return false; + ++temp; + int end = atoi(temp); + + char **table = new char*[end-start+1]; + assert(table); + + char file[64]; + temp = filename; + temp = strstr(temp, " "); + ++temp; + temp = strstr(temp, " "); + if (temp == NULL) + return false; + ++temp; + strncpy(file, temp, 64); + + char name[64]; + for (int i = start; i <= end; ++i) { + snprintf(name, 64, "%s%d.PAL", file, i); + table[(start != 0) ? (i-start) : i] = (char*)getFile(name, size); + if (!table[(start != 0) ? (i-start) : i]) { + delete [] table; + return false; + } } + + ptr = table; + size = end - start + 1; + return true; +} + +void StaticResource::freeRawData(void *&ptr, int &size) { + uint8 *data = (uint8*)ptr; + delete [] data; + ptr = 0; + size = 0; } -void KyraEngine::res_freeLangTable(char ***string, int *size) { - if (!string || !size) - return; - if (!*size || !*string) - return; - for (int i = 0; i < *size; ++i) { - delete [] (*string)[i]; +void StaticResource::freeStringTable(void *&ptr, int &size) { + char **data = (char**)ptr; + while (size--) { + delete [] data[size]; } - delete [] *string; + ptr = 0; + size = 0; +} + +void StaticResource::freeShapeTable(void *&ptr, int &size) { + Shape *data = (Shape*)ptr; + delete [] data; + ptr = 0; + size = 0; +} + +void StaticResource::freeRoomTable(void *&ptr, int &size) { + Room *data = (Room*)ptr; + delete [] data; + ptr = 0; size = 0; - *string = 0; +} + +void StaticResource::freePaletteTable(void *&ptr, int &size) { + uint8 **data = (uint8**)ptr; + while (size--) { + delete [] data[size]; + } + ptr = 0; + size = 0; +} + +uint8 *StaticResource::getFile(const char *name, int &size) { + char buffer[64]; + const char *ext = ""; + if (_engine->features() & GF_TALKIE) { + ext = ".CD"; + } else if (_engine->features() & GF_DEMO) { + ext = ".DEM"; + } + snprintf(buffer, 64, "%s%s", name, ext); + uint32 tempSize = 0; + uint8 *data = _engine->resource()->fileData(buffer, &tempSize); + size = tempSize; + return data; +} + +#pragma mark - + +void KyraEngine::initStaticResource() { + int temp = 0; + _seq_Forest = _staticres->loadRawData(kForestSeq, temp); + _seq_KallakWriting = _staticres->loadRawData(kKallakWritingSeq, temp); + _seq_KyrandiaLogo = _staticres->loadRawData(kKyrandiaLogoSeq, temp); + _seq_KallakMalcolm = _staticres->loadRawData(kKallakMalcolmSeq, temp); + _seq_MalcolmTree = _staticres->loadRawData(kMalcolmTreeSeq, temp); + _seq_WestwoodLogo = _staticres->loadRawData(kWestwoodLogoSeq, temp); + _seq_Demo1 = _staticres->loadRawData(kDemo1Seq, temp); + _seq_Demo2 = _staticres->loadRawData(kDemo2Seq, temp); + _seq_Demo3 = _staticres->loadRawData(kDemo3Seq, temp); + _seq_Demo4 = _staticres->loadRawData(kDemo4Seq, temp); + _seq_Reunion = _staticres->loadRawData(kOutroReunionSeq, temp); + + _seq_WSATable = _staticres->loadStrings(kIntroWSAStrings, _seq_WSATable_Size); + _seq_CPSTable = _staticres->loadStrings(kIntroCPSStrings, _seq_CPSTable_Size); + _seq_COLTable = _staticres->loadStrings(kIntroCOLStrings, _seq_COLTable_Size); + _seq_textsTable = _staticres->loadStrings(kIntroStrings, _seq_textsTable_Size); + + _itemList = _staticres->loadStrings(kItemNames, _itemList_Size); + _takenList = _staticres->loadStrings(kTakenStrings, _takenList_Size); + _placedList = _staticres->loadStrings(kPlacedStrings, _placedList_Size); + _droppedList = _staticres->loadStrings(kDroppedStrings, _droppedList_Size); + _noDropList = _staticres->loadStrings(kNoDropStrings, _noDropList_Size); + _putDownFirst = _staticres->loadStrings(kPutDownString, _putDownFirst_Size); + _waitForAmulet = _staticres->loadStrings(kWaitAmuletString, _waitForAmulet_Size); + _blackJewel = _staticres->loadStrings(kBlackJewelString, _blackJewel_Size); + _poisonGone = _staticres->loadStrings(kPoisonGoneString, _poisonGone_Size); + _healingTip = _staticres->loadStrings(kHealingTipString, _healingTip_Size); + _thePoison = _staticres->loadStrings(kThePoisonStrings, _thePoison_Size); + _fluteString = _staticres->loadStrings(kFluteStrings, _fluteString_Size); + _wispJewelStrings = _staticres->loadStrings(kWispJewelStrings, _wispJewelStrings_Size); + _magicJewelString = _staticres->loadStrings(kMagicJewelStrings, _magicJewelString_Size); + _flaskFull = _staticres->loadStrings(kFlaskFullString, _flaskFull_Size); + _fullFlask = _staticres->loadStrings(kFullFlaskString, _fullFlask_Size); + _veryClever = _staticres->loadStrings(kVeryCleverString, _veryClever_Size); + _homeString = _staticres->loadStrings(kOutroHomeString, _homeString_Size); + + _healingShapeTable = _staticres->loadShapeTable(kHealing1Shapes, _healingShapeTableSize); + _healingShape2Table = _staticres->loadShapeTable(kHealing2Shapes, _healingShape2TableSize); + _posionDeathShapeTable = _staticres->loadShapeTable(kPoisonDeathShapes, _posionDeathShapeTableSize); + _fluteAnimShapeTable = _staticres->loadShapeTable(kFluteShapes, _fluteAnimShapeTableSize); + _winterScrollTable = _staticres->loadShapeTable(kWinter1Shapes, _winterScrollTableSize); + _winterScroll1Table = _staticres->loadShapeTable(kWinter2Shapes, _winterScroll1TableSize); + _winterScroll2Table = _staticres->loadShapeTable(kWinter3Shapes, _winterScroll2TableSize); + _drinkAnimationTable = _staticres->loadShapeTable(kDrinkShapes, _drinkAnimationTableSize); + _brandonToWispTable = _staticres->loadShapeTable(kWispShapes, _brandonToWispTableSize); + _magicAnimationTable = _staticres->loadShapeTable(kMagicAnimShapes, _magicAnimationTableSize); + _brandonStoneTable = _staticres->loadShapeTable(kBranStoneShapes, _brandonStoneTableSize); + + _characterImageTable = _staticres->loadStrings(kCharacterImageFilenames, _characterImageTableSize); + + _roomFilenameTable = _staticres->loadStrings(kRoomFilenames, _roomFilenameTableSize); + + _amuleteAnim = _staticres->loadRawData(kAmuleteAnimSeq, temp); + + _specialPalettes = _staticres->loadPaletteTable(kPaletteList, temp); + + // copied static res + + // room list + const Room *tempRoomList = _staticres->loadRoomTable(kRoomList, _roomTableSize); + + if (_roomTableSize > 0) { + _roomTable = new Room[_roomTableSize]; + assert(_roomTable); + + memcpy(_roomTable, tempRoomList, _roomTableSize*sizeof(Room)); + tempRoomList = 0; + + _staticres->unloadId(kRoomList); + } + + // default shape table + const Shape *tempShapeTable = _staticres->loadShapeTable(kDefaultShapes, _defaultShapeTableSize); + + if (_defaultShapeTableSize > 0) { + _defaultShapeTable = new Shape[_defaultShapeTableSize]; + assert(_defaultShapeTable); + + memcpy(_defaultShapeTable, tempShapeTable, _defaultShapeTableSize*sizeof(Shape)); + tempShapeTable = 0; + + _staticres->unloadId(kDefaultShapes); + } } void KyraEngine::loadMouseShapes() { diff --git a/engines/kyra/text.cpp b/engines/kyra/text.cpp index f47136ced4..61073b5cfc 100644 --- a/engines/kyra/text.cpp +++ b/engines/kyra/text.cpp @@ -32,7 +32,7 @@ namespace Kyra { -void KyraEngine::waitForChatToFinish(int16 chatDuration, char *chatStr, uint8 charNum) { +void KyraEngine::waitForChatToFinish(int16 chatDuration, const char *chatStr, uint8 charNum) { debugC(9, kDebugLevelMain, "KyraEngine::waitForChatToFinish(%i, %s, %i)", chatDuration, chatStr, charNum); bool hasUpdatedNPCs = false; bool runLoop = true; @@ -229,7 +229,7 @@ int KyraEngine::initCharacterChat(int8 charNum) { return 1; } -void KyraEngine::characterSays(char *chatStr, int8 charNum, int8 chatDuration) { +void KyraEngine::characterSays(const char *chatStr, int8 charNum, int8 chatDuration) { debugC(9, kDebugLevelMain, "KyraEngine::characterSays('%s', %i, %d)", chatStr, charNum, chatDuration); uint8 startAnimFrames[] = { 0x10, 0x32, 0x56, 0x0, 0x0, 0x0 }; @@ -302,7 +302,7 @@ void KyraEngine::characterSays(char *chatStr, int8 charNum, int8 chatDuration) { endCharacterChat(charNum, convoInitialized); } -void KyraEngine::drawSentenceCommand(char *sentence, int color) { +void KyraEngine::drawSentenceCommand(const char *sentence, int color) { debugC(9, kDebugLevelMain, "KyraEngine::drawSentenceCommand('%s', %i)", sentence, color); _screen->hideMouse(); _screen->fillRect(8, 143, 311, 152, 12); @@ -322,7 +322,7 @@ void KyraEngine::drawSentenceCommand(char *sentence, int color) { _fadeText = false; } -void KyraEngine::updateSentenceCommand(char *str1, char *str2, int color) { +void KyraEngine::updateSentenceCommand(const char *str1, const char *str2, int color) { debugC(9, kDebugLevelMain, "KyraEngine::updateSentenceCommand('%s', '%s', %i)", str1, str2, color); char sentenceCommand[500]; strncpy(sentenceCommand, str1, 500); @@ -551,7 +551,7 @@ void TextDisplayer::printText(const char *str, int x, int y, uint8 c0, uint8 c1, _screen->setFont(curFont); } -void TextDisplayer::printCharacterText(char *text, int8 charNum, int charX) { +void TextDisplayer::printCharacterText(const char *text, int8 charNum, int charX) { debugC(9, kDebugLevelMain, "TextDisplayer::printCharacterText('%s', %d, %d)", text, charNum, charX); uint8 colorTable[] = {0x0F, 0x9, 0x0C9, 0x80, 0x5, 0x81, 0x0E, 0xD8, 0x55, 0x3A, 0x3a}; int top, left, x1, x2, w, x; diff --git a/engines/kyra/text.h b/engines/kyra/text.h index f8f7c975a6..7c5f1846ee 100644 --- a/engines/kyra/text.h +++ b/engines/kyra/text.h @@ -50,7 +50,7 @@ public: void restoreTalkTextMessageBkgd(int srcPage, int dstPage); void printTalkTextMessage(const char *text, int x, int y, uint8 color, int srcPage, int dstPage); void printText(const char *str, int x, int y, uint8 c0, uint8 c1, uint8 c2); - void printCharacterText(char *text, int8 charNum, int charX); + void printCharacterText(const char *text, int8 charNum, int charX); uint16 _talkMessageY; uint16 _talkMessageH; |