diff options
Diffstat (limited to 'engines/gob')
70 files changed, 7196 insertions, 10026 deletions
diff --git a/engines/gob/dataio.cpp b/engines/gob/dataio.cpp index a37586aee6..f59fa80e8d 100644 --- a/engines/gob/dataio.cpp +++ b/engines/gob/dataio.cpp @@ -239,7 +239,7 @@ int16 DataIO::getChunk(const char *chunkName) { } dataDesc = _dataFiles[file]; - for (int16 chunk = 0; chunk < _numDataChunks[file]; chunk++, dataDesc++) { + for (uint16 chunk = 0; chunk < _numDataChunks[file]; chunk++, dataDesc++) { if (scumm_stricmp(chunkName, dataDesc->chunkName) != 0) continue; @@ -334,7 +334,6 @@ uint32 DataIO::getChunkPos(int16 handle) const { int32 DataIO::getChunkSize(const char *chunkName) { int16 file; - int16 chunk; struct ChunkDesc *dataDesc; int16 slot; int32 realSize; @@ -344,7 +343,7 @@ int32 DataIO::getChunkSize(const char *chunkName) { return -1; dataDesc = _dataFiles[file]; - for (chunk = 0; chunk < _numDataChunks[file]; chunk++, dataDesc++) { + for (uint16 chunk = 0; chunk < _numDataChunks[file]; chunk++, dataDesc++) { if (scumm_stricmp(chunkName, dataDesc->chunkName) != 0) continue; @@ -488,6 +487,16 @@ int16 DataIO::openData(const char *path) { return file_open(path); } +bool DataIO::existData(const char *path) { + int16 handle = openData(path); + + if (handle < 0) + return false; + + closeData(handle); + return true; +} + DataStream *DataIO::openAsStream(int16 handle, bool dispose) { uint32 curPos = getPos(handle); seekData(handle, 0, SEEK_END); @@ -575,6 +584,9 @@ byte *DataIO::getData(const char *path) { } DataStream *DataIO::getDataStream(const char *path) { + if (!path || (path[0] == '\0') || !existData(path)) + return 0; + uint32 size = getDataSize(path); byte *data = getData(path); diff --git a/engines/gob/dataio.h b/engines/gob/dataio.h index c67dc89df8..1f55cac90d 100644 --- a/engines/gob/dataio.h +++ b/engines/gob/dataio.h @@ -80,6 +80,7 @@ public: byte *getUnpackedData(const char *name); void closeData(int16 handle); int16 openData(const char *path); + bool existData(const char *path); DataStream *openAsStream(int16 handle, bool dispose = false); int32 getDataSize(const char *name); @@ -92,7 +93,7 @@ public: protected: Common::File _filesHandles[MAX_FILES]; struct ChunkDesc *_dataFiles[MAX_DATA_FILES]; - int16 _numDataChunks[MAX_DATA_FILES]; + uint16 _numDataChunks[MAX_DATA_FILES]; int16 _dataFileHandles[MAX_DATA_FILES]; bool _dataFileItk[MAX_DATA_FILES]; int32 _chunkPos[MAX_SLOT_COUNT * MAX_DATA_FILES]; diff --git a/engines/gob/demos/demoplayer.cpp b/engines/gob/demos/demoplayer.cpp index ede90af333..0229bb7515 100644 --- a/engines/gob/demos/demoplayer.cpp +++ b/engines/gob/demos/demoplayer.cpp @@ -123,7 +123,9 @@ void DemoPlayer::init() { void DemoPlayer::clearScreen() { debugC(1, kDebugDemo, "Clearing the screen"); - _vm->_video->clearScreen(); + _vm->_video->clearSurf(*_vm->_draw->_backSurface); + _vm->_draw->forceBlit(); + _vm->_video->retrace(); } void DemoPlayer::playVideo(const char *fileName) { diff --git a/engines/gob/detection.cpp b/engines/gob/detection.cpp index af64a53b60..9426c01ef2 100644 --- a/engines/gob/detection.cpp +++ b/engines/gob/detection.cpp @@ -61,13 +61,14 @@ static const PlainGameDescriptor gobGames[] = { {"woodruff", "The Bizarre Adventures of Woodruff and the Schnibble"}, {"dynasty", "The Last Dynasty"}, {"urban", "Urban Runner"}, - {"archi", "Playtoon 1 - Uncle Archibald"}, - {"spirou", "Playtoon 2 - The Case of the Counterfeit Collaborator"}, - {"chato", "Playtoon 3 - The Secret of the Castle"}, - {"manda", "Playtoon 4 - The Mandarine Prince"}, - {"wakan", "Playtoon 5 - The Stone of Wakan"}, - {"playtnck2", "Playtoon Construction Kit 2 - Les chevaliers"}, - {"bambou", "Playtoon Limited Edition - Bambou le sauveur de la jungle"}, + {"playtoons1", "Playtoons 1 - Uncle Archibald"}, + {"playtoons2", "Playtoons 2 - The Case of the Counterfeit Collaborator"}, + {"playtoons3", "Playtoons 3 - The Secret of the Castle"}, + {"playtoons4", "Playtoons 4 - The Mandarine Prince"}, + {"playtoons5", "Playtoons 5 - The Stone of Wakan"}, + {"playtnck1", "Playtoons Construction Kit 1 - Monsters"}, + {"playtnck2", "Playtoons Construction Kit 2 - Knights"}, + {"bambou", "Playtoons Limited Edition - Bambou le sauveur de la jungle"}, {"fascination", "Fascination"}, {"geisha", "Geisha"}, {"adibou4", "Adibou v4"}, @@ -84,6 +85,7 @@ static const ADObsoleteGameID obsoleteGameIDsTable[] = { namespace Gob { using Common::GUIO_NOSPEECH; +using Common::GUIO_NOSUBTITLES; using Common::GUIO_NONE; static const GOBGameDescription gameDescriptions[] = { @@ -95,7 +97,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesEGA, @@ -109,7 +111,7 @@ static const GOBGameDescription gameDescriptions[] = { RU_RUS, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesEGA, @@ -123,7 +125,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesNone, @@ -137,7 +139,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesAdlib, @@ -151,7 +153,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -165,7 +167,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -179,7 +181,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -193,7 +195,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -207,7 +209,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -221,7 +223,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -235,7 +237,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -249,7 +251,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -263,7 +265,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -277,7 +279,63 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob1cd", + "v1.02", + AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248), + HU_HUN, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob1cd", + "v1.02", + AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob1cd", + "v1.02", + AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob1cd", + "v1.02", + AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -291,7 +349,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformAmiga, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesNone, @@ -305,7 +363,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesNone, @@ -319,7 +377,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesNone, @@ -333,7 +391,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesNone, @@ -347,7 +405,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_ANY, kPlatformMacintosh, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesNone, @@ -361,7 +419,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_ANY, kPlatformMacintosh, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesAdlib, @@ -375,7 +433,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformMacintosh, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesAdlib, @@ -389,7 +447,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformMacintosh, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesAdlib, @@ -403,7 +461,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformMacintosh, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesAdlib, @@ -417,13 +475,13 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformMacintosh, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesAdlib, 0, 0, 0 }, - { + { // Supplied by Hkz on #scummvm { "gob1", "", @@ -435,7 +493,151 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformWindows, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdlib, + 0, 0, 0 + }, + { // Supplied by Hkz on #scummvm + { + "gob1", + "", + { + {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + IT_ITA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdlib, + 0, 0, 0 + }, + { // Supplied by Hkz on #scummvm + { + "gob1", + "", + { + {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + EN_GRB, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdlib, + 0, 0, 0 + }, + { // Supplied by Hkz on #scummvm + { + "gob1", + "", + { + {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + DE_DEU, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdlib, + 0, 0, 0 + }, + { // Supplied by Hkz on #scummvm + { + "gob1", + "", + { + {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + ES_ESP, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdlib, + 0, 0, 0 + }, + { + { + "gob1", + "", + { + {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + EN_GRB, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdlib, + 0, 0, 0 + }, + { + { + "gob1", + "", + { + {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdlib, + 0, 0, 0 + }, + { + { + "gob1", + "", + { + {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + ES_ESP, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdlib, + 0, 0, 0 + }, + { + { + "gob1", + "", + { + {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + IT_ITA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesAdlib, @@ -453,7 +655,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformWindows, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesAdlib, @@ -467,7 +669,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_ANY, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesNone, @@ -481,7 +683,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesNone, @@ -495,7 +697,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesNone, @@ -509,7 +711,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformAtariST, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesNone, @@ -527,7 +729,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformMacintosh, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -545,7 +747,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformMacintosh, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -559,7 +761,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -573,7 +775,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -587,7 +789,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -601,7 +803,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -615,7 +817,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -629,7 +831,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -643,7 +845,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -657,7 +859,7 @@ static const GOBGameDescription gameDescriptions[] = { RU_RUS, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -671,7 +873,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -685,7 +887,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesCD, @@ -699,7 +901,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_ANY, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesCD, @@ -713,7 +915,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesCD, @@ -727,7 +929,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesCD, @@ -741,7 +943,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesCD, @@ -755,7 +957,77 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob2cd", + "v1.02", + AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236), + HU_HUN, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob2cd", + "v1.02", + AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob2cd", + "v1.02", + AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob2cd", + "v1.02", + AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob2cd", + "v1.02", + AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesCD, @@ -769,7 +1041,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -783,7 +1055,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -797,7 +1069,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformAmiga, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesNone, @@ -811,7 +1083,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformAmiga, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesNone, @@ -829,7 +1101,43 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformWindows, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdlib, + 0, 0, 0 + }, + { + { + "gob2", + "", + { + {"intro.stk", 0, "25a99827cd59751a80bed9620fb677a0", 893302}, + {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, + {0, 0, 0, 0} + }, + EN_USA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdlib, + 0, 0, 0 + }, + { + { + "gob2", + "", + { + {"intro.stk", 0, "25a99827cd59751a80bed9620fb677a0", 893302}, + {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -847,7 +1155,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformWindows, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -865,7 +1173,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesNone, @@ -879,7 +1187,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesNone, @@ -893,7 +1201,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesNone, @@ -907,7 +1215,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesNone, @@ -925,7 +1233,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesNone, @@ -943,7 +1251,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformAtariST, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesNone, @@ -957,7 +1265,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformAtariST, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesNone, @@ -971,7 +1279,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesAdlib, @@ -985,7 +1293,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesAdlib, @@ -999,7 +1307,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesAdlib, @@ -1013,7 +1321,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesAdlib, @@ -1027,7 +1335,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesAdlib, @@ -1041,7 +1349,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesAdlib, @@ -1055,7 +1363,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesAdlib, @@ -1069,7 +1377,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesAdlib, @@ -1083,7 +1391,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeBargon, kFeaturesNone, @@ -1097,7 +1405,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformAtariST, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeBargon, kFeaturesNone, @@ -1111,7 +1419,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeBargon, kFeaturesNone, @@ -1125,7 +1433,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeBargon, kFeaturesNone, @@ -1139,7 +1447,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_ANY, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeBargon, kFeaturesNone, @@ -1153,7 +1461,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeBargon, kFeaturesNone, @@ -1167,7 +1475,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeBargon, kFeaturesNone, @@ -1181,7 +1489,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib | kFeaturesEGA, @@ -1195,7 +1503,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib | kFeaturesEGA, @@ -1209,7 +1517,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib | kFeaturesEGA, @@ -1223,7 +1531,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib | kFeaturesEGA, @@ -1237,7 +1545,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib | kFeaturesEGA, @@ -1255,7 +1563,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesNone, @@ -1269,7 +1577,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_ANY, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -1283,7 +1591,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -1297,7 +1605,7 @@ static const GOBGameDescription gameDescriptions[] = { HB_ISR, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -1311,7 +1619,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -1325,7 +1633,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -1339,7 +1647,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -1357,7 +1665,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformMacintosh, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -1371,7 +1679,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1385,7 +1693,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1399,7 +1707,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1413,7 +1721,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1427,7 +1735,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1441,7 +1749,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1455,7 +1763,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1469,7 +1777,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1483,7 +1791,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1497,7 +1805,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1511,7 +1819,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1525,7 +1833,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1536,10 +1844,38 @@ static const GOBGameDescription gameDescriptions[] = { "lostintime", "", AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330), - UNK_LANG, + EN_GRB, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdlib, + 0, 0, 0 + }, + { + { + "lostintime", + "", + AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330), + FR_FRA, kPlatformWindows, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdlib, + 0, 0, 0 + }, + { + { + "lostintime", + "", + AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330), + ES_ESP, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -1553,7 +1889,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_ANY, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES }, kGameTypeFascination, kFeaturesCD, @@ -1567,7 +1903,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeFascination, kFeaturesAdlib, @@ -1581,14 +1917,13 @@ static const GOBGameDescription gameDescriptions[] = { HB_ISR, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeFascination, kFeaturesAdlib, "intro.stk", 0, 0 }, - //Provided by Sanguine - { + { // Supplied by sanguine { "fascination", "VGA 3 disks edition", @@ -1596,7 +1931,21 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeFascination, + kFeaturesAdlib, + "disk0.stk", 0, 0 + }, + { // Supplied by windlepoons in bug report #2809247 + { + "fascination", + "VGA 3 disks edition", + AD_ENTRY1s("disk0.stk", "3a24e60a035250189643c86a9ceafb97", 1062480), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeFascination, kFeaturesAdlib, @@ -1610,7 +1959,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeFascination, kFeaturesAdlib, @@ -1624,7 +1973,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeFascination, kFeaturesNone, @@ -1638,7 +1987,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_ANY, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeFascination, kFeaturesNone, @@ -1652,7 +2001,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeFascination, kFeaturesNone, @@ -1666,7 +2015,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeFascination, kFeaturesNone, @@ -1680,7 +2029,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGeisha, kFeaturesNone, @@ -1694,7 +2043,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGeisha, kFeaturesNone, @@ -1708,7 +2057,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -1722,7 +2071,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -1736,7 +2085,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1750,7 +2099,7 @@ static const GOBGameDescription gameDescriptions[] = { HB_ISR, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1764,7 +2113,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1782,7 +2131,43 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformWindows, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdlib, + 0, 0, 0 + }, + { + { + "gob3", + "", + { + {"intro.stk", 0, "16b014bf32dbd6ab4c5163c44f56fed1", 445104}, + {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdlib, + 0, 0, 0 + }, + { + { + "gob3", + "", + { + {"intro.stk", 0, "16b014bf32dbd6ab4c5163c44f56fed1", 445104}, + {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404}, + {0, 0, 0, 0} + }, + EN_GRB, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1800,7 +2185,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformMacintosh, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1814,7 +2199,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1828,7 +2213,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1842,7 +2227,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1856,7 +2241,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1870,7 +2255,7 @@ static const GOBGameDescription gameDescriptions[] = { RU_RUS, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1884,7 +2269,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1898,7 +2283,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1912,7 +2297,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesNone, @@ -1926,7 +2311,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesNone, @@ -1940,7 +2325,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesCD, @@ -1954,7 +2339,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_ANY, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesCD, @@ -1968,7 +2353,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesCD, @@ -1982,7 +2367,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesCD, @@ -1996,7 +2381,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesCD, @@ -2010,7 +2395,63 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob3cd", + "v1.02", + AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220), + HU_HUN, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob3cd", + "v1.02", + AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob3cd", + "v1.02", + AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob3cd", + "v1.02", + AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesCD, @@ -2024,7 +2465,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -2038,7 +2479,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -2052,7 +2493,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -2066,7 +2507,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_ANY, kPlatformPC, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -2084,7 +2525,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformWindows, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -2098,7 +2539,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeInca2, kFeaturesCD, @@ -2112,7 +2553,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeInca2, kFeaturesCD, @@ -2126,7 +2567,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeInca2, kFeaturesCD, @@ -2140,7 +2581,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeInca2, kFeaturesCD, @@ -2154,7 +2595,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeInca2, kFeaturesCD, @@ -2168,7 +2609,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeInca2, kFeaturesAdlib, @@ -2182,7 +2623,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeInca2, kFeaturesAdlib, @@ -2196,7 +2637,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeInca2, kFeaturesAdlib, @@ -2210,7 +2651,63 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformWindows, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesAdlib, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612), + DE_DEU, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesAdlib, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612), + IT_ITA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesAdlib, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612), + ES_ESP, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesAdlib, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612), + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeInca2, kFeaturesAdlib, @@ -2237,7 +2734,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_ANY, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeInca2, kFeaturesAdlib | kFeaturesBATDemo, @@ -2251,7 +2748,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2265,7 +2762,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2279,7 +2776,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2293,7 +2790,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2307,7 +2804,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2321,7 +2818,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2335,7 +2832,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2349,7 +2846,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2363,7 +2860,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2377,7 +2874,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2391,7 +2888,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2405,7 +2902,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2419,7 +2916,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2433,7 +2930,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2447,7 +2944,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2461,7 +2958,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2475,7 +2972,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2489,7 +2986,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2503,7 +3000,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2517,7 +3014,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2531,7 +3028,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2545,7 +3042,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2559,7 +3056,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2573,7 +3070,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2587,7 +3084,7 @@ static const GOBGameDescription gameDescriptions[] = { PL_POL, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2605,7 +3102,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_ANY, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640 | kFeaturesSCNDemo, @@ -2619,7 +3116,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeDynasty, kFeatures640, @@ -2633,7 +3130,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeDynasty, kFeatures640, @@ -2647,7 +3144,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeDynasty, kFeatures640, @@ -2661,7 +3158,21 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeDynasty, + kFeatures640, + 0, 0, 0 + }, + { + { + "dynasty", + "", + AD_ENTRY1s("intro.stk", "bdbdac8919200a5e71ffb9fb0709f704", 2446652), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeDynasty, kFeatures640, @@ -2717,7 +3228,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeUrban, kFeatures640, @@ -2731,7 +3242,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeUrban, kFeatures640, @@ -2745,7 +3256,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeUrban, kFeatures640, @@ -2759,7 +3270,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeUrban, kFeatures640, @@ -2786,7 +3297,7 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "archi", + "playtoons1", "", { {"playtoon.stk", 0, "8c98e9a11be9bb203a55e8c6e68e519b", 25574338}, @@ -2796,7 +3307,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -2804,8 +3315,8 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "archi", - "Pack mes histoires animées", + "playtoons1", + "Pack mes histoires anim\xE9""es", { {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474}, {"archi.stk", 0, "8d44b2a0d4e3139471213f9f0ed21e81", 5524674}, @@ -2814,7 +3325,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -2822,7 +3333,7 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "archi", + "playtoons1", "", { {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926}, @@ -2832,7 +3343,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -2840,7 +3351,7 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "archi", + "playtoons1", "Non-Interactive Demo", { {"play123.scn", 0, "4689a31f543915e488c3bc46ea358add", 258}, @@ -2855,7 +3366,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_ANY, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640 | kFeaturesSCNDemo, @@ -2863,7 +3374,7 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "archi", + "playtoons1", "Non-Interactive Demo", { {"e.scn", 0, "8a0db733c3f77be86e74e8242e5caa61", 124}, @@ -2873,7 +3384,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_ANY, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640 | kFeaturesSCNDemo, @@ -2881,7 +3392,7 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "archi", + "playtoons1", "Non-Interactive Demo", { {"i.scn", 0, "8b3294474d39970463663edd22341730", 285}, @@ -2895,7 +3406,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640 | kFeaturesSCNDemo, @@ -2903,7 +3414,7 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "archi", + "playtoons1", "Non-Interactive Demo", { {"s.scn", 0, "1f527010626b5490761f16ba7a6f639a", 251}, @@ -2916,7 +3427,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640 | kFeaturesSCNDemo, @@ -2924,7 +3435,7 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "spirou", + "playtoons2", "", { {"playtoon.stk", 0, "55a85036dd93cce93532d8f743d90074", 17467154}, @@ -2934,7 +3445,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -2942,7 +3453,7 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "spirou", + "playtoons2", "", { {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926}, @@ -2952,7 +3463,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -2960,7 +3471,7 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "chato", + "playtoons3", "", { {"playtoon.stk", 0, "8c98e9a11be9bb203a55e8c6e68e519b", 25574338}, @@ -2970,7 +3481,25 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoon, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "playtoons3", + "", + { + {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506}, + {"chato.stk", 0, "8fc8d0da5b3e758908d1d7298d497d0b", 6041026}, + {0, 0, 0, 0} + }, + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -2978,8 +3507,8 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "chato", - "Pack mes histoires animées", + "playtoons3", + "Pack mes histoires anim\xE9""es", { {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474}, {"chato.stk", 0, "4fa4ed96a427c344e9f916f9f236598d", 6033793}, @@ -2988,7 +3517,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -2996,7 +3525,7 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "chato", + "playtoons3", "", { {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926}, @@ -3006,7 +3535,26 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoon, + kFeatures640, + "intro2.stk", 0, 0 + }, + + { + { + "playtoons4", + "", + { + {"playtoon.stk", 0, "b7f5afa2dc1b0f75970b7c07d175db1b", 24340406}, + {"manda.stk", 0, "92529e0b927191d9898a34c2892e9a3a", 6485072}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -3014,7 +3562,7 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "wakan", + "playtoons5", "", { {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474}, @@ -3024,7 +3572,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -3042,11 +3590,29 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeBambou, kFeatures640, - 0, 0, 0 + "intro.stk", "intro.tot", 0 + }, + { + { + "playtnck1", + "", + { + {"playtoon.stk", 0, "5f9aae29265f1f105ad8ec195dff81de", 68382024}, + {"dan.itk", 0, "906d67b3e438d5e95ec7ea9e781a94f3", 3000320}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytnCk, + kFeatures640, + "intro2.stk", 0, 0 }, { { @@ -3054,12 +3620,13 @@ static const GOBGameDescription gameDescriptions[] = { "", { {"playtoon.stk", 0, "5f9aae29265f1f105ad8ec195dff81de", 68382024}, + {"dan.itk", 0, "74eeb075bd2cb47b243349730264af01", 3213312}, {0, 0, 0, 0} }, FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytnCk, kFeatures640, @@ -3073,7 +3640,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NONE }, kGameTypeAdibou4, kFeatures640, @@ -3207,7 +3774,7 @@ static const GOBGameDescription gameDescriptions[] = { { { "adibouunknown", - "ADIBÙ 2 Ambiente", + "ADIB\xD9 2 Ambiente", AD_ENTRY1s("intro.stk", "092707829555f27706920e4cacf1fada", 8737958), IT_ITA, kPlatformPC, @@ -3221,7 +3788,7 @@ static const GOBGameDescription gameDescriptions[] = { { { "adibouunknown", - "ADIBÙ prima elementare : Imparo a leggere e a contare", + "ADIB\xD9 prima elementare : Imparo a leggere e a contare", { {"intro.stk", 0, "092707829555f27706920e4cacf1fada", 8737958}, {"appbou2.itk", 0, "f7bf045f6bdce5a7607c720e36704f33", 200005632}, @@ -3239,7 +3806,7 @@ static const GOBGameDescription gameDescriptions[] = { { { "adibouunknown", - "ADIBOU présente La Magie (STK2.1/OBC)", + "ADIBOU pr\xE9sente La Magie (STK2.1/OBC)", { {"adibou.stk", 0, "977d2449d398f3df23238d718fca35b5", 61097}, {"magic.stk", 0, "9776765dead3e338a32c43bf344b5819", 302664}, @@ -3320,7 +3887,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesNone, @@ -3334,7 +3901,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -3348,7 +3915,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -3362,7 +3929,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformMacintosh, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -3376,7 +3943,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesCD, @@ -3390,7 +3957,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeBargon, kFeaturesNone, @@ -3404,7 +3971,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -3418,7 +3985,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesCD, @@ -3432,7 +3999,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -3446,7 +4013,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -3460,7 +4027,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformMacintosh, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -3474,7 +4041,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -3488,7 +4055,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeUrban, kFeaturesCD, @@ -3496,13 +4063,13 @@ static const GOBGameDescription fallbackDescs[] = { }, { { - "archi", + "playtoons1", "unknown", AD_ENTRY1(0, 0), UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -3510,13 +4077,13 @@ static const GOBGameDescription fallbackDescs[] = { }, { { - "spirou", + "playtoons2", "unknown", AD_ENTRY1(0, 0), UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -3524,13 +4091,13 @@ static const GOBGameDescription fallbackDescs[] = { }, { { - "chato", + "playtoons3", "unknown", AD_ENTRY1(0, 0), UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -3538,13 +4105,13 @@ static const GOBGameDescription fallbackDescs[] = { }, { { - "manda", + "playtoons4", "unknown", AD_ENTRY1(0, 0), UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -3552,13 +4119,13 @@ static const GOBGameDescription fallbackDescs[] = { }, { { - "wakan", + "playtoons5", "unknown", AD_ENTRY1(0, 0), UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -3572,7 +4139,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytnCk, kFeatures640, @@ -3586,7 +4153,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeBambou, kFeatures640, @@ -3600,7 +4167,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeFascination, kFeaturesNone, @@ -3614,7 +4181,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGeisha, kFeaturesNone, @@ -3628,7 +4195,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeAdibou4, kFeatures640, diff --git a/engines/gob/draw.cpp b/engines/gob/draw.cpp index 8619e08e8b..b3e5e7418c 100644 --- a/engines/gob/draw.cpp +++ b/engines/gob/draw.cpp @@ -30,6 +30,7 @@ #include "gob/global.h" #include "gob/util.h" #include "gob/game.h" +#include "gob/script.h" #include "gob/inter.h" #include "gob/video.h" #include "gob/palanim.h" @@ -389,11 +390,10 @@ void Draw::printTextCentered(int16 id, int16 left, int16 top, int16 right, adjustCoords(1, &left, &top); adjustCoords(1, &right, &bottom); - if (READ_LE_UINT16(_vm->_game->_totFileData + 0x7E) != 0) { - byte *storedIP = _vm->_global->_inter_execPtr; + uint16 centerOffset = _vm->_game->_script->getFunctionOffset(TOTFile::kFunctionCenter); + if (centerOffset != 0) { + _vm->_game->_script->call(centerOffset); - _vm->_global->_inter_execPtr = _vm->_game->_totFileData + - READ_LE_UINT16(_vm->_game->_totFileData + 0x7E); WRITE_VAR(17, (uint32) id); WRITE_VAR(18, (uint32) left); WRITE_VAR(19, (uint32) top); @@ -401,7 +401,7 @@ void Draw::printTextCentered(int16 id, int16 left, int16 top, int16 right, WRITE_VAR(21, (uint32) (bottom - top + 1)); _vm->_inter->funcBlock(0); - _vm->_global->_inter_execPtr = storedIP; + _vm->_game->_script->pop(); } if (str[0] == '\0') diff --git a/engines/gob/draw_v1.cpp b/engines/gob/draw_v1.cpp index de71f20142..94ee32a031 100644 --- a/engines/gob/draw_v1.cpp +++ b/engines/gob/draw_v1.cpp @@ -32,6 +32,7 @@ #include "gob/global.h" #include "gob/util.h" #include "gob/game.h" +#include "gob/resources.h" #include "gob/scenery.h" #include "gob/inter.h" #include "gob/sound/sound.h" @@ -173,12 +174,12 @@ void Draw_v1::printTotText(int16 id) { _vm->_sound->cdPlayMultMusic(); - if (!_vm->_game->_totTextData || !_vm->_game->_totTextData->dataPtr) + TextItem *textItem = _vm->_game->_resources->getTextItem(id); + if (!textItem) return; - dataPtr = _vm->_game->_totTextData->dataPtr + - _vm->_game->_totTextData->items[id].offset; - ptr = dataPtr; + dataPtr = textItem->getData(); + ptr = dataPtr; destX = READ_LE_UINT16(ptr) & 0x7FFF; destY = READ_LE_UINT16(ptr + 2); @@ -312,7 +313,9 @@ void Draw_v1::printTotText(int16 id) { } } + delete textItem; _renderFlags = savedFlags; + if (_renderFlags & RENDERFLAG_COLLISIONS) _vm->_game->checkCollisions(0, 0, 0, 0); @@ -323,11 +326,10 @@ void Draw_v1::printTotText(int16 id) { } void Draw_v1::spriteOperation(int16 operation) { - uint16 id; - byte *dataBuf; int16 len; int16 x, y; int16 perLine; + Resource *resource; if (_sourceSurface >= 100) _sourceSurface -= 80; @@ -396,30 +398,20 @@ void Draw_v1::spriteOperation(int16 operation) { break; case DRAW_LOADSPRITE: - id = _spriteLeft; - if (id >= 30000) { - dataBuf = - _vm->_game->loadExtData(id, &_spriteRight, &_spriteBottom); - _vm->_video->drawPackedSprite(dataBuf, - _spriteRight, _spriteBottom, - _destSpriteX, _destSpriteY, - _transparency, *_spritesArray[_destSurface]); - dirtiedRect(_destSurface, _destSpriteX, _destSpriteY, - _destSpriteX + _spriteRight - 1, _destSpriteY + _spriteBottom - 1); - delete[] dataBuf; - break; - } + resource = _vm->_game->_resources->getResource((uint16) _spriteLeft, + &_spriteRight, &_spriteBottom); - if (!(dataBuf = _vm->_game->loadTotResource(id, 0, &_spriteRight, &_spriteBottom))) + if (!resource) break; - _vm->_video->drawPackedSprite(dataBuf, - _spriteRight, _spriteBottom, - _destSpriteX, _destSpriteY, - _transparency, *_spritesArray[_destSurface]); + _vm->_video->drawPackedSprite(resource->getData(), + _spriteRight, _spriteBottom, _destSpriteX, _destSpriteY, + _transparency, *_spritesArray[_destSurface]); dirtiedRect(_destSurface, _destSpriteX, _destSpriteY, _destSpriteX + _spriteRight - 1, _destSpriteY + _spriteBottom - 1); + + delete resource; break; case DRAW_PRINTTEXT: diff --git a/engines/gob/draw_v2.cpp b/engines/gob/draw_v2.cpp index 4bb8120e3a..2843456f42 100644 --- a/engines/gob/draw_v2.cpp +++ b/engines/gob/draw_v2.cpp @@ -32,6 +32,8 @@ #include "gob/global.h" #include "gob/util.h" #include "gob/game.h" +#include "gob/script.h" +#include "gob/resources.h" #include "gob/scenery.h" #include "gob/inter.h" #include "gob/video.h" @@ -205,12 +207,6 @@ void Draw_v2::printTotText(int16 id) { id &= 0xFFF; - if (!_vm->_game->_totTextData || !_vm->_game->_totTextData->dataPtr || - (id >= _vm->_game->_totTextData->itemsCount) || - (_vm->_game->_totTextData->items[id].offset == -1) || - (_vm->_game->_totTextData->items[id].size == 0)) - return; - _vm->validateLanguage(); // WORKAROUND: In the scripts of some Gobliins 2 versions, the dialog text IDs @@ -234,13 +230,18 @@ void Draw_v2::printTotText(int16 id) { } - size = _vm->_game->_totTextData->items[id].size; - dataPtr = _vm->_game->_totTextData->dataPtr + - _vm->_game->_totTextData->items[id].offset; - ptr = dataPtr; + TextItem *textItem = _vm->_game->_resources->getTextItem(id); + if (!textItem) + return; - if ((_renderFlags & RENDERFLAG_SKIPOPTIONALTEXT) && (ptr[1] & 0x80)) + size = textItem->getSize(); + dataPtr = textItem->getData(); + ptr = dataPtr; + + if ((_renderFlags & RENDERFLAG_SKIPOPTIONALTEXT) && (ptr[1] & 0x80)) { + delete textItem; return; + } if (_renderFlags & RENDERFLAG_DOUBLECOORDS) { destX = (READ_LE_UINT16(ptr) & 0x7FFF) * 2; @@ -328,7 +329,7 @@ void Draw_v2::printTotText(int16 id) { ptrEnd = ptr; while (((ptrEnd - dataPtr) < size) && (*ptrEnd != 1)) { // Converting to unknown commands/characters to spaces - if ((_vm->_game->_totFileData[0x29] < 0x32) && (*ptrEnd > 3) && (*ptrEnd < 32)) + if ((_vm->_game->_script->getVersionMinor() < 2) && (*ptrEnd > 3) && (*ptrEnd < 32)) *ptrEnd = 32; switch (*ptrEnd) { @@ -524,7 +525,7 @@ void Draw_v2::printTotText(int16 id) { case 10: str[0] = (char) 255; WRITE_LE_UINT16((uint16 *) (str + 1), - ptr - _vm->_game->_totTextData->dataPtr); + ptr - _vm->_game->_resources->getTexts()); str[3] = 0; ptr++; for (int i = *ptr++; i > 0; i--) { @@ -597,7 +598,9 @@ void Draw_v2::printTotText(int16 id) { } } + delete textItem; _renderFlags = savedFlags; + if (!(_renderFlags & RENDERFLAG_COLLISIONS)) return; @@ -610,14 +613,13 @@ void Draw_v2::printTotText(int16 id) { } void Draw_v2::spriteOperation(int16 operation) { - uint16 id; - byte *dataBuf; int16 len; int16 x, y; SurfaceDescPtr sourceSurf, destSurf; bool deltaVeto; int16 left; int16 ratio; + Resource *resource; // Always assigned to -1 in Game::loadTotFile() int16 someHandle = -1; @@ -705,6 +707,11 @@ void Draw_v2::spriteOperation(int16 operation) { sourceSurf = _spritesArray[_sourceSurface]; destSurf = _spritesArray[_destSurface]; + if (!destSurf) { + warning("Can't do operation %d on surface %d: nonexistent", operation, _destSurface); + return; + } + switch (operation) { case DRAW_BLITSURF: case DRAW_DRAWLETTER: @@ -755,41 +762,20 @@ void Draw_v2::spriteOperation(int16 operation) { break; case DRAW_LOADSPRITE: - id = _spriteLeft; - - if ((id >= 30000) || (_vm->_game->_lomHandle >= 0)) { - dataBuf = 0; + resource = _vm->_game->_resources->getResource((uint16) _spriteLeft, + &_spriteRight, &_spriteBottom); - if (_vm->_game->_lomHandle >= 0) - warning("Urban Stub: LOADSPRITE %d, LOM", id); - else - dataBuf = _vm->_game->loadExtData(id, &_spriteRight, &_spriteBottom); - - if (!dataBuf) - break; - - _vm->_video->drawPackedSprite(dataBuf, - _spriteRight, _spriteBottom, _destSpriteX, _destSpriteY, - _transparency, *_spritesArray[_destSurface]); - - dirtiedRect(_destSurface, _destSpriteX, _destSpriteY, - _destSpriteX + _spriteRight - 1, _destSpriteY + _spriteBottom - 1); - - delete[] dataBuf; + if (!resource) break; - } - // Load from .TOT resources - if (!(dataBuf = _vm->_game->loadTotResource(id, 0, &_spriteRight, &_spriteBottom))) - break; - - _vm->_video->drawPackedSprite(dataBuf, - _spriteRight, _spriteBottom, - _destSpriteX, _destSpriteY, - _transparency, *_spritesArray[_destSurface]); + _vm->_video->drawPackedSprite(resource->getData(), + _spriteRight, _spriteBottom, _destSpriteX, _destSpriteY, + _transparency, *_spritesArray[_destSurface]); dirtiedRect(_destSurface, _destSpriteX, _destSpriteY, _destSpriteX + _spriteRight - 1, _destSpriteY + _spriteBottom - 1); + + delete resource; break; case DRAW_PRINTTEXT: @@ -802,7 +788,7 @@ void Draw_v2::spriteOperation(int16 operation) { if (((int8) _textToPrint[0]) == -1) { _vm->validateLanguage(); - dataBuf = _vm->_game->_totTextData->dataPtr + _textToPrint[1] + 1; + byte *dataBuf = _vm->_game->_resources->getTexts() + _textToPrint[1] + 1; len = *dataBuf++; for (int i = 0; i < len; i++, dataBuf += 2) { _vm->_video->drawLetter(READ_LE_UINT16(dataBuf), _destSpriteX, diff --git a/engines/gob/expression.cpp b/engines/gob/expression.cpp new file mode 100644 index 0000000000..61376b2212 --- /dev/null +++ b/engines/gob/expression.cpp @@ -0,0 +1,1144 @@ +/* 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. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "common/endian.h" + +#include "gob/gob.h" +#include "gob/expression.h" +#include "gob/global.h" +#include "gob/game.h" +#include "gob/script.h" +#include "gob/inter.h" + +namespace Gob { + +Expression::Stack::Stack(size_t size) { + opers = new byte[size]; + values = new int32[size]; + memset(opers , 0, size * sizeof(byte )); + memset(values, 0, size * sizeof(int32)); +} + +Expression::Stack::~Stack() { + delete[] opers; + delete[] values; +} + +Expression::StackFrame::StackFrame(const Stack &stack) { + opers = stack.opers - 1; + values = stack.values - 1; + pos = -1; +} + +void Expression::StackFrame::push(int count) { + opers += count; + values += count; + pos += count; +} + +void Expression::StackFrame::pop(int count) { + opers -= count; + values -= count; + pos -= count; +} + +Expression::Expression(GobEngine *vm) : _vm(vm) { + _resultStr[0] = 0; + _resultInt = 0; +} + +int32 Expression::encodePtr(byte *ptr, int type) { + int32 offset = 0; + + switch (type) { + case kExecPtr: + offset = _vm->_game->_script->getOffset(ptr); + break; + case kInterVar: + offset = ptr - ((byte *) _vm->_inter->_variables->getAddressOff8(0)); + break; + case kResStr: + offset = ptr - ((byte *) _resultStr); + break; + default: + error("Expression::encodePtr(): Unknown pointer type"); + } + assert((offset & 0xF0000000) == 0); + return (type << 28) | offset; +} + +byte *Expression::decodePtr(int32 n) { + byte *ptr; + + switch (n >> 28) { + case kExecPtr: + return _vm->_game->_script->getData((n & 0x0FFFFFFF)); + case kInterVar: + ptr = (byte *) _vm->_inter->_variables->getAddressOff8(0); + break; + case kResStr: + ptr = (byte *) _resultStr; + break; + default: + error("Expression::decodePtr(): Unknown pointer type"); + } + return ptr + (n & 0x0FFFFFFF); +} + +void Expression::skipExpr(char stopToken) { + int16 dimCount; + byte operation; + int16 num; + int16 dim; + + num = 0; + while (true) { + operation = _vm->_game->_script->readByte(); + + if ((operation >= 14) && (operation <= OP_FUNC)) { + switch (operation) { + case 14: + _vm->_game->_script->skip(4); + if (_vm->_game->_script->peekByte() == 97) + _vm->_game->_script->skip(1); + break; + + case OP_LOAD_VAR_INT16: + case OP_LOAD_VAR_INT8: + case OP_LOAD_IMM_INT16: + case OP_LOAD_VAR_INT32: + case OP_LOAD_VAR_INT32_AS_INT16: + _vm->_game->_script->skip(2); + break; + + case OP_LOAD_IMM_INT32: + _vm->_game->_script->skip(4); + break; + + case OP_LOAD_IMM_INT8: + _vm->_game->_script->skip(1); + break; + + case OP_LOAD_IMM_STR: + _vm->_game->_script->skip(strlen(_vm->_game->_script->peekString()) + 1); + break; + + case OP_LOAD_VAR_STR: + _vm->_game->_script->skip(2); + if (_vm->_game->_script->peekByte() == 13) { + _vm->_game->_script->skip(1); + skipExpr(OP_END_MARKER); + } + break; + + case 15: + _vm->_game->_script->skip(2); + + case OP_ARRAY_INT8: + case OP_ARRAY_INT32: + case OP_ARRAY_INT16: + case OP_ARRAY_STR: + dimCount = _vm->_game->_script->peekByte(2); + // skip header and dimensions + _vm->_game->_script->skip(3 + dimCount); + // skip indices + for (dim = 0; dim < dimCount; dim++) + skipExpr(OP_END_MARKER); + + if ((operation == OP_ARRAY_STR) && (_vm->_game->_script->peekByte() == 13)) { + _vm->_game->_script->skip(1); + skipExpr(OP_END_MARKER); + } + break; + + case OP_FUNC: + _vm->_game->_script->skip(1); + skipExpr(OP_END_EXPR); + } + continue; + } // if ((operation >= OP_ARRAY_INT8) && (operation <= OP_FUNC)) + + if (operation == OP_BEGIN_EXPR) { + num++; + continue; + } + + if ((operation == OP_NOT) || ((operation >= OP_NEG) && (operation <= 8))) + continue; + + if ((operation >= OP_OR) && (operation <= OP_NEQ)) + continue; + + if (operation == OP_END_EXPR) + num--; + + if (operation != stopToken) + continue; + + if ((stopToken != OP_END_EXPR) || (num < 0)) + return; + } +} + +void Expression::printExpr(char stopToken) { + // Expression printing disabled by default + return; + + int32 savedPos = _vm->_game->_script->pos(); + printExpr_internal(stopToken); + + // restore IP to start of expression + _vm->_game->_script->seek(savedPos); +} + +void Expression::printExpr_internal(char stopToken) { + int16 dimCount; + byte operation; + int16 num; + int16 dim; + byte *arrDesc; + byte func; + + num = 0; + while (true) { + operation = _vm->_game->_script->readByte(); + + if ((operation >= OP_ARRAY_INT8) && (operation <= OP_FUNC)) { + // operands + + switch (operation) { + case OP_LOAD_VAR_INT16: // int16 variable load + debugN(5, "var16_%d", _vm->_game->_script->readUint16()); + break; + + case OP_LOAD_VAR_INT8: // int8 variable load: + debugN(5, "var8_%d", _vm->_game->_script->readUint16()); + break; + + case OP_LOAD_IMM_INT32: // int32/uint32 immediate + debugN(5, "%d", _vm->_game->_script->readInt32()); + break; + + case OP_LOAD_IMM_INT16: // int16 immediate + debugN(5, "%d", _vm->_game->_script->readInt16()); + break; + + case OP_LOAD_IMM_INT8: // int8 immediate + debugN(5, "%d", _vm->_game->_script->readInt8()); + break; + + case OP_LOAD_IMM_STR: // string immediate + debugN(5, "\42%s\42", _vm->_game->_script->readString()); + break; + + case OP_LOAD_VAR_INT32: + case OP_LOAD_VAR_INT32_AS_INT16: + debugN(5, "var_%d", _vm->_game->_script->readUint16()); + break; + + case OP_LOAD_VAR_STR: // string variable load + debugN(5, "(&var_%d)", _vm->_game->_script->readUint16()); + if (_vm->_game->_script->peekByte() == 13) { + _vm->_game->_script->skip(1); + debugN(5, "{"); + printExpr_internal(OP_END_MARKER); // this also prints the closing } + } + break; + + case OP_ARRAY_INT8: // int8 array access + case OP_ARRAY_INT32: // int32 array access + case OP_ARRAY_INT16: // int16 array access + case OP_ARRAY_STR: // string array access + debugN(5, "\n"); + if (operation == OP_ARRAY_STR) + debugN(5, "(&"); + + debugN(5, "var_%d[", _vm->_game->_script->readInt16()); + dimCount = _vm->_game->_script->readByte(); + arrDesc = _vm->_game->_script->getData() + _vm->_game->_script->pos(); + _vm->_game->_script->skip(dimCount); + for (dim = 0; dim < dimCount; dim++) { + printExpr_internal(OP_END_MARKER); + debugN(5, " of %d", (int16) arrDesc[dim]); + if (dim != dimCount - 1) + debugN(5, ","); + } + debugN(5, "]"); + if (operation == OP_ARRAY_STR) + debugN(5, ")"); + + if ((operation == OP_ARRAY_STR) && (_vm->_game->_script->peekByte() == 13)) { + _vm->_game->_script->skip(1); + debugN(5, "{"); + printExpr_internal(OP_END_MARKER); // this also prints the closing } + } + break; + + case OP_FUNC: // function + func = _vm->_game->_script->readByte(); + if (func == FUNC_SQR) + debugN(5, "sqr("); + else if (func == FUNC_RAND) + debugN(5, "rand("); + else if (func == FUNC_ABS) + debugN(5, "abs("); + else if ((func == FUNC_SQRT1) || (func == FUNC_SQRT2) || (func == FUNC_SQRT3)) + debugN(5, "sqrt("); + else + debugN(5, "id("); + printExpr_internal(OP_END_EXPR); + break; + } + continue; + } // if ((operation >= OP_ARRAY_INT8) && (operation <= OP_FUNC)) + + // operators + switch (operation) { + case OP_BEGIN_EXPR: + debugN(5, "("); + break; + + case OP_NOT: + debugN(5, "!"); + break; + + case OP_END_EXPR: + debugN(5, ")"); + break; + + case OP_NEG: + debugN(5, "-"); + break; + + case OP_ADD: + debugN(5, "+"); + break; + + case OP_SUB: + debugN(5, "-"); + break; + + case OP_BITOR: + debugN(5, "|"); + break; + + case OP_MUL: + debugN(5, "*"); + break; + + case OP_DIV: + debugN(5, "/"); + break; + + case OP_MOD: + debugN(5, "%%"); + break; + + case OP_BITAND: + debugN(5, "&"); + break; + + case OP_OR: + debugN(5, "||"); + break; + + case 31: + debugN(5, "&&"); + break; + + case OP_LESS: + debugN(5, "<"); + break; + + case OP_LEQ: + debugN(5, "<="); + break; + + case OP_GREATER: + debugN(5, ">"); + break; + + case OP_GEQ: + debugN(5, ">="); + break; + + case OP_EQ: + debugN(5, "=="); + break; + + case OP_NEQ: + debugN(5, "!="); + break; + + case 99: + debugN(5, "\n"); + break; + + case OP_END_MARKER: + debugN(5, "}"); + if (stopToken != OP_END_MARKER) { + debugN(5, "Closing paren without opening?"); + } + break; + + default: + debugN(5, "<%d>", (int16) operation); + error("Expression::printExpr(): invalid operator in expression"); + break; + } + + if (operation == OP_BEGIN_EXPR) { + num++; + continue; + } + + if ((operation == OP_NOT) || ((operation >= OP_NEG) && (operation <= 8))) + continue; + + if ((operation >= OP_OR) && (operation <= OP_NEQ)) + continue; + + if (operation == OP_END_EXPR) + num--; + + if (operation == stopToken) { + if ((stopToken != OP_END_EXPR) || (num < 0)) { + return; + } + } + } +} + + +void Expression::printVarIndex() { + byte *arrDesc; + int16 dim; + int16 dimCount; + int16 operation; + int16 temp; + + int32 pos = _vm->_game->_script->pos(); + + operation = _vm->_game->_script->readByte(); + switch (operation) { + case OP_LOAD_VAR_INT32: + case OP_LOAD_VAR_STR: + temp = _vm->_game->_script->readUint16() * 4; + debugN(5, "&var_%d", temp); + if ((operation == OP_LOAD_VAR_STR) && (_vm->_game->_script->peekByte() == 13)) { + _vm->_game->_script->skip(1); + debugN(5, "+"); + printExpr(OP_END_MARKER); + } + break; + + case OP_ARRAY_INT32: + case OP_ARRAY_STR: + debugN(5, "&var_%d[", _vm->_game->_script->readUint16()); + dimCount = _vm->_game->_script->readByte(); + arrDesc = _vm->_game->_script->getData() + _vm->_game->_script->pos(); + _vm->_game->_script->skip(dimCount); + for (dim = 0; dim < dimCount; dim++) { + printExpr(OP_END_MARKER); + debugN(5, " of %d", (int16) arrDesc[dim]); + if (dim != dimCount - 1) + debugN(5, ","); + } + debugN(5, "]"); + + if ((operation == OP_ARRAY_STR) && (_vm->_game->_script->peekByte() == 13)) { + _vm->_game->_script->skip(1); + debugN(5, "+"); + printExpr(OP_END_MARKER); + } + break; + + default: + debugN(5, "var_0"); + break; + } + debugN(5, "\n"); + + _vm->_game->_script->seek(pos); + return; +} + +int Expression::cmpHelper(const StackFrame &stackFrame) { + byte type = stackFrame.opers[-3]; + int cmpTemp = 0; + + if (type == OP_LOAD_IMM_INT16) { + cmpTemp = (int)stackFrame.values[-3] - (int)stackFrame.values[-1]; + } else if (type == OP_LOAD_IMM_STR) { + if ((char *)decodePtr(stackFrame.values[-3]) != _resultStr) { + strcpy(_resultStr, (char *)decodePtr(stackFrame.values[-3])); + stackFrame.values[-3] = encodePtr((byte *) _resultStr, kResStr); + } + cmpTemp = strcmp(_resultStr, (char *)decodePtr(stackFrame.values[-1])); + } + + return cmpTemp; +} + +bool Expression::getVarBase(uint32 &varBase, bool mindStop, + uint16 *size, uint16 *type) { + + varBase = 0; + + byte operation = _vm->_game->_script->peekByte(); + while ((operation == 14) || (operation == 15)) { + _vm->_game->_script->skip(1); + + if (operation == 14) { + // Add a direct offset + + varBase += _vm->_game->_script->readInt16() * 4; + + if (size) + *size = _vm->_game->_script->peekUint16(); + if (type) + *type = 14; + + _vm->_game->_script->skip(2); + + debugC(2, kDebugExpression, "varBase: %d, by %d", varBase, operation); + + if (_vm->_game->_script->peekByte() != 97) { + if (mindStop) + return true; + } else + _vm->_game->_script->skip(1); + + } else if (operation == 15) { + // Add an offset from an array + + varBase += _vm->_game->_script->readInt16() * 4; + + uint16 offset1 = _vm->_game->_script->readUint16(); + + if (size) + *size = offset1; + if (type) + *type = 15; + + uint8 dimCount = _vm->_game->_script->readByte(); + byte *dimArray = _vm->_game->_script->getData() + _vm->_game->_script->pos(); + + _vm->_game->_script->skip(dimCount); + + uint16 offset2 = 0; + for (int i = 0; i < dimCount; i++) { + int16 dim = CLIP<int>(parseValExpr(OP_END_MARKER), 0, dimArray[i] - 1); + + offset2 = offset2 * dimArray[i] + dim; + } + + varBase += offset2 * offset1 * 4; + + debugC(2, kDebugExpression, "varBase: %d, by %d", varBase, operation); + + if (_vm->_game->_script->peekByte() != 97) { + if (mindStop) + return true; + } else + _vm->_game->_script->skip(1); + } + + operation = _vm->_game->_script->peekByte(); + } + + return false; +} + +int16 Expression::parseVarIndex(uint16 *size, uint16 *type) { + int16 temp2; + byte *arrDesc; + int16 dim; + int16 dimCount; + int16 operation; + int16 temp; + int16 offset; + int16 val; + uint32 varBase; + + if (getVarBase(varBase, true, size, type)) + return varBase; + + operation = _vm->_game->_script->readByte(); + + if (size) + *size = 0; + if (type) + *type = operation; + + debugC(5, kDebugExpression, "var parse = %d", operation); + switch (operation) { + case OP_ARRAY_INT8: + case OP_ARRAY_INT32: + case OP_ARRAY_INT16: + case OP_ARRAY_STR: + temp = _vm->_game->_script->readInt16(); + dimCount = _vm->_game->_script->readByte(); + arrDesc = _vm->_game->_script->getData() + _vm->_game->_script->pos(); + _vm->_game->_script->skip(dimCount); + offset = 0; + for (dim = 0; dim < dimCount; dim++) { + temp2 = parseValExpr(OP_END_MARKER); + offset = arrDesc[dim] * offset + temp2; + } + if (operation == OP_ARRAY_INT8) + return varBase + temp + offset; + if (operation == OP_ARRAY_INT32) + return varBase + (temp + offset) * 4; + if (operation == OP_ARRAY_INT16) + return varBase + (temp + offset) * 2; + temp *= 4; + offset *= 4; + if (_vm->_game->_script->peekByte() == 13) { + _vm->_game->_script->skip(1); + temp += parseValExpr(OP_END_MARKER); + } + return varBase + offset * _vm->_global->_inter_animDataSize + temp; + + case OP_LOAD_VAR_INT16: + return varBase + _vm->_game->_script->readInt16() * 2; + + case OP_LOAD_VAR_INT8: + return varBase + _vm->_game->_script->readInt16(); + + case OP_LOAD_VAR_INT32: + case OP_LOAD_VAR_INT32_AS_INT16: + case OP_LOAD_VAR_STR: + temp = _vm->_game->_script->readInt16() * 4; + debugC(5, kDebugExpression, "oper = %d", _vm->_game->_script->peekInt16()); + if ((operation == OP_LOAD_VAR_STR) && (_vm->_game->_script->peekByte() == 13)) { + _vm->_game->_script->skip(1); + val = parseValExpr(OP_END_MARKER); + temp += val; + debugC(5, kDebugExpression, "parse subscript = %d", val); + } + return varBase + temp; + + default: + return 0; + } +} + +int16 Expression::parseValExpr(byte stopToken) { + parseExpr(stopToken, 0); + + return _resultInt; +} + +// Load a value according to the operation +void Expression::loadValue(byte operation, uint32 varBase, const StackFrame &stackFrame) { + int16 dimCount; + int16 temp; + int16 temp2; + int16 offset; + int16 dim; + byte *arrDescPtr; + int32 prevPrevVal; + int32 prevVal; + int32 curVal; + + switch (operation) { + case OP_ARRAY_INT8: + case OP_ARRAY_INT32: + case OP_ARRAY_INT16: + case OP_ARRAY_STR: + *stackFrame.opers = (operation == OP_ARRAY_STR) ? OP_LOAD_IMM_STR : OP_LOAD_IMM_INT16; + temp = _vm->_game->_script->readInt16(); + dimCount = _vm->_game->_script->readByte(); + arrDescPtr = _vm->_game->_script->getData() + _vm->_game->_script->pos(); + _vm->_game->_script->skip(dimCount); + offset = 0; + for (dim = 0; dim < dimCount; dim++) { + temp2 = parseValExpr(OP_END_MARKER); + offset = offset * arrDescPtr[dim] + temp2; + } + if (operation == OP_ARRAY_INT8) + *stackFrame.values = (int8) READ_VARO_UINT8(varBase + temp + offset); + else if (operation == OP_ARRAY_INT32) + *stackFrame.values = READ_VARO_UINT32(varBase + temp * 4 + offset * 4); + else if (operation == OP_ARRAY_INT16) + *stackFrame.values = (int16) READ_VARO_UINT16(varBase + temp * 2 + offset * 2); + else if (operation == OP_ARRAY_STR) { + *stackFrame.values = encodePtr(_vm->_inter->_variables->getAddressOff8( + varBase + temp * 4 + offset * _vm->_global->_inter_animDataSize * 4), + kInterVar); + if (_vm->_game->_script->peekByte() == 13) { + _vm->_game->_script->skip(1); + temp2 = parseValExpr(OP_END_MARKER); + *stackFrame.opers = OP_LOAD_IMM_INT16; + *stackFrame.values = READ_VARO_UINT8(varBase + temp * 4 + + offset * 4 * _vm->_global->_inter_animDataSize + temp2); + } + } + break; + + case OP_LOAD_VAR_INT16: + *stackFrame.opers = OP_LOAD_IMM_INT16; + *stackFrame.values = (int16) READ_VARO_UINT16(varBase + _vm->_game->_script->readInt16() * 2); + break; + + case OP_LOAD_VAR_INT8: + *stackFrame.opers = OP_LOAD_IMM_INT16; + *stackFrame.values = (int8) READ_VARO_UINT8(varBase + _vm->_game->_script->readInt16()); + break; + + case OP_LOAD_IMM_INT32: + *stackFrame.opers = OP_LOAD_IMM_INT16; + *stackFrame.values = _vm->_game->_script->readInt32(); + break; + + case OP_LOAD_IMM_INT16: + *stackFrame.opers = OP_LOAD_IMM_INT16; + *stackFrame.values = _vm->_game->_script->readInt16(); + break; + + case OP_LOAD_IMM_INT8: + *stackFrame.opers = OP_LOAD_IMM_INT16; + *stackFrame.values = _vm->_game->_script->readInt8(); + break; + + case OP_LOAD_IMM_STR: + *stackFrame.opers = OP_LOAD_IMM_STR; + *stackFrame.values = encodePtr((byte *) _vm->_game->_script->readString(), kExecPtr); + break; + + case OP_LOAD_VAR_INT32: + *stackFrame.opers = OP_LOAD_IMM_INT16; + *stackFrame.values = READ_VARO_UINT32(varBase + _vm->_game->_script->readInt16() * 4); + break; + + case OP_LOAD_VAR_INT32_AS_INT16: + *stackFrame.opers = OP_LOAD_IMM_INT16; + *stackFrame.values = (int16) READ_VARO_UINT16(varBase + _vm->_game->_script->readInt16() * 4); + break; + + case OP_LOAD_VAR_STR: + *stackFrame.opers = OP_LOAD_IMM_STR; + temp = _vm->_game->_script->readInt16() * 4; + *stackFrame.values = encodePtr(_vm->_inter->_variables->getAddressOff8(varBase + temp), kInterVar); + if (_vm->_game->_script->peekByte() == 13) { + _vm->_game->_script->skip(1); + temp += parseValExpr(OP_END_MARKER); + *stackFrame.opers = OP_LOAD_IMM_INT16; + *stackFrame.values = READ_VARO_UINT8(varBase + temp); + } + break; + + case OP_FUNC: + operation = _vm->_game->_script->readByte(); + parseExpr(OP_END_EXPR, 0); + + switch (operation) { + case FUNC_SQRT1: + case FUNC_SQRT2: + case FUNC_SQRT3: + curVal = 1; + prevVal = 1; + + do { + prevPrevVal = prevVal; + prevVal = curVal; + curVal = (curVal + _resultInt / curVal) / 2; + } while ((curVal != prevVal) && (curVal != prevPrevVal)); + _resultInt = curVal; + break; + + case FUNC_SQR: + _resultInt = + _resultInt * _resultInt; + break; + + case FUNC_ABS: + if (_resultInt < 0) + _resultInt = -_resultInt; + break; + + case FUNC_RAND: + _resultInt = + _vm->_util->getRandom(_resultInt); + break; + } + + *stackFrame.opers = OP_LOAD_IMM_INT16; + *stackFrame.values = _resultInt; + break; + } +} + +void Expression::simpleArithmetic1(StackFrame &stackFrame) { + switch (stackFrame.opers[-1]) { + case OP_ADD: + if (stackFrame.opers[-2] == OP_LOAD_IMM_STR) { + if ((char *) decodePtr(stackFrame.values[-2]) != _resultStr) { + strcpy(_resultStr, (char *) decodePtr(stackFrame.values[-2])); + stackFrame.values[-2] = encodePtr((byte *) _resultStr, kResStr); + } + strcat(_resultStr, (char *) decodePtr(stackFrame.values[0])); + stackFrame.pop(2); + } + break; + + case OP_MUL: + stackFrame.values[-2] *= stackFrame.values[0]; + stackFrame.pop(2); + break; + + case OP_DIV: + stackFrame.values[-2] /= stackFrame.values[0]; + stackFrame.pop(2); + break; + + case OP_MOD: + stackFrame.values[-2] %= stackFrame.values[0]; + stackFrame.pop(2); + break; + + case OP_BITAND: + stackFrame.values[-2] &= stackFrame.values[0]; + stackFrame.pop(2); + break; + } +} + +void Expression::simpleArithmetic2(StackFrame &stackFrame) { + if (stackFrame.pos > 1) { + if (stackFrame.opers[-2] == OP_NEG) { + stackFrame.opers[-2] = OP_LOAD_IMM_INT16; + stackFrame.values[-2] = -stackFrame.values[-1]; + stackFrame.pop(); + } else if (stackFrame.opers[-2] == OP_NOT) { + stackFrame.opers[-2] = (stackFrame.opers[-1] == GOB_FALSE) ? GOB_TRUE : GOB_FALSE; + stackFrame.pop(); + } + } + + if (stackFrame.pos > 2) { + switch (stackFrame.opers[-2]) { + case OP_MUL: + stackFrame.values[-3] *= stackFrame.values[-1]; + stackFrame.pop(2); + break; + + case OP_DIV: + stackFrame.values[-3] /= stackFrame.values[-1]; + stackFrame.pop(2); + break; + + case OP_MOD: + stackFrame.values[-3] %= stackFrame.values[-1]; + stackFrame.pop(2); + break; + + case OP_BITAND: + stackFrame.values[-3] &= stackFrame.values[-1]; + stackFrame.pop(2); + break; + } + } + +} + +// Complex arithmetics with brackets +bool Expression::complexArithmetic(Stack &stack, StackFrame &stackFrame, int16 brackStart) { + switch (stackFrame.opers[-2]) { + case OP_ADD: + if (stack.opers[brackStart] == OP_LOAD_IMM_INT16) { + stack.values[brackStart] += stackFrame.values[-1]; + } else if (stack.opers[brackStart] == OP_LOAD_IMM_STR) { + if ((char *) decodePtr(stack.values[brackStart]) != _resultStr) { + strcpy(_resultStr, (char *) decodePtr(stack.values[brackStart])); + stack.values[brackStart] = + encodePtr((byte *) _resultStr, kResStr); + } + strcat(_resultStr, (char *) decodePtr(stackFrame.values[-1])); + } + stackFrame.pop(2); + break; + + case OP_SUB: + stack.values[brackStart] -= stackFrame.values[-1]; + stackFrame.pop(2); + break; + + case OP_BITOR: + stack.values[brackStart] |= stackFrame.values[-1]; + stackFrame.pop(2); + break; + + case OP_MUL: + stackFrame.values[-3] *= stackFrame.values[-1]; + stackFrame.pop(2); + break; + + case OP_DIV: + stackFrame.values[-3] /= stackFrame.values[-1]; + stackFrame.pop(2); + break; + + case OP_MOD: + stackFrame.values[-3] %= stackFrame.values[-1]; + stackFrame.pop(2); + break; + + case OP_BITAND: + stackFrame.values[-3] &= stackFrame.values[-1]; + stackFrame.pop(2); + break; + + case OP_OR: + // (x OR false) == x + // (x OR true) == true + if (stackFrame.opers[-3] == GOB_FALSE) + stackFrame.opers[-3] = stackFrame.opers[-1]; + stackFrame.pop(2); + break; + + case OP_AND: + // (x AND false) == false + // (x AND true) == x + if (stackFrame.opers[-3] == GOB_TRUE) + stackFrame.opers[-3] = stackFrame.opers[-1]; + stackFrame.pop(2); + break; + + case OP_LESS: + stackFrame.opers[-3] = (cmpHelper(stackFrame) < 0) ? GOB_TRUE : GOB_FALSE; + stackFrame.pop(2); + break; + + case OP_LEQ: + stackFrame.opers[-3] = (cmpHelper(stackFrame) <= 0) ? GOB_TRUE : GOB_FALSE; + stackFrame.pop(2); + break; + + case OP_GREATER: + stackFrame.opers[-3] = (cmpHelper(stackFrame) > 0) ? GOB_TRUE : GOB_FALSE; + stackFrame.pop(2); + break; + + case OP_GEQ: + stackFrame.opers[-3] = (cmpHelper(stackFrame) >= 0) ? GOB_TRUE : GOB_FALSE; + stackFrame.pop(2); + break; + + case OP_EQ: + stackFrame.opers[-3] = (cmpHelper(stackFrame) == 0) ? GOB_TRUE : GOB_FALSE; + stackFrame.pop(2); + break; + + case OP_NEQ: + stackFrame.opers[-3] = (cmpHelper(stackFrame) != 0) ? GOB_TRUE : GOB_FALSE; + stackFrame.pop(2); + break; + + default: + return true; + } + + return false; +} + +// Assign the result to the appropriate _result variable +void Expression::getResult(byte operation, int32 value, byte *type) { + if (type != 0) + *type = operation; + + switch (operation) { + case OP_NOT: + if (type != 0) + *type ^= 1; + break; + + case OP_LOAD_IMM_INT16: + _resultInt = value; + break; + + case OP_LOAD_IMM_STR: + if ((char *) decodePtr(value) != _resultStr) + strcpy(_resultStr, (char *) decodePtr(value)); + break; + + case OP_LOAD_VAR_INT32: + case OP_LOAD_VAR_INT32_AS_INT16: + break; + + default: + _resultInt = 0; + if (type != 0) + *type = OP_LOAD_IMM_INT16; + break; + } +} + +int16 Expression::parseExpr(byte stopToken, byte *type) { + Stack stack; + StackFrame stackFrame(stack); + byte operation; + bool escape; + int16 brackStart; + uint32 varBase; + + while (true) { + getVarBase(varBase); + + stackFrame.push(); + + operation = _vm->_game->_script->readByte(); + if ((operation >= OP_ARRAY_INT8) && (operation <= OP_FUNC)) { + + loadValue(operation, varBase, stackFrame); + + if ((stackFrame.pos > 0) && ((stackFrame.opers[-1] == OP_NEG) || (stackFrame.opers[-1] == OP_NOT))) { + stackFrame.pop(); + + if (*stackFrame.opers == OP_NEG) { + *stackFrame.opers = OP_LOAD_IMM_INT16; + stackFrame.values[0] = -stackFrame.values[1]; + } else + *stackFrame.opers = (stackFrame.opers[1] == GOB_FALSE) ? GOB_TRUE : GOB_FALSE; + } + + if (stackFrame.pos <= 0) + continue; + + simpleArithmetic1(stackFrame); + + continue; + } // (op >= OP_ARRAY_INT8) && (op <= OP_FUNC) + + if ((operation == stopToken) || (operation == OP_OR) || + (operation == OP_AND) || (operation == OP_END_EXPR)) { + while (stackFrame.pos >= 2) { + escape = false; + if ((stackFrame.opers[-2] == OP_BEGIN_EXPR) && + ((operation == OP_END_EXPR) || (operation == stopToken))) { + stackFrame.opers[-2] = stackFrame.opers[-1]; + if ((stackFrame.opers[-2] == OP_LOAD_IMM_INT16) || (stackFrame.opers[-2] == OP_LOAD_IMM_STR)) + stackFrame.values[-2] = stackFrame.values[-1]; + + stackFrame.pop(); + + simpleArithmetic2(stackFrame); + + if (operation != stopToken) + break; + } // if ((stackFrame.opers[-2] == OP_BEGIN_EXPR) && ...) + + for (brackStart = (stackFrame.pos - 2); (brackStart > 0) && + (stack.opers[brackStart] < OP_OR) && (stack.opers[brackStart] != OP_BEGIN_EXPR); + brackStart--) + ; + + if ((stack.opers[brackStart] >= OP_OR) || (stack.opers[brackStart] == OP_BEGIN_EXPR)) + brackStart++; + + if (complexArithmetic(stack, stackFrame, brackStart)) + break; + + } // while (stackFrame.pos >= 2) + + if ((operation == OP_OR) || (operation == OP_AND)) { + if (stackFrame.opers[-1] == OP_LOAD_IMM_INT16) { + if (stackFrame.values[-1] != 0) + stackFrame.opers[-1] = GOB_TRUE; + else + stackFrame.opers[-1] = GOB_FALSE; + } + + if (((operation == OP_OR) && (stackFrame.opers[-1] == GOB_TRUE)) || + ((operation == OP_AND) && (stackFrame.opers[-1] == GOB_FALSE))) { + if ((stackFrame.pos > 1) && (stackFrame.opers[-2] == OP_BEGIN_EXPR)) { + skipExpr(OP_END_EXPR); + stackFrame.opers[-2] = stackFrame.opers[-1]; + stackFrame.pop(2); + } else { + skipExpr(stopToken); + } + operation = _vm->_game->_script->peekByte(-1); + if ((stackFrame.pos > 0) && (stackFrame.opers[-1] == OP_NOT)) { + if (stackFrame.opers[0] == GOB_FALSE) + stackFrame.opers[-1] = GOB_TRUE; + else + stackFrame.opers[-1] = GOB_FALSE; + + stackFrame.pop(); + } + } else + stackFrame.opers[0] = operation; + } else + stackFrame.pop(); + + if (operation != stopToken) + continue; + + getResult(stack.opers[0], stack.values[0], type); + + return 0; + } // (operation == stopToken) || (operation == OP_OR) || (operation == OP_AND) || (operation == OP_END_EXPR) + + if ((operation < OP_NEG) || (operation > OP_NOT)) { + if ((operation < OP_LESS) || (operation > OP_NEQ)) + continue; + + if (stackFrame.pos > 2) { + if (stackFrame.opers[-2] == OP_ADD) { + if (stackFrame.opers[-3] == OP_LOAD_IMM_INT16) { + stackFrame.values[-3] += stackFrame.values[-1]; + } else if (stackFrame.opers[-3] == OP_LOAD_IMM_STR) { + if ((char *) decodePtr(stackFrame.values[-3]) != _resultStr) { + strcpy(_resultStr, (char *) decodePtr(stackFrame.values[-3])); + stackFrame.values[-3] = encodePtr((byte *) _resultStr, kResStr); + } + strcat(_resultStr, (char *) decodePtr(stackFrame.values[-1])); + } + stackFrame.pop(2); + + } else if (stackFrame.opers[-2] == OP_SUB) { + stackFrame.values[-3] -= stackFrame.values[-1]; + stackFrame.pop(2); + } else if (stackFrame.opers[-2] == OP_BITOR) { + stackFrame.values[-3] |= stackFrame.values[-1]; + stackFrame.pop(2); + } + } + } + *stackFrame.opers = operation; + } +} + +int32 Expression::getResultInt() { + return _resultInt; +} + +char *Expression::getResultStr() { + return _resultStr; +} + +} // End of namespace Gob diff --git a/engines/gob/expression.h b/engines/gob/expression.h new file mode 100644 index 0000000000..894704e2a9 --- /dev/null +++ b/engines/gob/expression.h @@ -0,0 +1,178 @@ +/* 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. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef GOB_EXPRESSION_H +#define GOB_EXPRESSION_H + +#include "common/scummsys.h" + +namespace Gob { + +class GobEngine; + +enum { + OP_NEG = 1, + OP_ADD = 2, + OP_SUB = 3, + OP_BITOR = 4, + OP_MUL = 5, + OP_DIV = 6, + OP_MOD = 7, + OP_BITAND = 8, + OP_BEGIN_EXPR = 9, + OP_END_EXPR = 10, + OP_NOT = 11, + + OP_END_MARKER = 12, // Marks end of an array or string + + + OP_ARRAY_INT8 = 16, + OP_LOAD_VAR_INT16 = 17, + OP_LOAD_VAR_INT8 = 18, + OP_LOAD_IMM_INT32 = 19, + OP_LOAD_IMM_INT16 = 20, + OP_LOAD_IMM_INT8 = 21, + OP_LOAD_IMM_STR = 22, + OP_LOAD_VAR_INT32 = 23, + OP_LOAD_VAR_INT32_AS_INT16 = 24, + OP_LOAD_VAR_STR = 25, + OP_ARRAY_INT32 = 26, + OP_ARRAY_INT16 = 27, + OP_ARRAY_STR = 28, + + OP_FUNC = 29, + + OP_OR = 30, // Logical OR + OP_AND = 31, // Logical AND + OP_LESS = 32, + OP_LEQ = 33, + OP_GREATER = 34, + OP_GEQ = 35, + OP_EQ = 36, + OP_NEQ = 37 +}; + +enum { + FUNC_SQRT1 = 0, + FUNC_SQRT2 = 1, + FUNC_SQRT3 = 6, + + FUNC_SQR = 5, + FUNC_ABS = 7, + FUNC_RAND = 10 +}; + +enum { + TYPE_IMM_INT8 = OP_LOAD_IMM_INT8, // 21 + TYPE_IMM_INT32 = OP_LOAD_IMM_INT32, // 19 + TYPE_IMM_INT16 = OP_LOAD_IMM_INT16, // 20 + TYPE_IMM_STR = OP_LOAD_IMM_STR, // 22 + TYPE_VAR_INT8 = OP_LOAD_VAR_INT8, // 18 + TYPE_VAR_INT16 = OP_LOAD_VAR_INT16, // 17 + TYPE_VAR_INT32 = OP_LOAD_VAR_INT32, // 23 + TYPE_VAR_STR = OP_LOAD_VAR_STR, // 25 + TYPE_ARRAY_INT8 = OP_ARRAY_INT8, // 16 + TYPE_ARRAY_INT16 = OP_ARRAY_INT16, // 27 + TYPE_ARRAY_INT32 = OP_ARRAY_INT32, // 26 + TYPE_ARRAY_STR = OP_ARRAY_STR, // 28 + TYPE_VAR_INT32_AS_INT16 = OP_LOAD_VAR_INT32_AS_INT16 // 24 +}; + +enum { + // FIXME: The following two 'truth values' are stored inside the list + // of "operators". So they somehow coincide with OP_LOAD_VAR_INT32 + // and OP_LOAD_VAR_INT32_AS_INT16. I haven't yet quite understood + // how, resp. what that means. You have been warned. + GOB_TRUE = 24, + GOB_FALSE = 23 +}; + +class Expression { +public: + Expression(GobEngine *vm); + virtual ~Expression() {} + + void skipExpr(char stopToken); + void printExpr(char stopToken); + void printVarIndex(void); + + int16 parseVarIndex(uint16 *size = 0, uint16 *type = 0); + int16 parseValExpr(byte stopToken = 99); + int16 parseExpr(byte stopToken, byte *type); + + int32 getResultInt(); + char *getResultStr(); + +private: + class Stack { + public: + byte *opers; + int32 *values; + + Stack(size_t size = 20); + ~Stack(); + }; + class StackFrame { + public: + byte *opers; + int32 *values; + int16 pos; + + StackFrame(const Stack &stack); + + void push(int count = 1); + void pop(int count = 1); + }; + + enum PointerType { + kExecPtr = 0, + kInterVar = 1, + kResStr = 2 + }; + + GobEngine *_vm; + + int32 _resultInt; + char _resultStr[200]; + + int32 encodePtr(byte *ptr, int type); + byte *decodePtr(int32 n); + + void printExpr_internal(char stopToken); + + bool getVarBase(uint32 &varBase, bool mindStop = false, + uint16 *size = 0, uint16 *type = 0); + int cmpHelper(const StackFrame &stackFrame); + void loadValue(byte operation, uint32 varBase, const StackFrame &stackFrame); + + void simpleArithmetic1(StackFrame &stackFrame); + void simpleArithmetic2(StackFrame &stackFrame); + bool complexArithmetic(Stack &stack, StackFrame &stackFrame, int16 brackStart); + void getResult(byte operation, int32 value, byte *type); +}; + +} // End of namespace Gob + +#endif // GOB_EXPRESSION_H diff --git a/engines/gob/game.cpp b/engines/gob/game.cpp index 09addc3900..5771ee9f76 100644 --- a/engines/gob/game.cpp +++ b/engines/gob/game.cpp @@ -31,8 +31,10 @@ #include "gob/global.h" #include "gob/util.h" #include "gob/dataio.h" +#include "gob/variables.h" +#include "gob/script.h" +#include "gob/resources.h" #include "gob/inter.h" -#include "gob/parse.h" #include "gob/draw.h" #include "gob/mult.h" #include "gob/videoplayer.h" @@ -40,21 +42,139 @@ namespace Gob { +Environments::Environments(GobEngine *vm) : _vm(vm) { + _environments = new Environment[kEnvironmentCount]; + + for (uint i = 0; i < kEnvironmentCount; i++) { + Environment &e = _environments[i]; + + e.cursorHotspotX = 0; + e.cursorHotspotY = 0; + e.variables = 0; + e.script = 0; + e.resources = 0; + e.curTotFile[0] = '\0'; + } +} + +Environments::~Environments() { + clear(); + + delete[] _environments; +} + +void Environments::clear() { + // Deleting unique variables, script and resources + + for (uint i = 0; i < kEnvironmentCount; i++) { + if (_environments[i].variables == _vm->_inter->_variables) + continue; + + if (!has(_environments[i].variables, i + 1)) + delete _environments[i].variables; + } + + for (uint i = 0; i < kEnvironmentCount; i++) { + if (_environments[i].script == _vm->_game->_script) + continue; + + if (!has(_environments[i].script, i + 1)) + delete _environments[i].script; + } + + for (uint i = 0; i < kEnvironmentCount; i++) { + if (_environments[i].resources == _vm->_game->_resources) + continue; + + if (!has(_environments[i].resources, i + 1)) + delete _environments[i].resources; + } +} + +void Environments::set(uint8 env) { + if (env >= kEnvironmentCount) + return; + + Environment &e = _environments[env]; + + // If it already has a unique script or resource assigned, delete them + if ((e.script != _vm->_game->_script) && !has(e.script, 0, env)) + delete e.script; + if ((e.resources != _vm->_game->_resources) && !has(e.resources, 0, env)) + delete e.resources; + + e.cursorHotspotX = _vm->_draw->_cursorHotspotXVar; + e.cursorHotspotY = _vm->_draw->_cursorHotspotYVar; + e.script = _vm->_game->_script; + e.resources = _vm->_game->_resources; + e.variables = _vm->_inter->_variables; + strncpy(e.curTotFile, _vm->_game->_curTotFile, 14); +} + +void Environments::get(uint8 env) const { + if (env >= kEnvironmentCount) + return; + + const Environment &e = _environments[env]; + + _vm->_draw->_cursorHotspotXVar = e.cursorHotspotX; + _vm->_draw->_cursorHotspotYVar = e.cursorHotspotY; + _vm->_game->_script = e.script; + _vm->_game->_resources = e.resources; + _vm->_inter->_variables = e.variables; + strncpy(_vm->_game->_curTotFile, e.curTotFile, 14); +} + +const char *Environments::getTotFile(uint8 env) const { + if (env >= kEnvironmentCount) + return ""; + + return _environments[env].curTotFile; +} + +bool Environments::has(Variables *variables, uint8 startEnv, int16 except) const { + for (uint i = startEnv; i < kEnvironmentCount; i++) { + if ((except >= 0) && (((uint16) except) == i)) + continue; + + if (_environments[i].variables == variables) + return true; + } + + return false; +} + +bool Environments::has(Script *script, uint8 startEnv, int16 except) const { + for (uint i = startEnv; i < kEnvironmentCount; i++) { + if ((except >= 0) && (((uint16) except) == i)) + continue; + + if (_environments[i].script == script) + return true; + } + + return false; +} + +bool Environments::has(Resources *resources, uint8 startEnv, int16 except) const { + for (uint i = startEnv; i < kEnvironmentCount; i++) { + if ((except >= 0) && (((uint16) except) == i)) + continue; + + if (_environments[i].resources == resources) + return true; + } + + return false; +} + + Game::Game(GobEngine *vm) : _vm(vm) { - _extTable = 0; - _totFileData = 0; - _totResourceTable = 0; - _imFileData = 0; - _extHandle = 0; - _lomHandle = -1; _collisionAreas = 0; _shouldPushColls = 0; _captureCount = 0; - _foundTotLoc = false; - _totTextData = 0; - _collStackSize = 0; for (int i = 0; i < 5; i++) { @@ -63,7 +183,6 @@ Game::Game(GobEngine *vm) : _vm(vm) { } _curTotFile[0] = 0; - _curExtFile[0] = 0; _totToLoad[0] = 0; _startTimeKey = 0; @@ -85,138 +204,20 @@ Game::Game(GobEngine *vm) : _vm(vm) { _noCd = false; _tempStr[0] = 0; - _curImaFile[0] = 0; _collStr[0] = 0; - _backupedCount = 0; - _curBackupPos = 0; + _numEnvironments = 0; + _curEnvironment = 0; - for (int i = 0; i < 5; i++) { - _cursorHotspotXArray[i] = 0; - _cursorHotspotYArray[i] = 0; - _totTextDataArray[i] = 0; - _totFileDataArray[i] = 0; - _totResourceTableArray[i] = 0; - _extTableArray[i] = 0; - _extHandleArray[i] = 0; - _imFileDataArray[i] = 0; - _variablesArray[i] = 0; - _curTotFileArray[i][0] = 0; - } + _environments = new Environments(_vm); + _script = new Script(_vm); + _resources = new Resources(_vm); } Game::~Game() { - delete[] _vm->_game->_totFileData; - if (_vm->_game->_totTextData) { - if (_vm->_game->_totTextData->items) - delete[] _vm->_game->_totTextData->items; - delete _vm->_game->_totTextData; - } - if (_vm->_game->_totResourceTable) { - delete[] _vm->_game->_totResourceTable->items; - delete _vm->_game->_totResourceTable; - } -} - -byte *Game::loadExtData(int16 itemId, int16 *pResWidth, - int16 *pResHeight, uint32 *dataSize) { - int16 commonHandle; - int16 itemsCount; - int32 offset; - uint32 size; - uint32 realSize; - ExtItem *item; - bool isPacked; - int16 handle; - int32 tableSize; - char path[20]; - byte *dataBuf; - byte *packedBuf; - byte *dataPtr; - - itemId -= 30000; - if (_extTable == 0) - return 0; - - commonHandle = -1; - itemsCount = _extTable->itemsCount; - item = &_extTable->items[itemId]; - tableSize = szGame_ExtTable + szGame_ExtItem * itemsCount; - - offset = item->offset; - size = item->size; - isPacked = (item->width & 0x8000) != 0; - - if ((pResWidth != 0) && (pResHeight != 0)) { - *pResWidth = item->width & 0x7FFF; - - if (*pResWidth & 0x4000) - size += 1 << 16; - if (*pResWidth & 0x2000) - size += 2 << 16; - if (*pResWidth & 0x1000) - size += 4 << 16; - - *pResWidth &= 0xFFF; - - *pResHeight = item->height; - debugC(7, kDebugFileIO, "loadExtData(%d, %d, %d)", - itemId, *pResWidth, *pResHeight); - } - - debugC(7, kDebugFileIO, "loadExtData(%d, 0, 0)", itemId); - - if (item->height == 0) - size += (item->width & 0x7FFF) << 16; - - debugC(7, kDebugFileIO, "size: %d off: %d", size, offset); - if (offset < 0) { - offset = -(offset + 1); - tableSize = 0; - _vm->_dataIO->closeData(_extHandle); - strcpy(path, "commun.ex1"); - path[strlen(path) - 1] = *(_totFileData + 0x3C) + '0'; - commonHandle = _vm->_dataIO->openData(path); - handle = commonHandle; - } else - handle = _extHandle; - - DataStream *stream = _vm->_dataIO->openAsStream(handle); - - debugC(7, kDebugFileIO, "off: %d size: %d", offset, tableSize); - stream->seek(offset + tableSize); - realSize = size; - if (isPacked) - dataBuf = new byte[size + 2]; - else - dataBuf = new byte[size]; - - dataPtr = dataBuf; - while (size > 32000) { - // BUG: huge->far conversion. Need normalization? - stream->read(dataPtr, 32000); - size -= 32000; - dataPtr += 32000; - } - stream->read(dataPtr, size); - - delete stream; - if (commonHandle != -1) { - _vm->_dataIO->closeData(commonHandle); - _extHandle = _vm->_dataIO->openData(_curExtFile); - } - - if (isPacked) { - packedBuf = dataBuf; - realSize = READ_LE_UINT32(packedBuf); - dataBuf = new byte[realSize]; - _vm->_dataIO->unpackData(packedBuf, dataBuf); - delete[] packedBuf; - } - - if (dataSize) - *dataSize = realSize; - return dataBuf; + delete _environments; + delete _script; + delete _resources; } void Game::freeCollision(int16 id) { @@ -281,39 +282,9 @@ void Game::capturePop(char doDraw) { _vm->_draw->freeSprite(30 + _captureCount); } -byte *Game::loadTotResource(int16 id, - int16 *dataSize, int16 *width, int16 *height) { - - TotResItem *itemPtr; - int32 offset; - - if (id >= _vm->_game->_totResourceTable->itemsCount) { - warning("Trying to load non-existent TOT resource (%s, %d/%d)", - _curTotFile, id, _totResourceTable->itemsCount - 1); - return 0; - } - - itemPtr = &_totResourceTable->items[id]; - offset = itemPtr->offset; - - if (dataSize) - *dataSize = itemPtr->size; - if (width) - *width = itemPtr->width; - if (height) - *height = itemPtr->height; - - if (offset < 0) { - offset = (-offset - 1) * 4; - return _imFileData + (int32) READ_LE_UINT32(_imFileData + offset); - } else - return _totResourceTable->dataPtr + szGame_TotResTable + - szGame_TotResItem * _totResourceTable->itemsCount + offset; -} - void Game::freeSoundSlot(int16 slot) { if (slot == -1) - slot = _vm->_parse->parseValExpr(); + slot = _vm->_game->_script->readValExpr(); _vm->_sound->sampleFree(_vm->_sound->sampleGetBySlot(slot)); } @@ -416,104 +387,6 @@ int16 Game::adjustKey(int16 key) { return key - 0x20; } -int32 Game::loadTotFile(const char *path) { - int16 handle; - int32 size; - - _lomHandle = -1; - - size = -1; - handle = _vm->_dataIO->openData(path); - if (handle >= 0) { - - if (!scumm_stricmp(path + strlen(path) - 3, "LOM")) { - warning("Urban Stub: loadTotFile %s", path); - - _lomHandle = handle; - - DataStream *stream = _vm->_dataIO->openAsStream(handle); - - stream->seek(48); - size = stream->readUint32LE(); - stream->seek(0); - - _totFileData = new byte[size]; - stream->read(_totFileData, size); - - delete stream; - } else { - _vm->_dataIO->closeData(handle); - size = _vm->_dataIO->getDataSize(path); - _totFileData = _vm->_dataIO->getData(path); - } - - } else { - Common::MemoryReadStream *videoExtraData = _vm->_vidPlayer->getExtraData(path); - - if (videoExtraData) { - warning("Found \"%s\" in video file", path); - - size = videoExtraData->size(); - _totFileData = new byte[size]; - videoExtraData->read(_totFileData, size); - delete videoExtraData; - } else - _totFileData = 0; - } - - return size; -} - -void Game::loadExtTable(void) { - int16 count; - - // Function is correct. [sev] - - _extHandle = _vm->_dataIO->openData(_curExtFile); - if (_extHandle < 0) - return; - - DataStream *stream = _vm->_dataIO->openAsStream(_extHandle); - count = stream->readUint16LE(); - - stream->seek(0); - _extTable = new ExtTable; - _extTable->items = 0; - if (count) - _extTable->items = new ExtItem[count]; - - _extTable->itemsCount = stream->readUint16LE(); - _extTable->unknown = stream->readByte(); - - for (int i = 0; i < count; i++) { - _extTable->items[i].offset = stream->readUint32LE(); - _extTable->items[i].size = stream->readUint16LE(); - _extTable->items[i].width = stream->readUint16LE(); - _extTable->items[i].height = stream->readUint16LE(); - } - - delete stream; -} - -void Game::loadImFile(void) { - char path[20]; - int16 handle; - - if ((_totFileData[0x3D] != 0) && (_totFileData[0x3B] == 0)) - return; - - strcpy(path, "commun.im1"); - if (_totFileData[0x3B] != 0) - path[strlen(path) - 1] = '0' + _totFileData[0x3B]; - - handle = _vm->_dataIO->openData(path); - if (handle < 0) - return; - - _vm->_dataIO->closeData(handle); - _imFileData = _vm->_dataIO->getData(path); -} - void Game::start(void) { _collisionAreas = new Collision[250]; memset(_collisionAreas, 0, 250 * sizeof(Collision)); @@ -533,27 +406,17 @@ void Game::start(void) { void Game::totSub(int8 flags, const char *newTotFile) { int8 curBackupPos; - if (_backupedCount >= 5) + if (_numEnvironments >= Environments::kEnvironmentCount) return; - _cursorHotspotXArray[_backupedCount] = _vm->_draw->_cursorHotspotXVar; - _cursorHotspotYArray[_backupedCount] = _vm->_draw->_cursorHotspotYVar; - _totTextDataArray[_backupedCount] = _totTextData; - _totFileDataArray[_backupedCount] = _totFileData; - _totResourceTableArray[_backupedCount] = _totResourceTable; - _extTableArray[_backupedCount] = _extTable; - _extHandleArray[_backupedCount] = _extHandle; - _imFileDataArray[_backupedCount] = _imFileData; - _variablesArray[_backupedCount] = _vm->_inter->_variables; - strcpy(_curTotFileArray[_backupedCount], _curTotFile); - - curBackupPos = _curBackupPos; - _backupedCount++; - _curBackupPos = _backupedCount; - - _totTextData = 0; - _totFileData = 0; - _totResourceTable = 0; + _environments->set(_numEnvironments); + + curBackupPos = _curEnvironment; + _numEnvironments++; + _curEnvironment = _numEnvironments; + + _script = new Script(_vm); + _resources = new Resources(_vm); if (flags & 1) _vm->_inter->_variables = 0; @@ -563,8 +426,10 @@ void Game::totSub(int8 flags, const char *newTotFile) { // else strcat(_curTotFile, ".TOT"); - if (_vm->_inter->_terminate != 0) + if (_vm->_inter->_terminate != 0) { + clearUnusedEnvironment(); return; + } pushCollisions(0); @@ -582,197 +447,64 @@ void Game::totSub(int8 flags, const char *newTotFile) { _vm->_inter->delocateVars(); } - _backupedCount--; - _curBackupPos = curBackupPos; - - _vm->_draw->_cursorHotspotXVar = _cursorHotspotXArray[_backupedCount]; - _vm->_draw->_cursorHotspotYVar = _cursorHotspotYArray[_backupedCount]; - _totTextData = _totTextDataArray[_backupedCount]; - _totFileData = _totFileDataArray[_backupedCount]; - _totResourceTable = _totResourceTableArray[_backupedCount]; - _extTable = _extTableArray[_backupedCount]; - _extHandle = _extHandleArray[_backupedCount]; - _imFileData = _imFileDataArray[_backupedCount]; - _vm->_inter->_variables = _variablesArray[_backupedCount]; - strcpy(_curTotFile, _curTotFileArray[_backupedCount]); - strcpy(_curExtFile, _curTotFile); - _curExtFile[strlen(_curExtFile) - 4] = '\0'; - strcat(_curExtFile, ".EXT"); + clearUnusedEnvironment(); + + _numEnvironments--; + _curEnvironment = curBackupPos; + _environments->get(_numEnvironments); } void Game::switchTotSub(int16 index, int16 skipPlay) { int16 backupedCount; int16 curBackupPos; - if ((_backupedCount - index) < 1) + if ((_numEnvironments - index) < 1) + return; + + int16 newPos = _curEnvironment - index - ((index >= 0) ? 1 : 0); + if (newPos >= Environments::kEnvironmentCount) return; - int16 newPos = _curBackupPos - index - ((index >= 0) ? 1 : 0); // WORKAROUND: Some versions don't make the MOVEMENT menu item unselectable // in the dreamland screen, resulting in a crash when it's clicked. if ((_vm->getGameType() == kGameTypeGob2) && (index == -1) && (skipPlay == 7) && - !scumm_stricmp(_curTotFileArray[newPos], "gob06.tot")) + !scumm_stricmp(_environments->getTotFile(newPos), "gob06.tot")) return; - curBackupPos = _curBackupPos; - backupedCount = _backupedCount; - if (_curBackupPos == _backupedCount) { - _cursorHotspotXArray[_backupedCount] = _vm->_draw->_cursorHotspotXVar; - _cursorHotspotYArray[_backupedCount] = _vm->_draw->_cursorHotspotYVar; - _totTextDataArray[_backupedCount] = _totTextData; - _totFileDataArray[_backupedCount] = _totFileData; - _totResourceTableArray[_backupedCount] = _totResourceTable; - _extTableArray[_backupedCount] = _extTable; - _extHandleArray[_backupedCount] = _extHandle; - _imFileDataArray[_backupedCount] = _imFileData; - _variablesArray[_backupedCount] = _vm->_inter->_variables; - strcpy(_curTotFileArray[_backupedCount], _curTotFile); - _backupedCount++; - } - _curBackupPos -= index; - if (index >= 0) - _curBackupPos--; - - _vm->_draw->_cursorHotspotXVar = _cursorHotspotXArray[_curBackupPos]; - _vm->_draw->_cursorHotspotYVar = _cursorHotspotYArray[_curBackupPos]; - _totTextData = _totTextDataArray[_curBackupPos]; - _totFileData = _totFileDataArray[_curBackupPos]; - _totResourceTable = _totResourceTableArray[_curBackupPos]; - _imFileData = _imFileDataArray[_curBackupPos]; - _extTable = _extTableArray[_curBackupPos]; - _extHandle = _extHandleArray[_curBackupPos]; - _vm->_inter->_variables = _variablesArray[_curBackupPos]; - strcpy(_curTotFile, _curTotFileArray[_curBackupPos]); - strcpy(_curExtFile, _curTotFile); - _curExtFile[strlen(_curExtFile) - 4] = '\0'; - strcat(_curExtFile, ".EXT"); - - if (_vm->_inter->_terminate != 0) - return; + curBackupPos = _curEnvironment; + backupedCount = _numEnvironments; + if (_curEnvironment == _numEnvironments) + _environments->set(_numEnvironments++); - _vm->_game->pushCollisions(0); - _vm->_game->playTot(skipPlay); + _curEnvironment -= index; + if (index >= 0) + _curEnvironment--; - if (_vm->_inter->_terminate != 2) - _vm->_inter->_terminate = 0; + clearUnusedEnvironment(); - _vm->_game->popCollisions(); - - _curBackupPos = curBackupPos; - _backupedCount = backupedCount; - _vm->_draw->_cursorHotspotXVar = _cursorHotspotXArray[_curBackupPos]; - _vm->_draw->_cursorHotspotYVar = _cursorHotspotYArray[_curBackupPos]; - _totTextData = _totTextDataArray[_curBackupPos]; - _totFileData = _totFileDataArray[_curBackupPos]; - _totResourceTable = _totResourceTableArray[_curBackupPos]; - _extTable = _extTableArray[_curBackupPos]; - _extHandle = _extHandleArray[_curBackupPos]; - _imFileData = _imFileDataArray[_curBackupPos]; - _vm->_inter->_variables = _variablesArray[_curBackupPos]; - strcpy(_curTotFile, _curTotFileArray[_curBackupPos]); - strcpy(_curExtFile, _curTotFile); - _curExtFile[strlen(_curExtFile) - 4] = '\0'; - strcat(_curExtFile, ".EXT"); -} + _environments->get(_curEnvironment); -int16 Game::openLocTextFile(char *locTextFile, int language) { - int n; - - n = strlen(locTextFile); - if (n < 4) - return -1; - - locTextFile[n - 4] = 0; - switch (language) { - case 0: - strcat(locTextFile, ".dat"); - break; - case 1: - strcat(locTextFile, ".all"); - break; - case 3: - strcat(locTextFile, ".esp"); - break; - case 4: - strcat(locTextFile, ".ita"); - break; - case 5: - strcat(locTextFile, ".usa"); - break; - case 6: - strcat(locTextFile, ".ndl"); - break; - case 7: - strcat(locTextFile, ".kor"); - break; - case 8: - strcat(locTextFile, ".isr"); - break; - default: - strcat(locTextFile, ".ang"); - break; + if (_vm->_inter->_terminate != 0) { + clearUnusedEnvironment(); + return; } - return _vm->_dataIO->openData(locTextFile); -} - -byte *Game::loadLocTexts(int32 *dataSize) { - char locTextFile[20]; - int16 handle; - int i; - - strcpy(locTextFile, _curTotFile); - - handle = openLocTextFile(locTextFile, _vm->_global->_languageWanted); - if (handle >= 0) { - - _foundTotLoc = true; - _vm->_global->_language = _vm->_global->_languageWanted; - - } else if (!_foundTotLoc) { - bool found = false; - - if (_vm->_global->_languageWanted == 2) { - handle = openLocTextFile(locTextFile, 5); - if (handle >= 0) { - _vm->_global->_language = 5; - found = true; - } - } else if (_vm->_global->_languageWanted == 5) { - handle = openLocTextFile(locTextFile, 2); - if (handle >= 0) { - _vm->_global->_language = 2; - found = true; - } - } - if (!found) { - for (i = 0; i < 10; i++) { - handle = openLocTextFile(locTextFile, i); - if (handle >= 0) { - _vm->_global->_language = i; - break; - } - } - } - - } + pushCollisions(0); + playTot(skipPlay); - debugC(1, kDebugFileIO, "Using language %d for %s", - _vm->_global->_language, _curTotFile); + if (_vm->_inter->_terminate != 2) + _vm->_inter->_terminate = 0; - if (handle >= 0) { - _vm->_dataIO->closeData(handle); + popCollisions(); - if (dataSize) - *dataSize = _vm->_dataIO->getDataSize(locTextFile); + clearUnusedEnvironment(); - return _vm->_dataIO->getData(locTextFile); - } - return 0; + _curEnvironment = curBackupPos; + _numEnvironments = backupedCount; + _environments->get(_curEnvironment); } void Game::setCollisions(byte arg_0) { - byte *savedIP; uint16 left; uint16 top; uint16 width; @@ -783,12 +515,12 @@ void Game::setCollisions(byte arg_0) { if (((collArea->id & 0xC000) != 0x8000) || (collArea->funcSub == 0)) continue; - savedIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr = _totFileData + collArea->funcSub; - left = _vm->_parse->parseValExpr(); - top = _vm->_parse->parseValExpr(); - width = _vm->_parse->parseValExpr(); - height = _vm->_parse->parseValExpr(); + _script->call(collArea->funcSub); + + left = _script->readValExpr(); + top = _script->readValExpr(); + width = _script->readValExpr(); + height = _script->readValExpr(); if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) && (left != 0xFFFF)) { left += _vm->_draw->_backDeltaX; @@ -807,16 +539,15 @@ void Game::setCollisions(byte arg_0) { collArea->top = top; collArea->right = left + width - 1; collArea->bottom = top + height - 1; - _vm->_global->_inter_execPtr = savedIP; + + _script->pop(); } } void Game::collSub(uint16 offset) { - byte *savedIP; int16 collStackSize; - savedIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr = _totFileData + offset; + _script->call(offset); _shouldPushColls = 1; collStackSize = _collStackSize; @@ -827,7 +558,9 @@ void Game::collSub(uint16 offset) { popCollisions(); _shouldPushColls = 0; - _vm->_global->_inter_execPtr = savedIP; + + _script->pop(); + setCollisions(); } @@ -852,4 +585,16 @@ void Game::collAreaSub(int16 index, int8 enter) { } } +void Game::clearUnusedEnvironment() { + if (!_environments->has(_script)) { + delete _script; + _script = 0; + } + if (!_environments->has(_resources)) { + delete _resources; + _resources = 0; + } + +} + } // End of namespace Gob diff --git a/engines/gob/game.h b/engines/gob/game.h index 3264288a32..ead4a56492 100644 --- a/engines/gob/game.h +++ b/engines/gob/game.h @@ -26,10 +26,45 @@ #ifndef GOB_GAME_H #define GOB_GAME_H -#include "gob/variables.h" - namespace Gob { +class Script; +class Resources; +class Variables; + +class Environments { +public: + static const uint8 kEnvironmentCount = 5; + + Environments(GobEngine *vm); + ~Environments(); + + void set(uint8 env); + void get(uint8 env) const; + + const char *getTotFile(uint8 env) const; + + bool has(Variables *variables, uint8 startEnv = 0, int16 except = -1) const; + bool has(Script *script , uint8 startEnv = 0, int16 except = -1) const; + bool has(Resources *resources, uint8 startEnv = 0, int16 except = -1) const; + + void clear(); + +private: + struct Environment { + int16 cursorHotspotX; + int16 cursorHotspotY; + char curTotFile[14]; + Variables *variables; + Script *script; + Resources *resources; + }; + + GobEngine *_vm; + + Environment *_environments; +}; + class Game { public: @@ -46,20 +81,7 @@ public: uint16 funcEnter; uint16 funcLeave; uint16 funcSub; - byte *totFileData; - } PACKED_STRUCT; - -#define szGame_TotTextItem (2 + 2) - struct TotTextItem { - int16 offset; - int16 size; - } PACKED_STRUCT; - -#define szGame_TotTextTable (2) - struct TotTextTable { - int16 itemsCount; - TotTextItem *items; - byte *dataPtr; + Script *script; } PACKED_STRUCT; struct InputDesc { @@ -74,18 +96,10 @@ public: Collision *_collisionAreas; Collision *_collStack[5]; - bool _foundTotLoc; - TotTextTable *_totTextData; + Script *_script; + Resources *_resources; char _curTotFile[14]; - char _curExtFile[14]; - - byte *_imFileData; - byte *_totFileData; - - int16 _extHandle; - int16 _lomHandle; - char _totToLoad[20]; int32 _startTimeKey; @@ -100,9 +114,6 @@ public: Game(GobEngine *vm); virtual ~Game(); - byte *loadExtData(int16 dataId, int16 *pResWidth, int16 *pResHeight, uint32 *dataSize = 0); - byte *loadTotResource(int16 id, int16 *dataSize = 0, int16 *width = 0, int16 *height = 0); - void capturePush(int16 left, int16 top, int16 width, int16 height); void capturePop(char doDraw); @@ -142,42 +153,6 @@ public: virtual void popCollisions(void) = 0; protected: -#include "common/pack-start.h" // START STRUCT PACKING - -#define szGame_TotResItem (4 + 2 + 2 + 2) - struct TotResItem { - int32 offset; // if > 0, then offset from end of resource table. - // If < 0, then -offset-1 is index in .IM file table - int16 size; - int16 width; - int16 height; - } PACKED_STRUCT; - -#define szGame_TotResTable (2 + 1) - struct TotResTable { - int16 itemsCount; - byte unknown; - TotResItem *items; - byte *dataPtr; - } PACKED_STRUCT; - -#define szGame_ExtItem (4 + 2 + 2 + 2) - struct ExtItem { - int32 offset; // offset from the table end - uint16 size; - int16 width; // width & 0x7FFF: width, width & 0x8000: pack flag - int16 height; // not zero - } PACKED_STRUCT; - -#define szGame_ExtTable (2 + 1) - struct ExtTable { - int16 itemsCount; - byte unknown; - ExtItem *items; - } PACKED_STRUCT; - -#include "common/pack-end.h" // END STRUCT PACKING - int16 _lastCollKey; int16 _lastCollAreaIndex; int16 _lastCollId; @@ -190,10 +165,6 @@ protected: char _tempStr[256]; - TotResTable *_totResourceTable; - ExtTable *_extTable; - char _curImaFile[18]; - int16 _collStackSize; int16 _collStackElemSizes[5]; @@ -206,35 +177,22 @@ protected: char _collStr[256]; // For totSub() - int8 _backupedCount; - int8 _curBackupPos; - int16 _cursorHotspotXArray[5]; - int16 _cursorHotspotYArray[5]; - TotTextTable *_totTextDataArray[5]; - byte *_totFileDataArray[5]; - TotResTable *_totResourceTableArray[5]; - ExtTable *_extTableArray[5]; - int16 _extHandleArray[5]; - byte *_imFileDataArray[5]; - Variables *_variablesArray[5]; - char _curTotFileArray[5][14]; + int8 _curEnvironment; + int8 _numEnvironments; + Environments *_environments; GobEngine *_vm; virtual int16 adjustKey(int16 key); - byte *loadLocTexts(int32 *dataSize = 0); - int32 loadTotFile(const char *path); - void loadExtTable(void); - void loadImFile(void); - void collAreaSub(int16 index, int8 enter); - int16 openLocTextFile(char *locTextFile, int language); virtual void setCollisions(byte arg_0 = 1); virtual void collSub(uint16 offset); virtual int16 checkMousePoint(int16 all, int16 *resId, int16 *resIndex) = 0; + + void clearUnusedEnvironment(); }; class Game_v1 : public Game { diff --git a/engines/gob/game_fascin.cpp b/engines/gob/game_fascin.cpp index 8e77141ce6..38ad03f0f8 100644 --- a/engines/gob/game_fascin.cpp +++ b/engines/gob/game_fascin.cpp @@ -35,7 +35,6 @@ #include "gob/goblin.h" #include "gob/inter.h" #include "gob/mult.h" -#include "gob/parse.h" #include "gob/scenery.h" #include "gob/video.h" #include "gob/videoplayer.h" diff --git a/engines/gob/game_v1.cpp b/engines/gob/game_v1.cpp index ad24d7d9c6..87dc78e3b1 100644 --- a/engines/gob/game_v1.cpp +++ b/engines/gob/game_v1.cpp @@ -32,11 +32,12 @@ #include "gob/global.h" #include "gob/util.h" #include "gob/dataio.h" +#include "gob/script.h" +#include "gob/resources.h" #include "gob/draw.h" #include "gob/inter.h" #include "gob/mult.h" #include "gob/video.h" -#include "gob/parse.h" #include "gob/scenery.h" #include "gob/sound/sound.h" @@ -49,12 +50,12 @@ void Game_v1::playTot(int16 skipPlay) { int16 _captureCounter; int16 breakFrom; int16 nestLevel; - int32 variablesCount; int16 *oldNestLevel = _vm->_inter->_nestLevel; int16 *oldBreakFrom = _vm->_inter->_breakFromLevel; int16 *oldCaptureCounter = _vm->_scenery->_pCaptureCounter; - byte *savedIP = _vm->_global->_inter_execPtr; + + _script->push(); _vm->_inter->_nestLevel = &nestLevel; _vm->_inter->_breakFromLevel = &breakFrom; @@ -93,86 +94,23 @@ void Game_v1::playTot(int16 skipPlay) { for (int i = 0; i < 20; i++) freeSoundSlot(i); - _totTextData = 0; - _totResourceTable = 0; - _imFileData = 0; - _extTable = 0; - _extHandle = -1; - _totToLoad[0] = 0; - if ((_curTotFile[0] == 0) && (_totFileData == 0)) + if ((_curTotFile[0] == 0) && !_script->isLoaded()) break; - loadTotFile(_curTotFile); - if (_totFileData == 0) { + if (!_script->load(_curTotFile)) { _vm->_draw->blitCursor(); break; } - strcpy(_curImaFile, _curTotFile); - strcpy(_curExtFile, _curTotFile); - - _curImaFile[strlen(_curImaFile) - 4] = 0; - strcat(_curImaFile, ".ima"); - - _curExtFile[strlen(_curExtFile) - 4] = 0; - strcat(_curExtFile, ".ext"); - - debugC(4, kDebugFileIO, "IMA: %s", _curImaFile); - debugC(4, kDebugFileIO, "EXT: %s", _curExtFile); - - byte *filePtr = _totFileData + 0x30; - - _totTextData = 0; - if (READ_LE_UINT32(filePtr) != (uint32) -1) { - _totTextData = new TotTextTable; - _totTextData->dataPtr = - (_totFileData + READ_LE_UINT32(_totFileData + 0x30)); - Common::MemoryReadStream totTextData(_totTextData->dataPtr, - 4294967295U); - - _totTextData->itemsCount = totTextData.readSint16LE(); - - _totTextData->items = new TotTextItem[_totTextData->itemsCount]; - for (int i = 0; i < _totTextData->itemsCount; ++i) { - _totTextData->items[i].offset = totTextData.readSint16LE(); - _totTextData->items[i].size = totTextData.readSint16LE(); - } - } - - filePtr = _totFileData + 0x34; - _totResourceTable = 0; - if (READ_LE_UINT32(filePtr) != (uint32) -1) { - _totResourceTable = new TotResTable; - _totResourceTable->dataPtr = - _totFileData + READ_LE_UINT32( _totFileData + 0x34); - Common::MemoryReadStream totResTable(_totResourceTable->dataPtr, - 4294967295U); - - _totResourceTable->itemsCount = totResTable.readSint16LE(); - _totResourceTable->unknown = totResTable.readByte(); - - _totResourceTable->items = - new TotResItem[_totResourceTable->itemsCount]; - for (int i = 0; i < _totResourceTable->itemsCount; ++i) { - _totResourceTable->items[i].offset = totResTable.readSint32LE(); - _totResourceTable->items[i].size = totResTable.readSint16LE(); - _totResourceTable->items[i].width = totResTable.readSint16LE(); - _totResourceTable->items[i].height = totResTable.readSint16LE(); - } - } - - loadImFile(); - loadExtTable(); + _resources->load(_curTotFile); - _vm->_global->_inter_animDataSize = - READ_LE_UINT16(_totFileData + 0x38); + _vm->_global->_inter_animDataSize = _script->getAnimDataSize(); if (!_vm->_inter->_variables) - _vm->_inter->allocateVars(READ_LE_UINT16(_totFileData + 0x2C)); + _vm->_inter->allocateVars(_script->getVariablesCount() & 0xFFFF); - _vm->_global->_inter_execPtr = _totFileData; - _vm->_global->_inter_execPtr += READ_LE_UINT32(_totFileData + 0x64); + _script->seek(_script->getFunctionOffset(TOTFile::kFunctionStart)); _vm->_inter->renewTimeInVars(); @@ -182,39 +120,16 @@ void Game_v1::playTot(int16 skipPlay) { WRITE_VAR(16, _vm->_global->_language); _vm->_inter->callSub(2); + _script->setFinished(false); if (_totToLoad[0] != 0) _vm->_inter->_terminate = 0; - variablesCount = READ_LE_UINT32(_totFileData + 0x2C); _vm->_draw->blitInvalidated(); - delete[] _totFileData; - _totFileData = 0; - - if (_totTextData) { - delete[] _totTextData->items; - delete _totTextData; - } - _totTextData = 0; - - if (_totResourceTable) { - delete[] _totResourceTable->items; - delete _totResourceTable; - } - _totResourceTable = 0; - - delete[] _imFileData; - _imFileData = 0; - if (_extTable) - delete[] _extTable->items; - delete _extTable; - _extTable = 0; + _script->unload(); - if (_extHandle >= 0) - _vm->_dataIO->closeData(_extHandle); - - _extHandle = -1; + _resources->unload(); for (int i = 0; i < *_vm->_scenery->_pCaptureCounter; i++) capturePop(0); @@ -241,7 +156,8 @@ void Game_v1::playTot(int16 skipPlay) { _vm->_inter->_nestLevel = oldNestLevel; _vm->_inter->_breakFromLevel = oldBreakFrom; _vm->_scenery->_pCaptureCounter = oldCaptureCounter; - _vm->_global->_inter_execPtr = savedIP; + + _script->pop(); } void Game_v1::clearCollisions() { @@ -279,7 +195,7 @@ int16 Game_v1::addNewCollision(int16 id, uint16 left, uint16 top, ptr->funcEnter = funcEnter; ptr->funcLeave = funcLeave; ptr->funcSub = funcSub; - ptr->totFileData = 0; + ptr->script = 0; return i; } @@ -331,7 +247,6 @@ void Game_v1::popCollisions(void) { int16 Game_v1::checkCollisions(byte handleMouse, int16 deltaTime, int16 *pResId, int16 *pResIndex) { - byte *savedIP; int16 resIndex; int16 key; int16 oldIndex; @@ -357,12 +272,9 @@ int16 Game_v1::checkCollisions(byte handleMouse, int16 deltaTime, _lastCollKey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); if ((_lastCollKey != 0) && ((_lastCollId & 0x8000) != 0)) { - savedIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr = _totFileData + - _collisionAreas[_lastCollAreaIndex].funcEnter; - + _script->call(_collisionAreas[_lastCollAreaIndex].funcEnter); _vm->_inter->funcBlock(0); - _vm->_global->_inter_execPtr = savedIP; + _script->pop(); } } @@ -423,12 +335,10 @@ int16 Game_v1::checkCollisions(byte handleMouse, int16 deltaTime, if ((_lastCollKey != 0) && (_collisionAreas[_lastCollAreaIndex].funcLeave != 0)) { - savedIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr = _totFileData + - _collisionAreas[_lastCollAreaIndex].funcLeave; + _script->call(_collisionAreas[_lastCollAreaIndex].funcLeave); _vm->_inter->funcBlock(0); - _vm->_global->_inter_execPtr = savedIP; + _script->pop(); } _lastCollKey = 0; @@ -463,12 +373,11 @@ int16 Game_v1::checkCollisions(byte handleMouse, int16 deltaTime, if ((_lastCollKey != 0) && (_collisionAreas[_lastCollAreaIndex].funcLeave != 0)) { - savedIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr = _totFileData + - _collisionAreas[_lastCollAreaIndex].funcLeave; + _script->call(_collisionAreas[_lastCollAreaIndex].funcLeave); _vm->_inter->funcBlock(0); - _vm->_global->_inter_execPtr = savedIP; + _script->pop(); + } _lastCollKey = 0; return key; @@ -476,24 +385,22 @@ int16 Game_v1::checkCollisions(byte handleMouse, int16 deltaTime, if ((_lastCollKey != 0) && (_collisionAreas[_lastCollAreaIndex].funcLeave != 0)) { - savedIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr = _totFileData + - _collisionAreas[_lastCollAreaIndex].funcLeave; + _script->call(_collisionAreas[_lastCollAreaIndex].funcLeave); _vm->_inter->funcBlock(0); - _vm->_global->_inter_execPtr = savedIP; + _script->pop(); + } _lastCollKey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); if ((_lastCollKey != 0) && ((_lastCollId & 0x8000) != 0)) { - savedIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr = _totFileData + - _collisionAreas[_lastCollAreaIndex].funcEnter; + _script->call(_collisionAreas[_lastCollAreaIndex].funcEnter); _vm->_inter->funcBlock(0); - _vm->_global->_inter_execPtr = savedIP; + _script->pop(); + } } else { @@ -507,23 +414,22 @@ int16 Game_v1::checkCollisions(byte handleMouse, int16 deltaTime, if (key != _lastCollKey) { if ((_lastCollKey != 0) && ((oldId & 0x8000) != 0)) { - savedIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr = _totFileData + - _collisionAreas[oldIndex].funcLeave; + _script->call(_collisionAreas[oldIndex].funcLeave); _vm->_inter->funcBlock(0); - _vm->_global->_inter_execPtr = savedIP; + _script->pop(); + } _lastCollKey = key; if ((_lastCollKey != 0) && ((_lastCollId & 0x8000) != 0)) { - savedIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr = _totFileData + - _collisionAreas[_lastCollAreaIndex].funcEnter; + _script->call(_collisionAreas[_lastCollAreaIndex].funcEnter); _vm->_inter->funcBlock(0); - _vm->_global->_inter_execPtr = savedIP; + _script->pop(); + } + } } } @@ -588,7 +494,6 @@ void Game_v1::collisionsBlock(void) { int16 array[250]; byte count; int16 collResId; - byte *startIP; int16 curCmd; int16 cmd; int16 cmdHigh; @@ -615,27 +520,27 @@ void Game_v1::collisionsBlock(void) { int16 collStackPos; Collision *collPtr; uint32 timeKey; - byte *savedIP; if (_shouldPushColls) pushCollisions(1); collResId = -1; - _vm->_global->_inter_execPtr++; - count = *_vm->_global->_inter_execPtr++; - _handleMouse = _vm->_global->_inter_execPtr[0]; - deltaTime = 1000 * _vm->_global->_inter_execPtr[1]; - descIndex2 = _vm->_global->_inter_execPtr[2]; - stackPos2 = _vm->_global->_inter_execPtr[3]; - descIndex = _vm->_global->_inter_execPtr[4]; + _script->skip(1); + count = _script->readByte(); + _handleMouse = _script->readByte(); + deltaTime = 1000 * _script->readByte(); + descIndex2 = _script->readByte(); + stackPos2 = _script->readByte(); + descIndex = _script->readByte(); if ((stackPos2 != 0) || (descIndex != 0)) deltaTime /= 100; timeVal = deltaTime; - _vm->_global->_inter_execPtr += 6; + _script->skip(1); + + uint32 startPos = _script->pos(); - startIP = _vm->_global->_inter_execPtr; WRITE_VAR(16, 0); var_22 = 0; index = 0; @@ -643,26 +548,25 @@ void Game_v1::collisionsBlock(void) { for (curCmd = 0; curCmd < count; curCmd++) { array[curCmd] = 0; - cmd = *_vm->_global->_inter_execPtr++; + cmd = _script->readByte(); if ((cmd & 0x40) != 0) { cmd -= 0x40; - cmdHigh = *_vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr++; + cmdHigh = _script->readByte(); cmdHigh <<= 8; } else cmdHigh = 0; if ((cmd & 0x80) != 0) { - left = _vm->_parse->parseValExpr(); - top = _vm->_parse->parseValExpr(); - width = _vm->_parse->parseValExpr(); - height = _vm->_parse->parseValExpr(); + left = _script->readValExpr(); + top = _script->readValExpr(); + width = _script->readValExpr(); + height = _script->readValExpr(); } else { - left = _vm->_inter->load16(); - top = _vm->_inter->load16(); - width = _vm->_inter->load16(); - height = _vm->_inter->load16(); + left = _script->readUint16(); + top = _script->readUint16(); + width = _script->readUint16(); + height = _script->readUint16(); } cmd &= 0x7F; @@ -680,16 +584,16 @@ void Game_v1::collisionsBlock(void) { _vm->_util->clearKeyBuf(); var_22 = 1; - key = _vm->_parse->parseVarIndex(); - descArray[index].fontIndex = _vm->_inter->load16(); - descArray[index].backColor = *_vm->_global->_inter_execPtr++; - descArray[index].frontColor = *_vm->_global->_inter_execPtr++; + key = _script->readVarIndex(); + descArray[index].fontIndex = _script->readInt16(); + descArray[index].backColor = _script->readByte(); + descArray[index].frontColor = _script->readByte(); if ((cmd < 5) || (cmd > 8)) { descArray[index].ptr = 0; } else { - descArray[index].ptr = _vm->_global->_inter_execPtr + 2; - _vm->_global->_inter_execPtr += _vm->_inter->load16(); + descArray[index].ptr = _script->getData() + _script->pos() + 2; + _script->skip(_script->readInt16()); } if (left == 0xFFFF) @@ -698,12 +602,9 @@ void Game_v1::collisionsBlock(void) { if ((cmd & 1) == 0) { addNewCollision(curCmd + 0x8000, left, top, left + width * _vm->_draw->_fonts[descArray[index].fontIndex]->itemWidth - 1, - top + height - 1, cmd, key, 0, - _vm->_global->_inter_execPtr - _totFileData); + top + height - 1, cmd, key, 0, _script->pos()); - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); } else { addNewCollision(curCmd + 0x8000, left, top, left + width * _vm->_draw->_fonts[descArray[index].fontIndex]->itemWidth - 1, @@ -713,18 +614,15 @@ void Game_v1::collisionsBlock(void) { break; case 21: - key = _vm->_inter->load16(); - array[curCmd] = _vm->_inter->load16(); - flags = _vm->_inter->load16() & 3; + key = _script->readInt16(); + array[curCmd] = _script->readInt16(); + flags = _script->readInt16() & 3; addNewCollision(curCmd + 0x8000, left, top, left + width - 1, top + height - 1, - (flags << 4) + cmdHigh + 2, key, - _vm->_global->_inter_execPtr - _totFileData, 0); + (flags << 4) + cmdHigh + 2, key, _script->pos(), 0); - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); break; case 20: @@ -732,61 +630,48 @@ void Game_v1::collisionsBlock(void) { // Fall through to case 2 case 2: - key = _vm->_inter->load16(); - array[curCmd] = _vm->_inter->load16(); - flags = _vm->_inter->load16() & 3; + key = _script->readInt16(); + array[curCmd] = _script->readInt16(); + flags = _script->readInt16() & 3; addNewCollision(curCmd + 0x8000, left, top, left + width - 1, top + height - 1, - (flags << 4) + cmdHigh + 2, key, 0, - _vm->_global->_inter_execPtr - _totFileData); + (flags << 4) + cmdHigh + 2, key, 0, _script->pos()); - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); break; case 0: - _vm->_global->_inter_execPtr += 6; - startIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(6); + startPos = _script->pos(); + _script->skip(_script->peekUint16(2) + 2); key = curCmd + 0xA000; addNewCollision(curCmd + 0x8000, left, top, left + width - 1, top + height - 1, cmd + cmdHigh, key, - startIP - _totFileData, - _vm->_global->_inter_execPtr - _totFileData); + startPos, _script->pos()); - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); break; case 1: - key = _vm->_inter->load16(); - array[curCmd] = _vm->_inter->load16(); - flags = _vm->_inter->load16() & 3; - - startIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + key = _script->readInt16(); + array[curCmd] = _script->readInt16(); + flags = _script->readInt16() & 3; + + startPos = _script->pos(); + _script->skip(_script->peekUint16(2) + 2); if (key == 0) key = curCmd + 0xA000; addNewCollision(curCmd + 0x8000, left, top, left + width - 1, top + height - 1, (flags << 4) + cmd + cmdHigh, key, - startIP - _totFileData, - _vm->_global->_inter_execPtr - _totFileData); + startPos, _script->pos()); - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); break; } } @@ -895,9 +780,11 @@ void Game_v1::collisionsBlock(void) { if (collPtr->funcLeave != 0) { timeKey = _vm->_util->getTimeKey(); - savedIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr = - _totFileData + collPtr->funcLeave; + + uint32 savedPos = _script->pos(); + + _script->seek(collPtr->funcLeave); + _shouldPushColls = 1; savedCollStackSize = _collStackSize; _vm->_inter->funcBlock(0); @@ -906,7 +793,8 @@ void Game_v1::collisionsBlock(void) { popCollisions(); _shouldPushColls = 0; - _vm->_global->_inter_execPtr = savedIP; + + _script->seek(savedPos); deltaTime = timeVal - (_vm->_util->getTimeKey() - timeKey); @@ -986,9 +874,9 @@ void Game_v1::collisionsBlock(void) { WRITE_VAR(16, array[(uint16) _activeCollResId & ~0x8000]); if (_collisionAreas[_activeCollIndex].funcEnter != 0) { - savedIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr = _totFileData + - _collisionAreas[_activeCollIndex].funcEnter; + uint32 savedPos = _script->pos(); + + _script->seek(_collisionAreas[_activeCollIndex].funcEnter); _shouldPushColls = 1; @@ -997,7 +885,8 @@ void Game_v1::collisionsBlock(void) { if (collStackPos != _collStackSize) popCollisions(); _shouldPushColls = 0; - _vm->_global->_inter_execPtr = savedIP; + + _script->seek(savedPos); } WRITE_VAR(16, 0); @@ -1071,10 +960,8 @@ void Game_v1::collisionsBlock(void) { WRITE_VAR(17, 1); } - savedIP = 0; if (!_vm->_inter->_terminate) { - savedIP = _totFileData + - _collisionAreas[_activeCollIndex].funcLeave; + _script->seek(_collisionAreas[_activeCollIndex].funcLeave); WRITE_VAR(2, _vm->_global->_inter_mouseX); WRITE_VAR(3, _vm->_global->_inter_mouseY); @@ -1082,12 +969,11 @@ void Game_v1::collisionsBlock(void) { if (VAR(16) == 0) WRITE_VAR(16, array[(uint16) _activeCollResId & ~0x8000]); - } + } else + _script->setFinished(true); for (curCmd = 0; curCmd < count; curCmd++) freeCollision(curCmd + 0x8000); - - _vm->_global->_inter_execPtr = savedIP; } int16 Game_v1::multiEdit(int16 time, int16 index, int16 *pCurPos, diff --git a/engines/gob/game_v2.cpp b/engines/gob/game_v2.cpp index e9656efa32..08184e73d0 100644 --- a/engines/gob/game_v2.cpp +++ b/engines/gob/game_v2.cpp @@ -32,11 +32,12 @@ #include "gob/global.h" #include "gob/util.h" #include "gob/dataio.h" +#include "gob/script.h" +#include "gob/resources.h" #include "gob/draw.h" #include "gob/goblin.h" #include "gob/inter.h" #include "gob/mult.h" -#include "gob/parse.h" #include "gob/scenery.h" #include "gob/video.h" #include "gob/videoplayer.h" @@ -55,15 +56,12 @@ void Game_v2::playTot(int16 skipPlay) { int16 _captureCounter; int16 breakFrom; int16 nestLevel; - int32 totSize; - byte *filePtr; - byte *savedIP; - bool totTextLoc; oldNestLevel = _vm->_inter->_nestLevel; oldBreakFrom = _vm->_inter->_breakFromLevel; oldCaptureCounter = _vm->_scenery->_pCaptureCounter; - savedIP = _vm->_global->_inter_execPtr; + + _script->push(); _vm->_inter->_nestLevel = &nestLevel; _vm->_inter->_breakFromLevel = &breakFrom; @@ -94,125 +92,30 @@ void Game_v2::playTot(int16 skipPlay) { } else _vm->_inter->initControlVars(0); - _totTextData = 0; - _totResourceTable = 0; - _imFileData = 0; - _extTable = 0; - _extHandle = -1; - _vm->_draw->_cursorHotspotXVar = -1; _totToLoad[0] = 0; - if ((_curTotFile[0] == 0) && (_totFileData == 0)) + if ((_curTotFile[0] == 0) && (!_script->isLoaded())) break; - totSize = loadTotFile(_curTotFile); - if (skipPlay == -2) { _vm->_vidPlayer->primaryClose(); skipPlay = 0; } - if (_totFileData == 0) { + if (!_script->load(_curTotFile)) { _vm->_draw->blitCursor(); _vm->_inter->_terminate = 2; break; } - strcpy(_curImaFile, _curTotFile); - strcpy(_curExtFile, _curTotFile); - - _curImaFile[strlen(_curImaFile) - 4] = 0; - strcat(_curImaFile, ".ima"); - - _curExtFile[strlen(_curExtFile) - 4] = 0; - strcat(_curExtFile, ".ext"); - - debugC(4, kDebugFileIO, "IMA: %s", _curImaFile); - debugC(4, kDebugFileIO, "EXT: %s", _curExtFile); - - filePtr = _totFileData + 0x30; - - _totTextData = 0; - totTextLoc = false; - if (READ_LE_UINT32(filePtr) != (uint32) -1) { - _totTextData = new TotTextTable; - - int32 size; - - if (READ_LE_UINT32(filePtr) == 0) { - _totTextData->dataPtr = loadLocTexts(&size); - totTextLoc = true; - } else { - _totTextData->dataPtr = - (_totFileData + READ_LE_UINT32(_totFileData + 0x30)); - size = totSize; - _vm->_global->_language = _vm->_global->_languageWanted; - } - - _totTextData->items = 0; - if (_totTextData->dataPtr != 0) { - Common::MemoryReadStream totTextData(_totTextData->dataPtr, - 4294967295U); - _totTextData->itemsCount = totTextData.readSint16LE() & 0x3FFF; - - _totTextData->items = new TotTextItem[_totTextData->itemsCount]; - for (int i = 0; i < _totTextData->itemsCount; ++i) { - _totTextData->items[i].offset = totTextData.readSint16LE(); - _totTextData->items[i].size = totTextData.readSint16LE(); - } - } - } - - filePtr = _totFileData + 0x34; - _totResourceTable = 0; - int32 resSize; - if (READ_LE_UINT32(filePtr) != (uint32) -1) { - _totResourceTable = new TotResTable; - _totResourceTable->dataPtr = - _totFileData + READ_LE_UINT32(_totFileData + 0x34); - Common::MemoryReadStream totResTable(_totResourceTable->dataPtr, - 4294967295U); - - _totResourceTable->itemsCount = totResTable.readSint16LE(); - resSize = _totResourceTable->itemsCount * szGame_TotResItem + szGame_TotResTable; - if (totSize > (resSize + 0x34)) { - _totResourceTable->unknown = totResTable.readByte(); - - _totResourceTable->items = - new TotResItem[_totResourceTable->itemsCount]; - for (int i = 0; i < _totResourceTable->itemsCount; ++i) { - _totResourceTable->items[i].offset = totResTable.readSint32LE(); - _totResourceTable->items[i].size = totResTable.readSint16LE(); - _totResourceTable->items[i].width = totResTable.readSint16LE(); - _totResourceTable->items[i].height = totResTable.readSint16LE(); - } - } - else { - // WORKAROUND: In the original asm, _totResourceTable is - // only assigned in playTot and evaluated later, right - // before using it. In the Gobliins 2 demo, there is a - // dummy tot that loads another tot, overwriting the dummy - // pointer with the real one. - debugC(1, kDebugFileIO, - "Attempted to load invalid resource table (size = %d, totSize = %d)", - resSize, totSize); - delete _totResourceTable; - _totResourceTable = 0; - } - } - - loadImFile(); - loadExtTable(); + _resources->load(_curTotFile); - _vm->_global->_inter_animDataSize = - READ_LE_UINT16(_totFileData + 0x38); + _vm->_global->_inter_animDataSize = _script->getAnimDataSize(); if (!_vm->_inter->_variables) - _vm->_inter->allocateVars(READ_LE_UINT16(_totFileData + 0x2C)); + _vm->_inter->allocateVars(_script->getVariablesCount() & 0xFFFF); - _vm->_global->_inter_execPtr = _totFileData; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_totFileData + 0x64); + _script->seek(_script->getFunctionOffset(TOTFile::kFunctionStart)); _vm->_inter->renewTimeInVars(); @@ -227,35 +130,10 @@ void Game_v2::playTot(int16 skipPlay) { _vm->_inter->_terminate = 0; _vm->_draw->blitInvalidated(); - delete[] _totFileData; - _totFileData = 0; - - if (_totTextData) { - delete[] _totTextData->items; - if (totTextLoc) - delete[] _totTextData->dataPtr; - delete _totTextData; - } - _totTextData = 0; - if (_totResourceTable) { - delete[] _totResourceTable->items; - delete _totResourceTable; - } - _totResourceTable = 0; - - delete[] _imFileData; - _imFileData = 0; - - if (_extTable) - delete[] _extTable->items; - delete _extTable; - _extTable = 0; - - if (_extHandle >= 0) - _vm->_dataIO->closeData(_extHandle); + _script->unload(); - _extHandle = -1; + _resources->unload(); for (int i = 0; i < *_vm->_scenery->_pCaptureCounter; i++) capturePop(0); @@ -282,9 +160,7 @@ void Game_v2::playTot(int16 skipPlay) { } else { _vm->_inter->initControlVars(0); _vm->_scenery->_pCaptureCounter = oldCaptureCounter; - _vm->_global->_inter_execPtr = _totFileData; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_totFileData + (skipPlay << 1) + 0x66); + _script->seek(_script->getFunctionOffset(skipPlay + 1)); _menuLevel++; _vm->_inter->callSub(2); @@ -299,7 +175,8 @@ void Game_v2::playTot(int16 skipPlay) { _vm->_inter->_nestLevel = oldNestLevel; _vm->_inter->_breakFromLevel = oldBreakFrom; _vm->_scenery->_pCaptureCounter = oldCaptureCounter; - _vm->_global->_inter_execPtr = savedIP; + + _script->pop(); } void Game_v2::clearCollisions() { @@ -337,7 +214,7 @@ int16 Game_v2::addNewCollision(int16 id, uint16 left, uint16 top, ptr->funcEnter = funcEnter; ptr->funcLeave = funcLeave; ptr->funcSub = funcSub; - ptr->totFileData = 0; + ptr->script = 0; return i; } @@ -604,7 +481,6 @@ void Game_v2::collisionsBlock(void) { int16 array[250]; byte count; int16 collResId; - byte *startIP; int16 curCmd; int16 cmd; int16 cmdHigh; @@ -621,7 +497,6 @@ void Game_v2::collisionsBlock(void) { int16 stackPos2; int16 descIndex; int16 timeVal; - int16 offsetIP; char *str; int16 i; int16 counter; @@ -631,8 +506,9 @@ void Game_v2::collisionsBlock(void) { Collision *collPtr; Collision *collArea; int16 timeKey; - byte *savedIP; byte collAreaStart; + uint32 startPos; + uint32 offsetPos; if (_shouldPushColls) pushCollisions(0); @@ -645,21 +521,22 @@ void Game_v2::collisionsBlock(void) { _shouldPushColls = 0; collResId = -1; - _vm->_global->_inter_execPtr++; - count = *_vm->_global->_inter_execPtr++; + _script->skip(1); + count = _script->readByte(); - _handleMouse = _vm->_global->_inter_execPtr[0]; - deltaTime = 1000 * _vm->_global->_inter_execPtr[1]; - stackPos2 = _vm->_global->_inter_execPtr[3]; - descIndex = _vm->_global->_inter_execPtr[4]; + _handleMouse = _script->readByte(); + deltaTime = 1000 * _script->readByte(); + _script->skip(1); + stackPos2 = _script->readByte(); + descIndex = _script->readByte(); if ((stackPos2 != 0) || (descIndex != 0)) deltaTime /= 100; timeVal = deltaTime; - _vm->_global->_inter_execPtr += 6; + _script->skip(1); - startIP = _vm->_global->_inter_execPtr; + startPos = _script->pos(); WRITE_VAR(16, 0); var_1C = 0; @@ -668,28 +545,27 @@ void Game_v2::collisionsBlock(void) { for (curCmd = 0; curCmd < count; curCmd++) { array[curCmd] = 0; - cmd = *_vm->_global->_inter_execPtr++; + cmd = _script->readByte(); if ((cmd & 0x40) != 0) { cmd -= 0x40; - cmdHigh = *_vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr++; + cmdHigh = _script->readByte(); cmdHigh <<= 8; } else cmdHigh = 0; if ((cmd & 0x80) != 0) { - offsetIP = _vm->_global->_inter_execPtr - _totFileData; - left = _vm->_parse->parseValExpr(); - top = _vm->_parse->parseValExpr(); - width = _vm->_parse->parseValExpr(); - height = _vm->_parse->parseValExpr(); + offsetPos = _script->pos(); + left = _script->readValExpr(); + top = _script->readValExpr(); + width = _script->readValExpr(); + height = _script->readValExpr(); } else { - offsetIP = 0; - left = _vm->_inter->load16(); - top = _vm->_inter->load16(); - width = _vm->_inter->load16(); - height = _vm->_inter->load16(); + offsetPos = 0; + left = _script->readUint16(); + top = _script->readUint16(); + width = _script->readUint16(); + height = _script->readUint16(); } if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) && (left != 0xFFFF)) { @@ -712,46 +588,37 @@ void Game_v2::collisionsBlock(void) { switch (cmd) { case 0: - _vm->_global->_inter_execPtr += 6; - startIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(6); + startPos = _script->pos(); + _script->skip(_script->peekUint16(2) + 2); key = curCmd + 0xA000; addNewCollision(curCmd + 0x8000, left, top, left + width - 1, top + height - 1, - cmd + cmdHigh, key, startIP - _totFileData, - _vm->_global->_inter_execPtr - _totFileData, offsetIP); + cmd + cmdHigh, key, startPos, + _script->pos(), offsetPos); - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); break; case 1: - key = _vm->_inter->load16(); - array[curCmd] = _vm->_inter->load16(); - flags = _vm->_inter->load16(); + key = _script->readInt16(); + array[curCmd] = _script->readInt16(); + flags = _script->readInt16(); - startIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + startPos = _script->pos(); + _script->skip(_script->peekUint16(2) + 2); if (key == 0) key = curCmd + 0xA000; addNewCollision(curCmd + 0x8000, left, top, left + width - 1, top + height - 1, - (flags << 4) + cmd + cmdHigh, key, startIP - _totFileData, - _vm->_global->_inter_execPtr - _totFileData, offsetIP); - - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + (flags << 4) + cmd + cmdHigh, key, startPos, + _script->pos(), offsetPos); + _script->skip(_script->peekUint16(2) + 2); break; case 3: @@ -764,23 +631,20 @@ void Game_v2::collisionsBlock(void) { case 10: _vm->_util->clearKeyBuf(); var_1C = 1; - key = _vm->_parse->parseVarIndex(); - descArray[index].fontIndex = _vm->_inter->load16(); - descArray[index].backColor = *_vm->_global->_inter_execPtr++; - descArray[index].frontColor = *_vm->_global->_inter_execPtr++; + key = _script->readVarIndex(); + descArray[index].fontIndex = _script->readInt16(); + descArray[index].backColor = _script->readByte(); + descArray[index].frontColor = _script->readByte(); if ((cmd >= 5) && (cmd <= 8)) { - descArray[index].ptr = _vm->_global->_inter_execPtr + 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr) + 2; + descArray[index].ptr = _script->getData() + _script->pos() + 2; + _script->skip(_script->peekUint16() + 2); } else descArray[index].ptr = 0; if (left == 0xFFFF) { if ((cmd & 1) == 0) { - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); } break; } @@ -789,11 +653,9 @@ void Game_v2::collisionsBlock(void) { addNewCollision(curCmd + 0x8000, left, top, left + width * _vm->_draw->_fonts[descArray[index].fontIndex]-> itemWidth - 1, top + height - 1, cmd, key, 0, - _vm->_global->_inter_execPtr - _totFileData); + _script->pos()); - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); } else addNewCollision(curCmd + 0x8000, left, top, left + width * _vm->_draw->_fonts[descArray[index].fontIndex]-> itemWidth - 1, @@ -803,35 +665,31 @@ void Game_v2::collisionsBlock(void) { break; case 11: - _vm->_global->_inter_execPtr += 6; + _script->skip(6); for (i = 0; i < 150; i++) { if ((_collisionAreas[i].id & 0xF000) == 0xE000) { _collisionAreas[i].id &= 0xBFFF; _collisionAreas[i].funcEnter = - _vm->_global->_inter_execPtr - _totFileData; + _script->pos(); _collisionAreas[i].funcLeave = - _vm->_global->_inter_execPtr - _totFileData; + _script->pos(); } } - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); break; case 12: - _vm->_global->_inter_execPtr += 6; + _script->skip(6); for (i = 0; i < 150; i++) { if ((_collisionAreas[i].id & 0xF000) == 0xD000) { _collisionAreas[i].id &= 0xBFFF; _collisionAreas[i].funcEnter = - _vm->_global->_inter_execPtr - _totFileData; + _script->pos(); _collisionAreas[i].funcLeave = - _vm->_global->_inter_execPtr - _totFileData; + _script->pos(); } } - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); break; case 20: @@ -839,34 +697,30 @@ void Game_v2::collisionsBlock(void) { // Fall through to case 2 case 2: - key = _vm->_inter->load16(); - array[curCmd] = _vm->_inter->load16(); - flags = _vm->_inter->load16(); + key = _script->readInt16(); + array[curCmd] = _script->readInt16(); + flags = _script->readInt16(); addNewCollision(curCmd + 0x8000, left, top, left + width - 1, top + height - 1, (flags << 4) + cmdHigh + 2, key, 0, - _vm->_global->_inter_execPtr - _totFileData, offsetIP); + _script->pos(), offsetPos); - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); break; case 21: - key = _vm->_inter->load16(); - array[curCmd] = _vm->_inter->load16(); - flags = _vm->_inter->load16() & 3; + key = _script->readInt16(); + array[curCmd] = _script->readInt16(); + flags = _script->readInt16() & 3; addNewCollision(curCmd + 0x8000, left, top, left + width - 1, top + height - 1, (flags << 4) + cmdHigh + 2, key, - _vm->_global->_inter_execPtr - _totFileData, 0, offsetIP); + _script->pos(), 0, offsetPos); - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); break; } @@ -1116,10 +970,8 @@ void Game_v2::collisionsBlock(void) { if (_handleMouse == 1) _vm->_draw->blitCursor(); - savedIP = 0; if (!_vm->_inter->_terminate) { - savedIP = _totFileData + - _collisionAreas[_activeCollIndex].funcLeave; + _script->seek(_collisionAreas[_activeCollIndex].funcLeave); _vm->_inter->storeMouse(); if (VAR(16) == 0) { @@ -1128,7 +980,8 @@ void Game_v2::collisionsBlock(void) { else WRITE_VAR(16, _activeCollResId & 0xFFF); } - } + } else + _script->setFinished(true); for (curCmd = 0; curCmd < count; curCmd++) freeCollision(curCmd + 0x8000); @@ -1138,8 +991,6 @@ void Game_v2::collisionsBlock(void) { ((_collisionAreas[i].id & 0xF000) == 0x9000)) _collisionAreas[i].id |= 0x4000; } - - _vm->_global->_inter_execPtr = savedIP; } int16 Game_v2::multiEdit(int16 time, int16 index, int16 *pCurPos, diff --git a/engines/gob/game_v6.cpp b/engines/gob/game_v6.cpp index 9d9bd1faa3..8d40d41acc 100644 --- a/engines/gob/game_v6.cpp +++ b/engines/gob/game_v6.cpp @@ -31,9 +31,10 @@ #include "gob/game.h" #include "gob/helper.h" #include "gob/global.h" +#include "gob/script.h" +#include "gob/resources.h" #include "gob/inter.h" #include "gob/draw.h" -#include "gob/parse.h" namespace Gob { @@ -48,27 +49,17 @@ void Game_v6::totSub(int8 flags, const char *newTotFile) { if ((flags == 16) || (flags == 17)) warning("Urban Stub: Game_v6::totSub(), flags == %d", flags); - if (_backupedCount >= 5) + if (_numEnvironments >= Environments::kEnvironmentCount) return; - _cursorHotspotXArray[_backupedCount] = _vm->_draw->_cursorHotspotXVar; - _cursorHotspotYArray[_backupedCount] = _vm->_draw->_cursorHotspotYVar; - _totTextDataArray[_backupedCount] = _totTextData; - _totFileDataArray[_backupedCount] = _totFileData; - _totResourceTableArray[_backupedCount] = _totResourceTable; - _extTableArray[_backupedCount] = _extTable; - _extHandleArray[_backupedCount] = _extHandle; - _imFileDataArray[_backupedCount] = _imFileData; - _variablesArray[_backupedCount] = _vm->_inter->_variables; - strcpy(_curTotFileArray[_backupedCount], _curTotFile); - - curBackupPos = _curBackupPos; - _backupedCount++; - _curBackupPos = _backupedCount; - - _totTextData = 0; - _totFileData = 0; - _totResourceTable = 0; + _environments->set(_numEnvironments); + + curBackupPos = _curEnvironment; + _numEnvironments++; + _curEnvironment = _numEnvironments; + + _script = new Script(_vm); + _resources = new Resources(_vm); if (flags & 0x80) warning("Urban Stub: Game_v6::totSub(), flags & 0x80"); @@ -79,8 +70,10 @@ void Game_v6::totSub(int8 flags, const char *newTotFile) { strncpy0(_curTotFile, newTotFile, 9); strcat(_curTotFile, ".TOT"); - if (_vm->_inter->_terminate != 0) + if (_vm->_inter->_terminate != 0) { + clearUnusedEnvironment(); return; + } pushCollisions(0); @@ -99,22 +92,11 @@ void Game_v6::totSub(int8 flags, const char *newTotFile) { _vm->_inter->delocateVars(); } - _backupedCount--; - _curBackupPos = curBackupPos; - - _vm->_draw->_cursorHotspotXVar = _cursorHotspotXArray[_backupedCount]; - _vm->_draw->_cursorHotspotYVar = _cursorHotspotYArray[_backupedCount]; - _totTextData = _totTextDataArray[_backupedCount]; - _totFileData = _totFileDataArray[_backupedCount]; - _totResourceTable = _totResourceTableArray[_backupedCount]; - _extTable = _extTableArray[_backupedCount]; - _extHandle = _extHandleArray[_backupedCount]; - _imFileData = _imFileDataArray[_backupedCount]; - _vm->_inter->_variables = _variablesArray[_backupedCount]; - strcpy(_curTotFile, _curTotFileArray[_backupedCount]); - strcpy(_curExtFile, _curTotFile); - _curExtFile[strlen(_curExtFile) - 4] = '\0'; - strcat(_curExtFile, ".EXT"); + clearUnusedEnvironment(); + + _numEnvironments--; + _curEnvironment = curBackupPos; + _environments->get(_numEnvironments); } int16 Game_v6::addNewCollision(int16 id, uint16 left, uint16 top, @@ -148,7 +130,7 @@ int16 Game_v6::addNewCollision(int16 id, uint16 left, uint16 top, ptr->funcEnter = funcEnter; ptr->funcLeave = funcLeave; ptr->funcSub = funcSub; - ptr->totFileData = _totFileData; + ptr->script = _script; return i; } @@ -383,7 +365,6 @@ void Game_v6::collisionsBlock(void) { int16 array[300]; byte count; int16 collResId; - byte *startIP; int16 curCmd; int16 cmd; int16 cmdHigh; @@ -397,7 +378,6 @@ void Game_v6::collisionsBlock(void) { int16 stackPos2; int16 descIndex; int16 timeVal; - int16 offsetIP; char *str; int16 i; int16 counter; @@ -406,10 +386,11 @@ void Game_v6::collisionsBlock(void) { int16 collStackPos; Collision *collPtr; Collision *collArea; - byte *savedIP; byte collAreaStart; int16 activeCollResId = 0; int16 activeCollIndex = 0; + uint32 startPos; + uint32 offsetPos; if (_shouldPushColls) pushCollisions(0); @@ -422,25 +403,25 @@ void Game_v6::collisionsBlock(void) { _shouldPushColls = 0; collResId = -1; - _vm->_global->_inter_execPtr++; - count = *_vm->_global->_inter_execPtr++; + _script->skip(1); + count = _script->readByte(); - _handleMouse = _vm->_global->_inter_execPtr[0]; - deltaTime = 1000 * _vm->_global->_inter_execPtr[1]; - stackPos2 = _vm->_global->_inter_execPtr[3]; - descIndex = _vm->_global->_inter_execPtr[4]; - byte var_42 = _vm->_global->_inter_execPtr[5]; + _handleMouse = _script->peekByte(0); + deltaTime = 1000 * _script->peekByte(1); + stackPos2 = _script->peekByte(3); + descIndex = _script->peekByte(4); + byte var_42 = _script->peekByte(5); if ((stackPos2 != 0) || (descIndex != 0)) { deltaTime /= 100; - if (_vm->_global->_inter_execPtr[1] == 100) + if (_script->peekByte(1) == 100) deltaTime = 2; } timeVal = deltaTime; - _vm->_global->_inter_execPtr += 6; + _script->skip(6); - startIP = _vm->_global->_inter_execPtr; + startPos = _script->pos(); WRITE_VAR(16, 0); byte var_41 = 0; @@ -452,28 +433,27 @@ void Game_v6::collisionsBlock(void) { for (curCmd = 0; curCmd < count; curCmd++) { array[curCmd] = 0; - cmd = *_vm->_global->_inter_execPtr++; + cmd = _script->readByte(); if ((cmd & 0x40) != 0) { cmd -= 0x40; - cmdHigh = *_vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr++; + cmdHigh = _script->readByte(); cmdHigh <<= 8; } else cmdHigh = 0; if ((cmd & 0x80) != 0) { - offsetIP = _vm->_global->_inter_execPtr - _totFileData; - left = _vm->_parse->parseValExpr(); - top = _vm->_parse->parseValExpr(); - width = _vm->_parse->parseValExpr(); - height = _vm->_parse->parseValExpr(); + offsetPos = _script->pos(); + left = _script->readValExpr(); + top = _script->readValExpr(); + width = _script->readValExpr(); + height = _script->readValExpr(); } else { - offsetIP = 0; - left = _vm->_inter->load16(); - top = _vm->_inter->load16(); - width = _vm->_inter->load16(); - height = _vm->_inter->load16(); + offsetPos = 0; + left = _script->readUint16(); + top = _script->readUint16(); + width = _script->readUint16(); + height = _script->readUint16(); } if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) && (left != 0xFFFF)) { @@ -496,45 +476,37 @@ void Game_v6::collisionsBlock(void) { switch (cmd) { case 0: - _vm->_global->_inter_execPtr += 6; - startIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(6); + startPos = _script->pos(); + _script->skip(_script->peekUint16(2) + 2); key = curCmd + 0xA000; addNewCollision(curCmd + 0x8000, left, top, left + width - 1, top + height - 1, - cmd + cmdHigh, key, startIP - _totFileData, - _vm->_global->_inter_execPtr - _totFileData, offsetIP); + cmd + cmdHigh, key, startPos, + _script->pos(), offsetPos); - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); break; case 1: - key = _vm->_inter->load16(); - array[curCmd] = _vm->_inter->load16(); - flags = _vm->_inter->load16(); + key = _script->readInt16(); + array[curCmd] = _script->readInt16(); + flags = _script->readInt16(); - startIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + startPos = _script->pos(); + _script->skip(_script->peekUint16(2) + 2); if (key == 0) key = curCmd + 0xA000; addNewCollision(curCmd + 0x8000, left, top, left + width - 1, top + height - 1, - (flags << 4) + cmd + cmdHigh, key, startIP - _totFileData, - _vm->_global->_inter_execPtr - _totFileData, offsetIP); + (flags << 4) + cmd + cmdHigh, key, startPos, + _script->pos(), offsetPos); - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); break; @@ -548,23 +520,20 @@ void Game_v6::collisionsBlock(void) { case 10: _vm->_util->clearKeyBuf(); var_1C = 1; - key = _vm->_parse->parseVarIndex(); - descArray[index].fontIndex = _vm->_inter->load16(); - descArray[index].backColor = *_vm->_global->_inter_execPtr++; - descArray[index].frontColor = *_vm->_global->_inter_execPtr++; + key = _script->readVarIndex(); + descArray[index].fontIndex = _script->readInt16(); + descArray[index].backColor = _script->readByte(); + descArray[index].frontColor = _script->readByte(); if ((cmd >= 5) && (cmd <= 8)) { - descArray[index].ptr = _vm->_global->_inter_execPtr + 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr) + 2; + descArray[index].ptr = _script->getData() + _script->pos() + 2; + _script->skip(_script->peekUint16() + 2); } else descArray[index].ptr = 0; if (left == 0xFFFF) { if ((cmd & 1) == 0) { - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); } break; } @@ -575,50 +544,44 @@ void Game_v6::collisionsBlock(void) { funcLeave = 0; if (!(cmd & 1)) - funcLeave = _vm->_global->_inter_execPtr - _totFileData; + funcLeave = _script->pos(); addNewCollision(curCmd + 0x8000, left, top, right, top + height - 1, cmd, key, 0, funcLeave, 0); if (!(cmd & 1)) { - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); } index++; break; case 11: - _vm->_global->_inter_execPtr += 6; + _script->skip(6); for (i = 0; i < 150; i++) { if ((_collisionAreas[i].id & 0xF000) == 0xE000) { _collisionAreas[i].id &= 0xBFFF; _collisionAreas[i].funcEnter = - _vm->_global->_inter_execPtr - _totFileData; + _script->pos(); _collisionAreas[i].funcLeave = - _vm->_global->_inter_execPtr - _totFileData; + _script->pos(); } } - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); break; case 12: - _vm->_global->_inter_execPtr += 6; + _script->skip(6); for (i = 0; i < 150; i++) { if ((_collisionAreas[i].id & 0xF000) == 0xD000) { _collisionAreas[i].id &= 0xBFFF; _collisionAreas[i].funcEnter = - _vm->_global->_inter_execPtr - _totFileData; + _script->pos(); _collisionAreas[i].funcLeave = - _vm->_global->_inter_execPtr - _totFileData; + _script->pos(); } } - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); break; case 20: @@ -626,34 +589,30 @@ void Game_v6::collisionsBlock(void) { // Fall through to case 2 case 2: - key = _vm->_inter->load16(); - array[curCmd] = _vm->_inter->load16(); - flags = _vm->_inter->load16(); + key = _script->readInt16(); + array[curCmd] = _script->readInt16(); + flags = _script->readInt16(); addNewCollision(curCmd + 0x8000, left, top, left + width - 1, top + height - 1, (flags << 4) + cmdHigh + 2, key, 0, - _vm->_global->_inter_execPtr - _totFileData, offsetIP); + _script->pos(), offsetPos); - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); break; case 21: - key = _vm->_inter->load16(); - array[curCmd] = _vm->_inter->load16(); - flags = _vm->_inter->load16() & 3; + key = _script->readInt16(); + array[curCmd] = _script->readInt16(); + flags = _script->readInt16() & 3; addNewCollision(curCmd + 0x8000, left, top, left + width - 1, top + height - 1, (flags << 4) + cmdHigh + 2, key, - _vm->_global->_inter_execPtr - _totFileData, 0, offsetIP); + _script->pos(), 0, offsetPos); - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); break; } @@ -915,10 +874,8 @@ void Game_v6::collisionsBlock(void) { if (_handleMouse == 1) _vm->_draw->blitCursor(); - savedIP = 0; if (!_vm->_inter->_terminate && (var_41 == 0)) { - savedIP = _totFileData + - _collisionAreas[activeCollIndex].funcLeave; + _script->seek(_collisionAreas[activeCollIndex].funcLeave); _vm->_inter->storeMouse(); if (VAR(16) == 0) { @@ -927,7 +884,8 @@ void Game_v6::collisionsBlock(void) { else WRITE_VAR(16, activeCollResId & 0xFFF); } - } + } else + _script->setFinished(true); for (curCmd = 0; curCmd < count; curCmd++) freeCollision(curCmd + 0x8000); @@ -937,8 +895,6 @@ void Game_v6::collisionsBlock(void) { ((_collisionAreas[i].id & 0xF000) == 0x9000)) _collisionAreas[i].id |= 0x4000; } - - _vm->_global->_inter_execPtr = savedIP; } void Game_v6::setCollisions(byte arg_0) { @@ -950,23 +906,22 @@ void Game_v6::setCollisions(byte arg_0) { if (collArea->flags & 0x80) continue; - byte *totFileData = collArea->totFileData; - - if (!totFileData) - totFileData = _totFileData; + Script *curScript = _script; - byte *savedIP = _vm->_global->_inter_execPtr; + _script = collArea->script; + if (!_script) + _script = curScript; - _vm->_global->_inter_execPtr = totFileData + collArea->funcSub; + _script->call(collArea->funcSub); - int16 left = _vm->_parse->parseValExpr(); - int16 top = _vm->_parse->parseValExpr(); - int16 width = _vm->_parse->parseValExpr(); - int16 height = _vm->_parse->parseValExpr(); + int16 left = _script->readValExpr(); + int16 top = _script->readValExpr(); + int16 width = _script->readValExpr(); + int16 height = _script->readValExpr(); uint16 flags = 0; if ((collArea->id & 0xF000) == 0xA000) - flags = _vm->_parse->parseValExpr(); + flags = _script->readValExpr(); if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) && (left != -1)) { @@ -1001,16 +956,18 @@ void Game_v6::setCollisions(byte arg_0) { if ((collArea->id & 0xF000) == 0xA000) collArea->flags = flags; - _vm->_global->_inter_execPtr = savedIP; + _script->pop(); + + _script = curScript; } } void Game_v6::collSub(uint16 offset) { - byte *savedIP; int16 collStackSize; - savedIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr = _totFileData + offset; + uint32 savedPos = _script->pos(); + + _script->seek(offset); _shouldPushColls = 1; collStackSize = _collStackSize; @@ -1021,7 +978,8 @@ void Game_v6::collSub(uint16 offset) { popCollisions(); _shouldPushColls = 0; - _vm->_global->_inter_execPtr = savedIP; + + _script->seek(savedPos); if ((_vm->_util->getTimeKey() - _someTimeDly) > 500) setCollisions(0); diff --git a/engines/gob/global.cpp b/engines/gob/global.cpp index 005d65815f..4165938966 100644 --- a/engines/gob/global.cpp +++ b/engines/gob/global.cpp @@ -37,35 +37,36 @@ Global::Global(GobEngine *vm) : _vm(vm) { _presentVGA = UNDEF; _presentHER = UNDEF; - _videoMode = 0; + _videoMode = 0; _fakeVideoMode = 0; - _oldMode = 3; + _oldMode = 3; _soundFlags = 0; - _language = 0x8000; + _language = 0x8000; _languageWanted = 0x8000; + _foundLanguage = false; - _useMouse = UNDEF; + _useMouse = UNDEF; _mousePresent = UNDEF; - _mouseXShift = 3; - _mouseYShift = 3; + _mouseXShift = 3; + _mouseYShift = 3; - _mouseMinX = 0; - _mouseMinY = 0; + _mouseMinX = 0; + _mouseMinY = 0; _mouseMaxX = 320; _mouseMaxY = 200; _useJoystick = 1; - _primaryWidth = 0; + _primaryWidth = 0; _primaryHeight = 0; _colorCount = 16; for (int i = 0; i < 256; i++) { - _redPalette[i] = 0; + _redPalette [i] = 0; _greenPalette[i] = 0; - _bluePalette[i] = 0; + _bluePalette [i] = 0; } _unusedPalette1[ 0] = (int16) 0x0000; @@ -109,15 +110,12 @@ Global::Global(GobEngine *vm) : _vm(vm) { _pPaletteDesc = 0; - _setAllPalette = false; + _setAllPalette = false; _dontSetPalette = false; _debugFlag = 0; _inVM = 0; - _inter_resStr[0] = 0; - _inter_resVal = 0; - _inter_execPtr = 0; _inter_animDataSize = 10; diff --git a/engines/gob/global.h b/engines/gob/global.h index 9f12f4ded6..982ce113cb 100644 --- a/engines/gob/global.h +++ b/engines/gob/global.h @@ -33,37 +33,51 @@ namespace Gob { -#define VIDMODE_CGA 0x05 -#define VIDMODE_EGA 0x0D -#define VIDMODE_VGA 0x13 -#define VIDMODE_HER 7 - -#define PROAUDIO_FLAG 0x10 -#define ADLIB_FLAG 0x08 -#define BLASTER_FLAG 0x04 -#define INTERSOUND_FLAG 0x02 -#define SPEAKER_FLAG 0x01 -#define MIDI_FLAG 0x4000 - -#define NO 0 -#define YES 1 -#define UNDEF 2 - -#define F1_KEY 0x3B00 -#define F2_KEY 0x3C00 -#define F3_KEY 0x3D00 -#define F4_KEY 0x3E00 -#define F5_KEY 0x3F00 -#define F6_KEY 0x4000 -#define ESCAPE 0x001B -#define ENTER 0x000D +#define VIDMODE_CGA 0x05 +#define VIDMODE_EGA 0x0D +#define VIDMODE_VGA 0x13 +#define VIDMODE_HER 0x07 + +#define MIDI_FLAG 0x4000 +#define PROAUDIO_FLAG 0x0010 +#define ADLIB_FLAG 0x0008 +#define BLASTER_FLAG 0x0004 +#define INTERSOUND_FLAG 0x0002 +#define SPEAKER_FLAG 0x0001 + +#define NO 0 +#define YES 1 +#define UNDEF 2 + +#define F1_KEY 0x3B00 +#define F2_KEY 0x3C00 +#define F3_KEY 0x3D00 +#define F4_KEY 0x3E00 +#define F5_KEY 0x3F00 +#define F6_KEY 0x4000 +#define ESCAPE 0x001B +#define ENTER 0x000D /* Video drivers */ -#define UNK_DRIVER 0 -#define VGA_DRIVER 1 -#define EGA_DRIVER 2 -#define CGA_DRIVER 3 -#define HER_DRIVER 4 +#define UNK_DRIVER 0 +#define VGA_DRIVER 1 +#define EGA_DRIVER 2 +#define CGA_DRIVER 3 +#define HER_DRIVER 4 + +enum Language { + kLanguageFrench = 0, + kLanguageGerman = 1, + kLanguageBritish = 2, + kLanguageSpanish = 3, + kLanguageItalian = 4, + kLanguageAmerican = 5, + kLanguageDutch = 6, + kLanguageKorean = 7, + kLanguageHebrew = 8, + kLanguagePortuguese = 9, + kLanguageJapanese = 10 +}; class Global { public: @@ -82,6 +96,7 @@ public: uint16 _language; uint16 _languageWanted; + bool _foundLanguage; char _useMouse; int16 _mousePresent; @@ -117,9 +132,6 @@ public: int16 _debugFlag; int16 _inVM; - char _inter_resStr[200]; - int32 _inter_resVal; - byte *_inter_execPtr; int16 _inter_animDataSize; diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp index 1de6245297..e534464cce 100644 --- a/engines/gob/gob.cpp +++ b/engines/gob/gob.cpp @@ -47,7 +47,6 @@ #include "gob/map.h" #include "gob/mult.h" #include "gob/palanim.h" -#include "gob/parse.h" #include "gob/scenery.h" #include "gob/videoplayer.h" #include "gob/save/saveload.h" @@ -102,12 +101,12 @@ void PauseDialog::handleKeyDown(Common::KeyState state) { GobEngine::GobEngine(OSystem *syst) : Engine(syst) { - _sound = 0; _mult = 0; _game = 0; - _global = 0; _dataIO = 0; _goblin = 0; - _vidPlayer = 0; _init = 0; _inter = 0; - _map = 0; _palAnim = 0; _parse = 0; - _scenery = 0; _draw = 0; _util = 0; - _video = 0; _saveLoad = 0; + _sound = 0; _mult = 0; _game = 0; + _global = 0; _dataIO = 0; _goblin = 0; + _vidPlayer = 0; _init = 0; _inter = 0; + _map = 0; _palAnim = 0; _scenery = 0; + _draw = 0; _util = 0; _video = 0; + _saveLoad = 0; _pauseStart = 0; @@ -121,7 +120,7 @@ GobEngine::GobEngine(OSystem *syst) : Engine(syst) { Common::addDebugChannel(kDebugDrawOp, "DrawOpcodes", "Script DrawOpcodes debug level"); Common::addDebugChannel(kDebugGobOp, "GoblinOpcodes", "Script GoblinOpcodes debug level"); Common::addDebugChannel(kDebugSound, "Sound", "Sound output debug level"); - Common::addDebugChannel(kDebugParser, "Parser", "Parser debug level"); + Common::addDebugChannel(kDebugExpression, "Expression", "Expression parser debug level"); Common::addDebugChannel(kDebugGameFlow, "Gameflow", "Gameflow debug level"); Common::addDebugChannel(kDebugFileIO, "FileIO", "File Input/Output debug level"); Common::addDebugChannel(kDebugSaveLoad, "SaveLoad", "Saving/Loading debug level"); @@ -248,42 +247,42 @@ Common::Error GobEngine::run() { switch (_language) { case Common::FR_FRA: case Common::RU_RUS: - _global->_language = 0; + _global->_language = kLanguageFrench; break; case Common::DE_DEU: - _global->_language = 1; + _global->_language = kLanguageGerman; break; case Common::EN_ANY: case Common::EN_GRB: - _global->_language = 2; + case Common::HU_HUN: + _global->_language = kLanguageBritish; break; case Common::ES_ESP: - _global->_language = 3; + _global->_language = kLanguageSpanish; break; case Common::IT_ITA: - _global->_language = 4; + _global->_language = kLanguageItalian; break; case Common::EN_USA: - _global->_language = 5; + _global->_language = kLanguageAmerican; break; case Common::NL_NLD: - _global->_language = 6; + _global->_language = kLanguageDutch; break; case Common::KO_KOR: - _global->_language = 7; + _global->_language = kLanguageKorean; break; case Common::HB_ISR: - _global->_language = 8; + _global->_language = kLanguageHebrew; break; case Common::PT_BRA: - _global->_language = 9; + _global->_language = kLanguagePortuguese; break; case Common::JA_JPN: - _global->_language = 10; + _global->_language = kLanguageJapanese; break; default: - // Default to English - _global->_language = 2; + _global->_language = kLanguageBritish; break; } _global->_languageWanted = _global->_language; @@ -332,7 +331,6 @@ bool GobEngine::initGameParts() { _palAnim = new PalAnim(this); _vidPlayer = new VideoPlayer(this); _sound = new Sound(this); - _parse = new Parse(this); switch (_gameType) { case kGameTypeGeisha: @@ -465,6 +463,8 @@ bool GobEngine::initGameParts() { break; } + _inter->setupOpcodes(); + if (is640()) { _video->_surfWidth = _width = 640; _video->_surfHeight = _video->_splitHeight1 = _height = 480; @@ -495,7 +495,6 @@ void GobEngine::deinitGameParts() { delete _inter; _inter = 0; delete _map; _map = 0; delete _palAnim; _palAnim = 0; - delete _parse; _parse = 0; delete _scenery; _scenery = 0; delete _draw; _draw = 0; delete _util; _util = 0; diff --git a/engines/gob/gob.h b/engines/gob/gob.h index 43e2270354..5d1cb3ecf2 100644 --- a/engines/gob/gob.h +++ b/engines/gob/gob.h @@ -52,7 +52,6 @@ class Inter; class Map; class Mult; class PalAnim; -class Parse; class Scenery; class Util; class SaveLoad; @@ -128,7 +127,7 @@ enum { kDebugDrawOp = 1 << 1, kDebugGobOp = 1 << 2, kDebugSound = 1 << 3, - kDebugParser = 1 << 4, + kDebugExpression = 1 << 4, kDebugGameFlow = 1 << 5, kDebugFileIO = 1 << 6, kDebugSaveLoad = 1 << 7, @@ -197,7 +196,6 @@ public: Map *_map; Mult *_mult; PalAnim *_palAnim; - Parse *_parse; Scenery *_scenery; Inter *_inter; SaveLoad *_saveLoad; diff --git a/engines/gob/init.cpp b/engines/gob/init.cpp index 8bf9536286..f9a22f52fb 100644 --- a/engines/gob/init.cpp +++ b/engines/gob/init.cpp @@ -32,6 +32,7 @@ #include "gob/dataio.h" #include "gob/draw.h" #include "gob/game.h" +#include "gob/script.h" #include "gob/palanim.h" #include "gob/inter.h" #include "gob/video.h" @@ -80,9 +81,6 @@ void Init::doDemo() { } void Init::initGame() { - int16 handle2; - int16 handle; - int16 imdHandle; byte *infBuf; char *infPtr; char *infEnd; @@ -91,11 +89,8 @@ void Init::initGame() { initVideo(); if (!_vm->isDemo()) { - handle2 = _vm->_dataIO->openData(_vm->_startStk.c_str()); - if (handle2 >= 0) { - _vm->_dataIO->closeData(handle2); + if (_vm->_dataIO->existData(_vm->_startStk.c_str())) _vm->_dataIO->openDataFile(_vm->_startStk.c_str()); - } } _vm->_util->initInput(); @@ -104,8 +99,6 @@ void Init::initGame() { _vm->_global->_mouseXShift = 1; _vm->_global->_mouseYShift = 1; - _vm->_game->_totTextData = 0; - _vm->_game->_totFileData = 0; _palDesc = new Video::PalDesc; _vm->validateVideoMode(_vm->_global->_videoMode); @@ -127,19 +120,13 @@ void Init::initGame() { return; } - handle = _vm->_dataIO->openData("intro.inf"); + if (!_vm->_dataIO->existData("intro.inf")) { - if (handle < 0) { - for (int i = 0; i < 4; i++) { - handle2 = _vm->_dataIO->openData(_fontNames[i]); - if (handle2 >= 0) { - _vm->_dataIO->closeData(handle2); + for (int i = 0; i < 4; i++) + if (_vm->_dataIO->existData(_fontNames[i])) _vm->_draw->_fonts[i] = _vm->_util->loadFont(_fontNames[i]); - } - } - } else { - _vm->_dataIO->closeData(handle); + } else { infBuf = _vm->_dataIO->getData("intro.inf"); infPtr = (char *) infBuf; @@ -153,11 +140,8 @@ void Init::initGame() { buffer[j] = 0; strcat(buffer, ".let"); - handle2 = _vm->_dataIO->openData(buffer); - if (handle2 >= 0) { - _vm->_dataIO->closeData(handle2); + if (_vm->_dataIO->existData(buffer)) _vm->_draw->_fonts[i] = _vm->_util->loadFont(buffer); - } if ((infPtr + 1) >= infEnd) break; @@ -167,26 +151,16 @@ void Init::initGame() { delete[] infBuf; } - strcpy(buffer, _vm->_startTot.c_str()); - handle = _vm->_dataIO->openData(buffer); + if (_vm->_dataIO->existData(_vm->_startTot.c_str())) { + _vm->_inter->allocateVars(Script::getVariablesCount(_vm->_startTot.c_str(), _vm)); - if (handle >= 0) { - DataStream *stream = _vm->_dataIO->openAsStream(handle, true); - - stream->seek(0x2C); - _vm->_inter->allocateVars(stream->readUint16LE()); - - delete stream; - - strcpy(_vm->_game->_curTotFile, buffer); + strcpy(_vm->_game->_curTotFile, _vm->_startTot.c_str()); _vm->_sound->cdTest(1, "GOB"); _vm->_sound->cdLoadLIC("gob.lic"); // Search for a Coktel logo animation or image to display - imdHandle = _vm->_dataIO->openData("coktel.imd"); - if (imdHandle >= 0) { - _vm->_dataIO->closeData(imdHandle); + if (_vm->_dataIO->existData("coktel.imd")) { _vm->_draw->initScreen(); _vm->_draw->_cursorIndex = -1; @@ -198,19 +172,17 @@ void Init::initGame() { } _vm->_draw->closeScreen(); - } else if ((imdHandle = _vm->_dataIO->openData("coktel.clt")) >= 0) { + } else if (_vm->_dataIO->existData("coktel.clt")) { _vm->_draw->initScreen(); - - stream = _vm->_dataIO->openAsStream(imdHandle, true); _vm->_util->clearPalette(); + + DataStream *stream = _vm->_dataIO->getDataStream("coktel.clt"); stream->read((byte *) _vm->_draw->_vgaPalette, 768); delete stream; - imdHandle = _vm->_dataIO->openData("coktel.ims"); - if (imdHandle >= 0) { + if (_vm->_dataIO->existData("coktel.ims")) { byte *sprBuf; - _vm->_dataIO->closeData(imdHandle); sprBuf = _vm->_dataIO->getData("coktel.ims"); _vm->_video->drawPackedSprite(sprBuf, 320, 200, 0, 0, 0, *_vm->_draw->_frontSurface); diff --git a/engines/gob/inter.cpp b/engines/gob/inter.cpp index ce7f2ba319..8be07034c6 100644 --- a/engines/gob/inter.cpp +++ b/engines/gob/inter.cpp @@ -33,7 +33,8 @@ #include "gob/util.h" #include "gob/draw.h" #include "gob/game.h" -#include "gob/parse.h" +#include "gob/expression.h" +#include "gob/script.h" #include "gob/scenery.h" #include "gob/sound/sound.h" @@ -67,65 +68,93 @@ Inter::~Inter() { delocateVars(); } -void Inter::initControlVars(char full) { - *_nestLevel = 0; - *_breakFromLevel = -1; +void Inter::setupOpcodes() { + setupOpcodesDraw(); + setupOpcodesFunc(); + setupOpcodesGob(); +} - *_vm->_scenery->_pCaptureCounter = 0; +void Inter::executeOpcodeDraw(byte i) { + debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)", i, i, getDescOpcodeDraw(i)); - _break = false; - _terminate = 0; + if (_opcodesDraw[i].proc && _opcodesDraw[i].proc->isValid()) + (*_opcodesDraw[i].proc)(); + else + warning("unimplemented opcodeDraw: %d [0x%X]", i, i); +} - if (full == 1) { - for (int i = 0; i < 8; i++) - _animPalDir[i] = 0; - _soundEndTimeKey = 0; +bool Inter::executeOpcodeFunc(byte i, byte j, OpFuncParams ¶ms) { + debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s)", + i, j, i, j, getDescOpcodeFunc(i, j)); + + if ((i > 4) || (j > 15)) { + warning("unimplemented opcodeFunc: %d.%d [0x%X.0x%X]", i, j, i, j); + return false; } + + i = i * 16 + j; + if (_opcodesFunc[i].proc && _opcodesFunc[i].proc->isValid()) + return (*_opcodesFunc[i].proc)(params); + else + warning("unimplemented opcodeFunc: %d.%d [0x%X.0x%X]", i, j, i, j); + + return false; } -int16 Inter::load16() { - int16 tmp = (int16) READ_LE_UINT16(_vm->_global->_inter_execPtr); - _vm->_global->_inter_execPtr += 2; - return tmp; +void Inter::executeOpcodeGob(int i, OpGobParams ¶ms) { + debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)", + i, i, getDescOpcodeGob(i)); + + OpcodeEntry<OpcodeGob> *op = 0; + + if (_opcodesGob.contains(i)) + op = &_opcodesGob.getVal(i); + + if (op && op->proc && op->proc->isValid()) { + (*op->proc)(params); + return; + } + + _vm->_game->_script->skip(params.paramCount << 1); + warning("unimplemented opcodeGob: %d [0x%X]", i, i); } -char Inter::evalExpr(int16 *pRes) { - byte token; +const char *Inter::getDescOpcodeDraw(byte i) { + const char *desc = _opcodesDraw[i].desc; - _vm->_parse->printExpr(99); + return ((desc) ? desc : ""); +} - _vm->_parse->parseExpr(99, &token); - if (!pRes) - return token; +const char *Inter::getDescOpcodeFunc(byte i, byte j) { + if ((i > 4) || (j > 15)) + return ""; - switch (token) { - case 20: - *pRes = _vm->_global->_inter_resVal; - break; + const char *desc = _opcodesFunc[i * 16 + j].desc; - case 22: - case 23: - *pRes = 0; - break; + return ((desc) ? desc : ""); +} - case 24: - *pRes = 1; - break; - } +const char *Inter::getDescOpcodeGob(int i) { + if (_opcodesGob.contains(i)) + return _opcodesGob.getVal(i).desc; - return token; + return ""; } -bool Inter::evalBoolResult() { - byte token; +void Inter::initControlVars(char full) { + *_nestLevel = 0; + *_breakFromLevel = -1; + + *_vm->_scenery->_pCaptureCounter = 0; - _vm->_parse->printExpr(99); + _break = false; + _terminate = 0; - _vm->_parse->parseExpr(99, &token); - if ((token == 24) || ((token == 20) && _vm->_global->_inter_resVal)) - return true; - else - return false; + if (full == 1) { + for (int i = 0; i < 8; i++) + _animPalDir[i] = 0; + _soundEndTimeKey = 0; + } } void Inter::renewTimeInVars() { @@ -185,14 +214,14 @@ void Inter::storeKey(int16 key) { void Inter::writeVar(uint32 offset, uint16 type, uint32 value) { switch (type) { - case 16: - case 18: + case TYPE_VAR_INT8: + case TYPE_ARRAY_INT8: WRITE_VARO_UINT8(offset, value); break; - case 17: - case 24: - case 27: + case TYPE_VAR_INT16: + case TYPE_VAR_INT32_AS_INT16: + case TYPE_ARRAY_INT16: WRITE_VARO_UINT16(offset, value); break; @@ -209,20 +238,20 @@ void Inter::funcBlock(int16 retFlag) { params.retFlag = retFlag; - if (!_vm->_global->_inter_execPtr) + if (_vm->_game->_script->isFinished()) return; _break = false; - _vm->_global->_inter_execPtr++; - params.cmdCount = *_vm->_global->_inter_execPtr++; - _vm->_global->_inter_execPtr += 2; + _vm->_game->_script->skip(1); + params.cmdCount = _vm->_game->_script->readByte(); + _vm->_game->_script->skip(2); if (params.cmdCount == 0) { - _vm->_global->_inter_execPtr = 0; + _vm->_game->_script->setFinished(true); return; } - int startaddr = _vm->_global->_inter_execPtr - _vm->_game->_totFileData; + int startaddr = _vm->_game->_script->pos(); params.counter = 0; do { @@ -237,7 +266,7 @@ void Inter::funcBlock(int16 retFlag) { (_vm->getPlatform() == Common::kPlatformMacintosh) || (_vm->getPlatform() == Common::kPlatformWindows))) { - int addr = _vm->_global->_inter_execPtr-_vm->_game->_totFileData; + int addr = _vm->_game->_script->pos(); if ((startaddr == 0x18B4 && addr == 0x1A7F && // Zombie, EGA !strncmp(_vm->_game->_curTotFile, "avt005.tot", 10)) || @@ -263,20 +292,19 @@ void Inter::funcBlock(int16 retFlag) { } // End of workaround - cmd = *_vm->_global->_inter_execPtr; + cmd = _vm->_game->_script->readByte(); if ((cmd >> 4) >= 12) { cmd2 = 16 - (cmd >> 4); cmd &= 0xF; } else cmd2 = 0; - _vm->_global->_inter_execPtr++; params.counter++; if (cmd2 == 0) cmd >>= 4; - if (executeFuncOpcode(cmd2, cmd, params)) + if (executeOpcodeFunc(cmd2, cmd, params)) return; if (_vm->shouldQuit()) @@ -292,17 +320,17 @@ void Inter::funcBlock(int16 retFlag) { } } while (params.counter != params.cmdCount); - _vm->_global->_inter_execPtr = 0; + _vm->_game->_script->setFinished(true); return; } void Inter::callSub(int16 retFlag) { byte block; - while (!_vm->shouldQuit() && _vm->_global->_inter_execPtr && - (_vm->_global->_inter_execPtr != _vm->_game->_totFileData)) { + while (!_vm->shouldQuit() && !_vm->_game->_script->isFinished() && + (_vm->_game->_script->pos() != 0)) { - block = *_vm->_global->_inter_execPtr; + block = _vm->_game->_script->peekByte(); if (block == 1) funcBlock(retFlag); else if (block == 2) @@ -311,7 +339,7 @@ void Inter::callSub(int16 retFlag) { error("Unknown block type %d in Inter::callSub()", block); } - if (_vm->_global->_inter_execPtr == _vm->_game->_totFileData) + if (!_vm->_game->_script->isFinished() && (_vm->_game->_script->pos() == 0)) _terminate = 1; } diff --git a/engines/gob/inter.h b/engines/gob/inter.h index 412c3f2673..d4ed2d3240 100644 --- a/engines/gob/inter.h +++ b/engines/gob/inter.h @@ -26,6 +26,9 @@ #ifndef GOB_INTER_H #define GOB_INTER_H +#include "common/func.h" +#include "common/hashmap.h" + #include "gob/goblin.h" #include "gob/variables.h" @@ -34,11 +37,54 @@ namespace Gob { // This is to help devices with small memory (PDA, smartphones, ...) // to save abit of memory used by opcode names in the Scumm engine. #ifndef REDUCE_MEMORY_USAGE -# define _OPCODE(ver, x) { &ver::x, #x } + #define _OPCODEDRAW(ver, x) setProc(new Common::Functor0Mem<void, ver>(this, &ver::x), #x) + #define _OPCODEFUNC(ver, x) setProc(new Common::Functor1Mem<OpFuncParams &, bool, ver>(this, &ver::x), #x) + #define _OPCODEGOB(ver, x) setProc(new Common::Functor1Mem<OpGobParams &, void, ver>(this, &ver::x), #x) #else -# define _OPCODE(ver, x) { &ver::x, "" } + #define _OPCODEDRAW(ver, x) setProc(new Common::Functor0Mem<void, ver>(this, &ver::x), "") + #define _OPCODEFUNC(ver, x) setProc(new Common::Functor1Mem<OpFuncParams &, bool, ver>(this, &ver::x), "") + #define _OPCODEGOB(ver, x) setProc(new Common::Functor1Mem<OpGobParams &, void, ver>(this, &ver::x), "") #endif +#define CLEAROPCODEDRAW(i) _opcodesDraw[i].setProc(0, 0) +#define CLEAROPCODEFUNC(i) _opcodesFunc[i].setProc(0, 0) +#define CLEAROPCODEGOB(i) _opcodesGob.erase(i) + +typedef Common::Functor0<void> OpcodeDraw; +typedef Common::Functor1<struct OpFuncParams &, bool> OpcodeFunc; +typedef Common::Functor1<struct OpGobParams &, void> OpcodeGob; + +struct OpFuncParams { + byte cmdCount; + byte counter; + int16 retFlag; +}; +struct OpGobParams { + int16 extraData; + int16 paramCount; + VariableReference retVarPtr; + Goblin::Gob_Object *objDesc; +}; + +template<typename T> +struct OpcodeEntry : Common::NonCopyable { + T *proc; + const char *desc; + + OpcodeEntry() : proc(0), desc(0) {} + ~OpcodeEntry() { + setProc(0, 0); + } + + void setProc(T *p, const char *d) { + if (proc != p) { + delete proc; + proc = p; + } + desc = d; + } +}; + class Inter { public: uint8 _terminate; @@ -51,10 +97,9 @@ public: Variables *_variables; + void setupOpcodes(); + void initControlVars(char full); - int16 load16(); - char evalExpr(int16 *pRes); - bool evalBoolResult(); void renewTimeInVars(); void storeMouse(); void storeKey(int16 key); @@ -74,16 +119,9 @@ public: virtual ~Inter(); protected: - struct OpFuncParams { - byte cmdCount; - byte counter; - int16 retFlag; - }; - struct OpGobParams { - int16 extraData; - VariableReference retVarPtr; - Goblin::Gob_Object *objDesc; - }; + OpcodeEntry<OpcodeDraw> _opcodesDraw[256]; + OpcodeEntry<OpcodeFunc> _opcodesFunc[256]; + Common::HashMap<int, OpcodeEntry<OpcodeGob> > _opcodesGob; bool _break; @@ -99,15 +137,19 @@ protected: GobEngine *_vm; - virtual void setupOpcodes() = 0; - virtual void executeDrawOpcode(byte i) = 0; - virtual bool executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms) = 0; - virtual void executeGoblinOpcode(int i, OpGobParams ¶ms) = 0; - virtual const char *getOpcodeDrawDesc(byte i) = 0; - virtual const char *getOpcodeFuncDesc(byte i, byte j) = 0; - virtual const char *getOpcodeGoblinDesc(int i) = 0; + void executeOpcodeDraw(byte i); + bool executeOpcodeFunc(byte i, byte j, OpFuncParams ¶ms); + void executeOpcodeGob(int i, OpGobParams ¶ms); + + const char *getDescOpcodeDraw(byte i); + const char *getDescOpcodeFunc(byte i, byte j); + const char *getDescOpcodeGob(int i); - virtual void checkSwitchTable(byte **ppExec) = 0; + virtual void setupOpcodesDraw() = 0; + virtual void setupOpcodesFunc() = 0; + virtual void setupOpcodesGob() = 0; + + virtual void checkSwitchTable(uint32 &offset) = 0; void o_drawNOP() {} bool o_funcNOP(OpFuncParams ¶ms) { return false; } @@ -123,35 +165,11 @@ public: virtual void animPalette(); protected: - typedef void (Inter_v1::*OpcodeDrawProcV1)(); - typedef bool (Inter_v1::*OpcodeFuncProcV1)(OpFuncParams &); - typedef void (Inter_v1::*OpcodeGoblinProcV1)(OpGobParams &); - struct OpcodeDrawEntryV1 { - OpcodeDrawProcV1 proc; - const char *desc; - }; - struct OpcodeFuncEntryV1 { - OpcodeFuncProcV1 proc; - const char *desc; - }; - struct OpcodeGoblinEntryV1 { - OpcodeGoblinProcV1 proc; - const char *desc; - }; - const OpcodeDrawEntryV1 *_opcodesDrawV1; - const OpcodeFuncEntryV1 *_opcodesFuncV1; - const OpcodeGoblinEntryV1 *_opcodesGoblinV1; - static const int _goblinFuncLookUp[][2]; - - virtual void setupOpcodes(); - virtual void executeDrawOpcode(byte i); - virtual bool executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms); - virtual void executeGoblinOpcode(int i, OpGobParams ¶ms); - virtual const char *getOpcodeDrawDesc(byte i); - virtual const char *getOpcodeFuncDesc(byte i, byte j); - virtual const char *getOpcodeGoblinDesc(int i); - - virtual void checkSwitchTable(byte **ppExec); + virtual void setupOpcodesDraw(); + virtual void setupOpcodesFunc(); + virtual void setupOpcodesGob(); + + virtual void checkSwitchTable(uint32 &offset); void o1_loadMult(); void o1_playMult(); @@ -318,35 +336,11 @@ public: virtual void animPalette(); protected: - typedef void (Inter_v2::*OpcodeDrawProcV2)(); - typedef bool (Inter_v2::*OpcodeFuncProcV2)(OpFuncParams &); - typedef void (Inter_v2::*OpcodeGoblinProcV2)(OpGobParams &); - struct OpcodeDrawEntryV2 { - OpcodeDrawProcV2 proc; - const char *desc; - }; - struct OpcodeFuncEntryV2 { - OpcodeFuncProcV2 proc; - const char *desc; - }; - struct OpcodeGoblinEntryV2 { - OpcodeGoblinProcV2 proc; - const char *desc; - }; - const OpcodeDrawEntryV2 *_opcodesDrawV2; - const OpcodeFuncEntryV2 *_opcodesFuncV2; - const OpcodeGoblinEntryV2 *_opcodesGoblinV2; - static const int _goblinFuncLookUp[][2]; - - virtual void setupOpcodes(); - virtual void executeDrawOpcode(byte i); - virtual bool executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms); - virtual void executeGoblinOpcode(int i, OpGobParams ¶ms); - virtual const char *getOpcodeDrawDesc(byte i); - virtual const char *getOpcodeFuncDesc(byte i, byte j); - virtual const char *getOpcodeGoblinDesc(int i); - - virtual void checkSwitchTable(byte **ppExec); + virtual void setupOpcodesDraw(); + virtual void setupOpcodesFunc(); + virtual void setupOpcodesGob(); + + virtual void checkSwitchTable(uint32 &offset); void o2_playMult(); void o2_freeMultKeys(); @@ -410,33 +404,9 @@ public: virtual ~Inter_Bargon() {} protected: - typedef void (Inter_Bargon::*OpcodeDrawProcBargon)(); - typedef bool (Inter_Bargon::*OpcodeFuncProcBargon)(OpFuncParams &); - typedef void (Inter_Bargon::*OpcodeGoblinProcBargon)(OpGobParams &); - struct OpcodeDrawEntryBargon { - OpcodeDrawProcBargon proc; - const char *desc; - }; - struct OpcodeFuncEntryBargon { - OpcodeFuncProcBargon proc; - const char *desc; - }; - struct OpcodeGoblinEntryBargon { - OpcodeGoblinProcBargon proc; - const char *desc; - }; - const OpcodeDrawEntryBargon *_opcodesDrawBargon; - const OpcodeFuncEntryBargon *_opcodesFuncBargon; - const OpcodeGoblinEntryBargon *_opcodesGoblinBargon; - static const int _goblinFuncLookUp[][2]; - - virtual void setupOpcodes(); - virtual void executeDrawOpcode(byte i); - virtual bool executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms); - virtual void executeGoblinOpcode(int i, OpGobParams ¶ms); - virtual const char *getOpcodeDrawDesc(byte i); - virtual const char *getOpcodeFuncDesc(byte i, byte j); - virtual const char *getOpcodeGoblinDesc(int i); + virtual void setupOpcodesDraw(); + virtual void setupOpcodesFunc(); + virtual void setupOpcodesGob(); void oBargon_intro0(OpGobParams ¶ms); void oBargon_intro1(OpGobParams ¶ms); @@ -456,33 +426,9 @@ public: virtual ~Inter_Fascination() {} protected: - typedef void (Inter_Fascination::*OpcodeDrawProcFascination)(); - typedef bool (Inter_Fascination::*OpcodeFuncProcFascination)(OpFuncParams &); - typedef void (Inter_Fascination::*OpcodeGoblinProcFascination)(OpGobParams &); - struct OpcodeDrawEntryFascination { - OpcodeDrawProcFascination proc; - const char *desc; - }; - struct OpcodeFuncEntryFascination { - OpcodeFuncProcFascination proc; - const char *desc; - }; - struct OpcodeGoblinEntryFascination { - OpcodeGoblinProcFascination proc; - const char *desc; - }; - const OpcodeDrawEntryFascination *_opcodesDrawFascination; - const OpcodeFuncEntryFascination *_opcodesFuncFascination; - const OpcodeGoblinEntryFascination *_opcodesGoblinFascination; - static const int _goblinFuncLookUp[][2]; - - virtual void setupOpcodes(); - virtual void executeDrawOpcode(byte i); - virtual bool executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms); - virtual void executeGoblinOpcode(int i, OpGobParams ¶ms); - virtual const char *getOpcodeDrawDesc(byte i); - virtual const char *getOpcodeFuncDesc(byte i, byte j); - virtual const char *getOpcodeGoblinDesc(int i); + virtual void setupOpcodesDraw(); + virtual void setupOpcodesFunc(); + virtual void setupOpcodesGob(); void oFascin_playProtracker(OpGobParams ¶ms); @@ -517,39 +463,12 @@ public: virtual ~Inter_v3() {} protected: - typedef void (Inter_v3::*OpcodeDrawProcV3)(); - typedef bool (Inter_v3::*OpcodeFuncProcV3)(OpFuncParams &); - typedef void (Inter_v3::*OpcodeGoblinProcV3)(OpGobParams &); - struct OpcodeDrawEntryV3 { - OpcodeDrawProcV3 proc; - const char *desc; - }; - struct OpcodeFuncEntryV3 { - OpcodeFuncProcV3 proc; - const char *desc; - }; - struct OpcodeGoblinEntryV3 { - OpcodeGoblinProcV3 proc; - const char *desc; - }; - const OpcodeDrawEntryV3 *_opcodesDrawV3; - const OpcodeFuncEntryV3 *_opcodesFuncV3; - const OpcodeGoblinEntryV3 *_opcodesGoblinV3; - static const int _goblinFuncLookUp[][2]; - - virtual void setupOpcodes(); - virtual void executeDrawOpcode(byte i); - virtual bool executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms); - virtual void executeGoblinOpcode(int i, OpGobParams ¶ms); - virtual const char *getOpcodeDrawDesc(byte i); - virtual const char *getOpcodeFuncDesc(byte i, byte j); - virtual const char *getOpcodeGoblinDesc(int i); + virtual void setupOpcodesDraw(); + virtual void setupOpcodesFunc(); + virtual void setupOpcodesGob(); bool o3_getTotTextItemPart(OpFuncParams ¶ms); bool o3_copySprite(OpFuncParams ¶ms); - bool o3_checkData(OpFuncParams ¶ms); - bool o3_readData(OpFuncParams ¶ms); - bool o3_writeData(OpFuncParams ¶ms); void o3_wobble(OpGobParams ¶ms); }; @@ -560,33 +479,9 @@ public: virtual ~Inter_v4() {} protected: - typedef void (Inter_v4::*OpcodeDrawProcV4)(); - typedef bool (Inter_v4::*OpcodeFuncProcV4)(OpFuncParams &); - typedef void (Inter_v4::*OpcodeGoblinProcV4)(OpGobParams &); - struct OpcodeDrawEntryV4 { - OpcodeDrawProcV4 proc; - const char *desc; - }; - struct OpcodeFuncEntryV4 { - OpcodeFuncProcV4 proc; - const char *desc; - }; - struct OpcodeGoblinEntryV4 { - OpcodeGoblinProcV4 proc; - const char *desc; - }; - const OpcodeDrawEntryV4 *_opcodesDrawV4; - const OpcodeFuncEntryV4 *_opcodesFuncV4; - const OpcodeGoblinEntryV4 *_opcodesGoblinV4; - static const int _goblinFuncLookUp[][2]; - - virtual void setupOpcodes(); - virtual void executeDrawOpcode(byte i); - virtual bool executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms); - virtual void executeGoblinOpcode(int i, OpGobParams ¶ms); - virtual const char *getOpcodeDrawDesc(byte i); - virtual const char *getOpcodeFuncDesc(byte i, byte j); - virtual const char *getOpcodeGoblinDesc(int i); + virtual void setupOpcodesDraw(); + virtual void setupOpcodesFunc(); + virtual void setupOpcodesGob(); void o4_initScreen(); void o4_playVmdOrMusic(); @@ -598,36 +493,12 @@ public: virtual ~Inter_v5() {} protected: - typedef void (Inter_v5::*OpcodeDrawProcV5)(); - typedef bool (Inter_v5::*OpcodeFuncProcV5)(OpFuncParams &); - typedef void (Inter_v5::*OpcodeGoblinProcV5)(OpGobParams &); - struct OpcodeDrawEntryV5 { - OpcodeDrawProcV5 proc; - const char *desc; - }; - struct OpcodeFuncEntryV5 { - OpcodeFuncProcV5 proc; - const char *desc; - }; - struct OpcodeGoblinEntryV5 { - OpcodeGoblinProcV5 proc; - const char *desc; - }; - const OpcodeDrawEntryV5 *_opcodesDrawV5; - const OpcodeFuncEntryV5 *_opcodesFuncV5; - const OpcodeGoblinEntryV5 *_opcodesGoblinV5; - static const int _goblinFuncLookUp[][2]; - - virtual void setupOpcodes(); - virtual void executeDrawOpcode(byte i); - virtual bool executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms); - virtual void executeGoblinOpcode(int i, OpGobParams ¶ms); - virtual const char *getOpcodeDrawDesc(byte i); - virtual const char *getOpcodeFuncDesc(byte i, byte j); - virtual const char *getOpcodeGoblinDesc(int i); - byte _gob_97_98_val; + virtual void setupOpcodesDraw(); + virtual void setupOpcodesFunc(); + virtual void setupOpcodesGob(); + void o5_deleteFile(); void o5_initScreen(); @@ -657,35 +528,11 @@ public: virtual ~Inter_v6() {} protected: - typedef void (Inter_v6::*OpcodeDrawProcV6)(); - typedef bool (Inter_v6::*OpcodeFuncProcV6)(OpFuncParams &); - typedef void (Inter_v6::*OpcodeGoblinProcV6)(OpGobParams &); - struct OpcodeDrawEntryV6 { - OpcodeDrawProcV6 proc; - const char *desc; - }; - struct OpcodeFuncEntryV6 { - OpcodeFuncProcV6 proc; - const char *desc; - }; - struct OpcodeGoblinEntryV6 { - OpcodeGoblinProcV6 proc; - const char *desc; - }; - const OpcodeDrawEntryV6 *_opcodesDrawV6; - const OpcodeFuncEntryV6 *_opcodesFuncV6; - const OpcodeGoblinEntryV6 *_opcodesGoblinV6; - static const int _goblinFuncLookUp[][2]; - bool _gotFirstPalette; - virtual void setupOpcodes(); - virtual void executeDrawOpcode(byte i); - virtual bool executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms); - virtual void executeGoblinOpcode(int i, OpGobParams ¶ms); - virtual const char *getOpcodeDrawDesc(byte i); - virtual const char *getOpcodeFuncDesc(byte i, byte j); - virtual const char *getOpcodeGoblinDesc(int i); + virtual void setupOpcodesDraw(); + virtual void setupOpcodesFunc(); + virtual void setupOpcodesGob(); void o6_totSub(); void o6_playVmdOrMusic(); diff --git a/engines/gob/inter_bargon.cpp b/engines/gob/inter_bargon.cpp index 54ca32fa9e..12079600c0 100644 --- a/engines/gob/inter_bargon.cpp +++ b/engines/gob/inter_bargon.cpp @@ -39,680 +39,36 @@ namespace Gob { -#define OPCODE(x) _OPCODE(Inter_Bargon, x) - -const int Inter_Bargon::_goblinFuncLookUp[][2] = { - {1, 0}, - {2, 1}, - {3, 2}, - {4, 3}, - {5, 4}, - {6, 5}, - {7, 6}, - {8, 7}, - {9, 8}, - {10, 9}, - {11, 10}, - {13, 11}, - {14, 12}, - {15, 13}, - {16, 14}, - {21, 15}, - {22, 16}, - {23, 17}, - {24, 18}, - {25, 19}, - {26, 20}, - {27, 21}, - {28, 22}, - {29, 23}, - {30, 24}, - {32, 25}, - {33, 26}, - {34, 27}, - {35, 28}, - {36, 29}, - {37, 30}, - {40, 31}, - {41, 32}, - {42, 33}, - {43, 34}, - {44, 35}, - {50, 36}, - {52, 37}, - {53, 38}, - {100, 39}, - {152, 40}, - {200, 41}, - {201, 42}, - {202, 43}, - {203, 44}, - {204, 45}, - {250, 46}, - {251, 47}, - {252, 48}, - {500, 49}, - {502, 50}, - {503, 51}, - {600, 52}, - {601, 53}, - {602, 54}, - {603, 55}, - {604, 56}, - {605, 57}, - {1000, 58}, - {1001, 59}, - {1002, 60}, - {1003, 61}, - {1004, 62}, - {1005, 63}, - {1006, 64}, - {1008, 65}, - {1009, 66}, - {1010, 67}, - {1011, 68}, - {1015, 69}, - {2005, 70} -}; +#define OPCODEVER Inter_Bargon +#define OPCODEDRAW(i, x) _opcodesDraw[i]._OPCODEDRAW(OPCODEVER, x) +#define OPCODEFUNC(i, x) _opcodesFunc[i]._OPCODEFUNC(OPCODEVER, x) +#define OPCODEGOB(i, x) _opcodesGob[i]._OPCODEGOB(OPCODEVER, x) Inter_Bargon::Inter_Bargon(GobEngine *vm) : Inter_v2(vm) { - setupOpcodes(); -} - -void Inter_Bargon::setupOpcodes() { - static const OpcodeDrawEntryBargon opcodesDraw[256] = { - /* 00 */ - OPCODE(o1_loadMult), - OPCODE(o2_playMult), - OPCODE(o1_freeMultKeys), - {0, ""}, - /* 04 */ - {0, ""}, - {0, ""}, - {0, ""}, - OPCODE(o1_initCursor), - /* 08 */ - OPCODE(o1_initCursorAnim), - OPCODE(o1_clearCursorAnim), - OPCODE(o2_setRenderFlags), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - OPCODE(o1_loadAnim), - OPCODE(o1_freeAnim), - OPCODE(o1_updateAnim), - OPCODE(o2_multSub), - /* 14 */ - OPCODE(o2_initMult), - OPCODE(o1_freeMult), - OPCODE(o1_animate), - OPCODE(o2_loadMultObject), - /* 18 */ - OPCODE(o1_getAnimLayerInfo), - OPCODE(o1_getObjAnimSize), - OPCODE(o1_loadStatic), - OPCODE(o1_freeStatic), - /* 1C */ - OPCODE(o2_renderStatic), - OPCODE(o2_loadCurLayer), - {0, ""}, - {0, ""}, - /* 20 */ - OPCODE(o2_playCDTrack), - OPCODE(o2_waitCDTrackEnd), - OPCODE(o2_stopCD), - OPCODE(o2_readLIC), - /* 24 */ - OPCODE(o2_freeLIC), - OPCODE(o2_getCDTrackPos), - {0, ""}, - {0, ""}, - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o2_loadFontToSprite), - OPCODE(o1_freeFontToSprite), - {0, ""}, - {0, ""}, - /* 34 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 38 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 3C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 40 */ - OPCODE(o2_totSub), - OPCODE(o2_switchTotSub), - OPCODE(o2_pushVars), - OPCODE(o2_popVars), - /* 44 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 48 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 4C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 50 */ - OPCODE(o2_loadMapObjects), - OPCODE(o2_freeGoblins), - OPCODE(o2_moveGoblin), - OPCODE(o2_writeGoblinPos), - /* 54 */ - OPCODE(o2_stopGoblin), - OPCODE(o2_setGoblinState), - OPCODE(o2_placeGoblin), - {0, ""}, - /* 58 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 5C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 60 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 64 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 68 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 6C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 70 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 74 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 78 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 7C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 80 */ - OPCODE(o2_initScreen), - OPCODE(o2_scroll), - OPCODE(o2_setScrollOffset), - OPCODE(o2_playImd), - /* 84 */ - OPCODE(o2_getImdInfo), - OPCODE(o2_openItk), - OPCODE(o2_closeItk), - OPCODE(o2_setImdFrontSurf), - /* 88 */ - OPCODE(o2_resetImdFrontSurf), - {0, ""}, - {0, ""}, - {0, ""}, - /* 8C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 90 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 94 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 98 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 9C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* AC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* BC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* CC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* DC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* EC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* FC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""} - }; - - static const OpcodeFuncEntryBargon opcodesFunc[80] = { - /* 00 */ - OPCODE(o1_callSub), - OPCODE(o1_callSub), - OPCODE(o1_printTotText), - OPCODE(o1_loadCursor), - /* 04 */ - {0, ""}, - OPCODE(o1_switch), - OPCODE(o1_repeatUntil), - OPCODE(o1_whileDo), - /* 08 */ - OPCODE(o1_if), - OPCODE(o2_assign), - OPCODE(o1_loadSpriteToPos), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - {0, ""}, - OPCODE(o2_printText), - OPCODE(o1_loadTot), - OPCODE(o1_palLoad), - /* 14 */ - OPCODE(o1_keyFunc), - OPCODE(o1_capturePush), - OPCODE(o1_capturePop), - OPCODE(o2_animPalInit), - /* 18 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 1C */ - {0, ""}, - {0, ""}, - OPCODE(o1_drawOperations), - OPCODE(o1_setcmdCount), - /* 20 */ - OPCODE(o1_return), - OPCODE(o1_renewTimeInVars), - OPCODE(o1_speakerOn), - OPCODE(o1_speakerOff), - /* 24 */ - OPCODE(o1_putPixel), - OPCODE(o2_goblinFunc), - OPCODE(o1_createSprite), - OPCODE(o1_freeSprite), - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o1_returnTo), - OPCODE(o1_loadSpriteContent), - OPCODE(o1_copySprite), - OPCODE(o1_fillRect), - /* 34 */ - OPCODE(o1_drawLine), - OPCODE(o1_strToLong), - OPCODE(o1_invalidate), - OPCODE(o1_setBackDelta), - /* 38 */ - OPCODE(o1_playSound), - OPCODE(o2_stopSound), - OPCODE(o2_loadSound), - OPCODE(o1_freeSoundSlot), - /* 3C */ - OPCODE(o1_waitEndPlay), - OPCODE(o1_playComposition), - OPCODE(o2_getFreeMem), - OPCODE(o2_checkData), - /* 40 */ - {0, ""}, - OPCODE(o1_prepareStr), - OPCODE(o1_insertStr), - OPCODE(o1_cutStr), - /* 44 */ - OPCODE(o1_strstr), - OPCODE(o1_istrlen), - OPCODE(o1_setMousePos), - OPCODE(o1_setFrameRate), - /* 48 */ - OPCODE(o1_animatePalette), - OPCODE(o1_animateCursor), - OPCODE(o1_blitCursor), - OPCODE(o1_loadFont), - /* 4C */ - OPCODE(o1_freeFont), - OPCODE(o2_readData), - OPCODE(o2_writeData), - OPCODE(o1_manageDataFile), - }; - - static const OpcodeGoblinEntryBargon opcodesGoblin[71] = { - /* 00 */ - OPCODE(oBargon_intro0), - OPCODE(oBargon_intro1), - OPCODE(oBargon_intro2), - OPCODE(oBargon_intro3), - /* 04 */ - OPCODE(oBargon_intro4), - OPCODE(oBargon_intro5), - OPCODE(oBargon_intro6), - OPCODE(oBargon_intro7), - /* 08 */ - OPCODE(oBargon_intro8), - OPCODE(oBargon_intro9), - OPCODE(o_gobNOP), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 14 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 18 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 1C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 20 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 24 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 34 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 38 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 3C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 40 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 44 */ - {0, ""}, - {0, ""}, - {0, ""}, - }; - - _opcodesDrawBargon = opcodesDraw; - _opcodesFuncBargon = opcodesFunc; - _opcodesGoblinBargon = opcodesGoblin; -} - -void Inter_Bargon::executeDrawOpcode(byte i) { - debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)", - i, i, getOpcodeDrawDesc(i)); - - OpcodeDrawProcBargon op = _opcodesDrawBargon[i].proc; - - if (op == 0) - warning("unimplemented opcodeDraw: %d", i); - else - (this->*op) (); -} - -bool Inter_Bargon::executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms) { - debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s)", - i, j, i, j, getOpcodeFuncDesc(i, j)); - - if ((i > 4) || (j > 15)) { - warning("unimplemented opcodeFunc: %d.%d", i, j); - return false; - } - - OpcodeFuncProcBargon op = _opcodesFuncBargon[i*16 + j].proc; - - if (op == 0) - warning("unimplemented opcodeFunc: %d.%d", i, j); - else - return (this->*op) (params); - - return false; } -void Inter_Bargon::executeGoblinOpcode(int i, OpGobParams ¶ms) { - debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)", - i, i, getOpcodeGoblinDesc(i)); - - OpcodeGoblinProcBargon op = 0; - - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) { - op = _opcodesGoblinBargon[_goblinFuncLookUp[j][1]].proc; - break; - } - - if (op == 0) { - int16 val; - - _vm->_global->_inter_execPtr -= 2; - val = load16(); - _vm->_global->_inter_execPtr += val << 1; - warning("unimplemented opcodeGob: %d", i); - } else - (this->*op) (params); +void Inter_Bargon::setupOpcodesDraw() { + Inter_v2::setupOpcodesDraw(); } -const char *Inter_Bargon::getOpcodeDrawDesc(byte i) { - return _opcodesDrawBargon[i].desc; +void Inter_Bargon::setupOpcodesFunc() { + Inter_v2::setupOpcodesFunc(); } -const char *Inter_Bargon::getOpcodeFuncDesc(byte i, byte j) { - if ((i > 4) || (j > 15)) - return ""; +void Inter_Bargon::setupOpcodesGob() { + OPCODEGOB( 1, oBargon_intro0); + OPCODEGOB( 2, oBargon_intro1); + OPCODEGOB( 3, oBargon_intro2); + OPCODEGOB( 4, oBargon_intro3); - return _opcodesFuncBargon[i*16 + j].desc; -} + OPCODEGOB( 5, oBargon_intro4); + OPCODEGOB( 6, oBargon_intro5); + OPCODEGOB( 7, oBargon_intro6); + OPCODEGOB( 8, oBargon_intro7); -const char *Inter_Bargon::getOpcodeGoblinDesc(int i) { - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) - return _opcodesGoblinBargon[_goblinFuncLookUp[j][1]].desc; - return ""; + OPCODEGOB( 9, oBargon_intro8); + OPCODEGOB(10, oBargon_intro9); + OPCODEGOB(11, o_gobNOP); } void Inter_Bargon::oBargon_intro0(OpGobParams ¶ms) { diff --git a/engines/gob/inter_fascin.cpp b/engines/gob/inter_fascin.cpp index bd0b0a94c6..3c4713f9eb 100644 --- a/engines/gob/inter_fascin.cpp +++ b/engines/gob/inter_fascin.cpp @@ -31,8 +31,8 @@ #include "gob/util.h" #include "gob/dataio.h" #include "gob/draw.h" -#include "gob/parse.h" #include "gob/game.h" +#include "gob/script.h" #include "gob/palanim.h" #include "gob/video.h" #include "gob/videoplayer.h" @@ -40,494 +40,73 @@ namespace Gob { -#define OPCODE(x) _OPCODE(Inter_Fascination, x) - -const int Inter_Fascination::_goblinFuncLookUp[][2] = { - {1, 0}, - {2, 1}, - {3, 2}, - {4, 3}, - {5, 4}, - {6, 5}, - {7, 6}, - {8, 7}, - {9, 8}, - {10, 9}, - {11, 10}, - {12, 11}, - {1000, 12}, - {1001, 13}, - {1002, 14} -}; +#define OPCODEVER Inter_Fascination +#define OPCODEDRAW(i, x) _opcodesDraw[i]._OPCODEDRAW(OPCODEVER, x) +#define OPCODEFUNC(i, x) _opcodesFunc[i]._OPCODEFUNC(OPCODEVER, x) +#define OPCODEGOB(i, x) _opcodesGob[i]._OPCODEGOB(OPCODEVER, x) Inter_Fascination::Inter_Fascination(GobEngine *vm) : Inter_v2(vm) { - setupOpcodes(); } -void Inter_Fascination::setupOpcodes() { - static const OpcodeDrawEntryFascination opcodesDraw[256] = { - /* 00 */ - OPCODE(o1_loadMult), - OPCODE(o2_playMult), - OPCODE(o1_freeMultKeys), - OPCODE(oFascin_cdUnknown3), - /* 04 */ - OPCODE(oFascin_cdUnknown4), - OPCODE(oFascin_cdUnknown5), - OPCODE(oFascin_cdUnknown6), - OPCODE(o1_initCursor), - /* 08 */ - OPCODE(o1_initCursorAnim), - OPCODE(o1_clearCursorAnim), - OPCODE(oFascin_setRenderFlags), - OPCODE(oFascin_cdUnknown11), - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - OPCODE(o1_loadAnim), - OPCODE(o1_freeAnim), - OPCODE(o1_updateAnim), - OPCODE(o2_multSub), - /* 14 */ - OPCODE(o2_initMult), - OPCODE(o1_freeMult), - OPCODE(o1_animate), - OPCODE(o2_loadMultObject), - /* 18 */ - OPCODE(o1_getAnimLayerInfo), - OPCODE(o1_getObjAnimSize), - OPCODE(o1_loadStatic), - OPCODE(o1_freeStatic), - /* 1C */ - OPCODE(o2_renderStatic), - OPCODE(o2_loadCurLayer), - {0, ""}, - {0, ""}, - /* 20 */ - OPCODE(o2_playCDTrack), - OPCODE(o2_waitCDTrackEnd), - OPCODE(o2_stopCD), - OPCODE(o2_readLIC), - /* 24 */ - OPCODE(o2_freeLIC), - OPCODE(o2_getCDTrackPos), - {0, ""}, - {0, ""}, - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o2_loadFontToSprite), - OPCODE(o1_freeFontToSprite), - {0, ""}, - {0, ""}, - /* 34 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 38 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 3C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 40 */ - OPCODE(o2_totSub), - OPCODE(o2_switchTotSub), - OPCODE(o2_pushVars), - OPCODE(o2_popVars), - /* 44 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 48 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 4C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 50 */ - {0, ""},//OPCODE(o2_loadMapObjects), - {0, ""},//OPCODE(o2_freeGoblins), - {0, ""},//OPCODE(o2_moveGoblin), - {0, ""},//OPCODE(o2_writeGoblinPos), - /* 54 */ - {0, ""},//OPCODE(o2_stopGoblin), - {0, ""},//OPCODE(o2_setGoblinState), - {0, ""},//OPCODE(o2_placeGoblin), - {0, ""}, - /* 58 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 5C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 60 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 64 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 68 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 6C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 70 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 74 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 78 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 7C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 80 */ - {0, ""},//OPCODE(o2_initScreen), - {0, ""},//OPCODE(o2_scroll), - {0, ""},//OPCODE(o2_setScrollOffset), - {0, ""},//OPCODE(o2_playImd), - /* 84 */ - {0, ""},//OPCODE(o2_getImdInfo), - {0, ""},//OPCODE(o2_openItk), - {0, ""},//OPCODE(o2_closeItk), - {0, ""},//OPCODE(o2_setImdFrontSurf), - /* 88 */ - {0, ""},//OPCODE(o2_resetImdFrontSurf), - {0, ""}, - {0, ""}, - {0, ""}, - /* 8C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 90 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 94 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 98 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 9C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* AC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* BC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* CC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* DC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* EC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* FC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""} - }; - - static const OpcodeFuncEntryFascination opcodesFunc[80] = { - /* 00 */ - OPCODE(o1_callSub), - OPCODE(o1_callSub), - OPCODE(o1_printTotText), - OPCODE(o1_loadCursor), - /* 04 */ - {0, ""}, - OPCODE(o1_switch), - OPCODE(o1_repeatUntil), - OPCODE(o1_whileDo), - /* 08 */ - OPCODE(o1_if), - OPCODE(o1_assign), - OPCODE(o1_loadSpriteToPos), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - {0, ""}, - OPCODE(o2_printText), - OPCODE(o1_loadTot), - OPCODE(o1_palLoad), - /* 14 */ - OPCODE(o1_keyFunc), - OPCODE(o1_capturePush), - OPCODE(o1_capturePop), - OPCODE(o1_animPalInit), - /* 18 */ - OPCODE(o2_addCollision), - OPCODE(o2_freeCollision), - {0, ""}, - {0, ""}, - /* 1C */ - {0, ""}, - {0, ""}, - OPCODE(o1_drawOperations), - OPCODE(o1_setcmdCount), - /* 20 */ - OPCODE(o1_return), - OPCODE(o1_renewTimeInVars), - OPCODE(o1_speakerOn), - OPCODE(o1_speakerOff), - /* 24 */ - OPCODE(o1_putPixel), - OPCODE(o2_goblinFunc), - OPCODE(o1_createSprite), - OPCODE(o1_freeSprite), - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o1_returnTo), - OPCODE(o1_loadSpriteContent), - OPCODE(o1_copySprite), - OPCODE(o1_fillRect), - /* 34 */ - OPCODE(o1_drawLine), - OPCODE(o1_strToLong), - OPCODE(o1_invalidate), - OPCODE(o1_setBackDelta), - /* 38 */ - OPCODE(o1_playSound), - OPCODE(o2_stopSound), - OPCODE(o2_loadSound), - OPCODE(o1_freeSoundSlot), - /* 3C */ - OPCODE(o1_waitEndPlay), - OPCODE(o1_playComposition), - OPCODE(o2_getFreeMem), - OPCODE(o2_checkData), - /* 40 */ - {0, ""}, - OPCODE(o1_prepareStr), - OPCODE(o1_insertStr), - OPCODE(o1_cutStr), - /* 44 */ - OPCODE(o1_strstr), - OPCODE(o1_istrlen), - OPCODE(o1_setMousePos), - OPCODE(o1_setFrameRate), - /* 48 */ - OPCODE(o1_animatePalette), - OPCODE(o1_animateCursor), - OPCODE(o1_blitCursor), - OPCODE(o1_loadFont), - /* 4C */ - OPCODE(o1_freeFont), - OPCODE(o2_readData), - OPCODE(o2_writeData), - OPCODE(o1_manageDataFile), - }; - - static const OpcodeGoblinEntryFascination opcodesGoblin[15] = { - /* 00 */ - OPCODE(oFascin_geUnknown0), - OPCODE(oFascin_geUnknown1), - OPCODE(oFascin_geUnknown2), - OPCODE(oFascin_geUnknown3), - /* 04 */ - OPCODE(oFascin_geUnknown4), - OPCODE(oFascin_geUnknown5), - OPCODE(oFascin_geUnknown6), - OPCODE(oFascin_geUnknown7), - /* 08 */ - OPCODE(oFascin_geUnknown8), - OPCODE(oFascin_geUnknown9), - OPCODE(oFascin_geUnknown10), - OPCODE(oFascin_geUnknown11), - /* 0C */ - OPCODE(oFascin_geUnknown1000), - OPCODE(oFascin_geUnknown1001), //protrackerPlay doesn't play correctly "mod.extasy" - OPCODE(oFascin_geUnknown1002), //to be replaced by o2_stopProtracker when protrackerPlay is fixed - }; - - _opcodesDrawFascination = opcodesDraw; - _opcodesFuncFascination = opcodesFunc; - _opcodesGoblinFascination = opcodesGoblin; +void Inter_Fascination::setupOpcodesDraw() { + Inter_v2::setupOpcodesDraw(); + + OPCODEDRAW(0x03, oFascin_cdUnknown3); + + OPCODEDRAW(0x04, oFascin_cdUnknown4); + OPCODEDRAW(0x05, oFascin_cdUnknown5); + OPCODEDRAW(0x06, oFascin_cdUnknown6); + + OPCODEDRAW(0x0A, oFascin_setRenderFlags); + OPCODEDRAW(0x0B, oFascin_cdUnknown11); + + CLEAROPCODEDRAW(0x50); + CLEAROPCODEDRAW(0x51); + CLEAROPCODEDRAW(0x52); + CLEAROPCODEDRAW(0x53); + + CLEAROPCODEDRAW(0x54); + CLEAROPCODEDRAW(0x55); + CLEAROPCODEDRAW(0x56); + + CLEAROPCODEDRAW(0x80); + CLEAROPCODEDRAW(0x81); + CLEAROPCODEDRAW(0x82); + CLEAROPCODEDRAW(0x83); + + CLEAROPCODEDRAW(0x84); + CLEAROPCODEDRAW(0x85); + CLEAROPCODEDRAW(0x86); + CLEAROPCODEDRAW(0x87); + + CLEAROPCODEDRAW(0x88); } -void Inter_Fascination::executeDrawOpcode(byte i) { - debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)", - i, i, getOpcodeDrawDesc(i)); +void Inter_Fascination::setupOpcodesFunc() { + Inter_v2::setupOpcodesFunc(); - OpcodeDrawProcFascination op = _opcodesDrawFascination[i].proc; + OPCODEFUNC(0x09, o1_assign); +} + +void Inter_Fascination::setupOpcodesGob() { + OPCODEGOB( 1, oFascin_geUnknown0); + OPCODEGOB( 2, oFascin_geUnknown1); + OPCODEGOB( 3, oFascin_geUnknown2); + OPCODEGOB( 4, oFascin_geUnknown3); + + OPCODEGOB( 5, oFascin_geUnknown4); + OPCODEGOB( 6, oFascin_geUnknown5); + OPCODEGOB( 7, oFascin_geUnknown6); + OPCODEGOB( 8, oFascin_geUnknown7); + + OPCODEGOB( 9, oFascin_geUnknown8); + OPCODEGOB( 10, oFascin_geUnknown9); + OPCODEGOB( 11, oFascin_geUnknown10); + OPCODEGOB( 12, oFascin_geUnknown11); - if (op == 0) - warning("Not yet implemented Fascination opcodeDraw: %d", i); - else - (this->*op) (); + OPCODEGOB(1000, oFascin_geUnknown1000); + OPCODEGOB(1001, oFascin_geUnknown1001); //protrackerPlay doesn't play correctly "mod.extasy" + OPCODEGOB(1002, oFascin_geUnknown1002); //to be replaced by o2_stopProtracker when protrackerPlay is fixed } void Inter_Fascination::oFascin_geUnknown0(OpGobParams ¶ms) { @@ -552,70 +131,58 @@ void Inter_Fascination::oFascin_geUnknown1(OpGobParams ¶ms) { } void Inter_Fascination::oFascin_geUnknown2(OpGobParams ¶ms) { - warning("Fascination Unknown GE Function 2"); - warning("funcLoadInstruments with parameter : 'extasy.tbr'. (Guess)"); - warning("funcLoadMusic with parameter : 'extasy.mdy'. (Guess)"); + _vm->_sound->adlibLoadTBR("extasy.tbr"); + _vm->_sound->adlibLoadMDY("extasy.mdy"); } void Inter_Fascination::oFascin_geUnknown3(OpGobParams ¶ms) { - warning("Fascination Unknown GE Function 3"); - warning("Verify if 'Guess music' is loaded. If yes, call funcPlayMusic. (Guess)"); + _vm->_sound->adlibPlay(); } void Inter_Fascination::oFascin_geUnknown4(OpGobParams ¶ms) { - warning("Fascination Unknown GE Function 4"); - warning("Verify if 'Guess music' is loaded. If yes, call funcStopMusic. (Guess)"); + _vm->_sound->adlibStop(); } void Inter_Fascination::oFascin_geUnknown5(OpGobParams ¶ms) { - warning("Fascination Unknown GE Function 5"); - warning("Verify if 'instruments' are loaded, If so, call mem_free"); - warning("Verify if 'Guess music' is loaded. If yes, call _cleanupMdy"); - warning("Then set _ptrTbr and _ptrMdy to 0"); + _vm->_sound->adlibUnload(); } void Inter_Fascination::oFascin_geUnknown6(OpGobParams ¶ms) { - warning("Fascination Unknown GE Function 6"); - warning("funcLoadInstruments with parameter : 'music1.tbr'. (Guess)"); - warning("funcLoadMusic with parameter : 'music1.mdy'. (Guess)"); + _vm->_sound->adlibLoadTBR("music1.tbr"); + _vm->_sound->adlibLoadMDY("music1.mdy"); } void Inter_Fascination::oFascin_geUnknown7(OpGobParams ¶ms) { - warning("Fascination Unknown GE Function 7"); - warning("funcLoadInstruments with parameter : 'music2.tbr'. (Guess)"); - warning("funcLoadMusic with parameter : 'music2.mdy'. (Guess)"); + _vm->_sound->adlibLoadTBR("music2.tbr"); + _vm->_sound->adlibLoadMDY("music2.mdy"); } void Inter_Fascination::oFascin_geUnknown8(OpGobParams ¶ms) { - warning("Fascination Unknown GE Function 8"); - warning("funcLoadInstruments with parameter : 'music3.tbr'. (Guess)"); - warning("funcLoadMusic with parameter : 'music3.mdy'. (Guess)"); + _vm->_sound->adlibLoadTBR("music3.tbr"); + _vm->_sound->adlibLoadMDY("music3.mdy"); } void Inter_Fascination::oFascin_geUnknown9(OpGobParams ¶ms) { - warning("Fascination Unknown GE Function 9"); - warning("funcLoadInstruments with parameter : 'batt1.tbr'. (Guess)"); - warning("funcLoadMusic with parameter : 'batt1.mdy'. (Guess)"); + _vm->_sound->adlibLoadTBR("batt1.tbr"); + _vm->_sound->adlibLoadMDY("batt1.mdy"); } void Inter_Fascination::oFascin_geUnknown10(OpGobParams ¶ms) { - warning("Fascination Unknown GE Function 10"); - warning("funcLoadInstruments with parameter : 'batt2.tbr'. (Guess)"); - warning("funcLoadMusic with parameter : 'batt2.mdy'. (Guess)"); + _vm->_sound->adlibLoadTBR("batt2.tbr"); + _vm->_sound->adlibLoadMDY("batt2.mdy"); } void Inter_Fascination::oFascin_geUnknown11(OpGobParams ¶ms) { - warning("Fascination Unknown GE Function 11"); - warning("funcLoadInstruments with parameter : 'batt3.tbr'. (Guess)"); - warning("funcLoadMusic with parameter : 'batt3.mdy'. (Guess)"); + _vm->_sound->adlibLoadTBR("batt3.tbr"); + _vm->_sound->adlibLoadMDY("batt3.mdy"); } void Inter_Fascination::oFascin_geUnknown1000(OpGobParams ¶ms) { - warning("Fascination Unknown GE Function 1000 - Load music ?"); + warning("Fascination Unknown GE Function 1000 - Load MOD music"); } void Inter_Fascination::oFascin_geUnknown1001(OpGobParams ¶ms) { - warning("Fascination oFascin_playProtracker - MOD not compatible, ToBeFixed"); + warning("Fascination oFascin_playProtracker - MOD not compatible (sample > 32768), To Be Fixed"); } void Inter_Fascination::oFascin_geUnknown1002(OpGobParams ¶ms) { @@ -638,15 +205,15 @@ void Inter_Fascination::oFascin_cdUnknown3() { warning("Fascination oFascin_cdUnknown3 - Variables initialisations"); - resVar = (uint16) load16(); - resVar2 = (uint16) load16(); - retVal1 = _vm->_parse->parseVarIndex(); - retVal2 = _vm->_parse->parseVarIndex(); - retVal3 = _vm->_parse->parseVarIndex(); - retVal4 = _vm->_parse->parseVarIndex(); - retVal5 = _vm->_parse->parseVarIndex(); - retVal6 = _vm->_parse->parseVarIndex(); - retVal7 = _vm->_parse->parseVarIndex(); + resVar = _vm->_game->_script->readUint16(); + resVar2 = _vm->_game->_script->readUint16(); + retVal1 = _vm->_game->_script->readVarIndex(); + retVal2 = _vm->_game->_script->readVarIndex(); + retVal3 = _vm->_game->_script->readVarIndex(); + retVal4 = _vm->_game->_script->readVarIndex(); + retVal5 = _vm->_game->_script->readVarIndex(); + retVal6 = _vm->_game->_script->readVarIndex(); + retVal7 = _vm->_game->_script->readVarIndex(); warning ("Width? :%d Height? :%d",resVar, resVar2); warning ("Fetched variables 1:%d 2:%d 3:%d 4:%d 5:%d 6:%d 7:%d", retVal1, retVal2, retVal3, retVal4, retVal5, retVal6, retVal7); } @@ -654,98 +221,37 @@ void Inter_Fascination::oFascin_cdUnknown3() { void Inter_Fascination::oFascin_cdUnknown4() { int16 expr; warning("Fascination oFascin_cdUnknown4"); - evalExpr(&expr); - warning ("evalExpr: %d, the rest is not yet implemented",expr); + _vm->_game->_script->evalExpr(&expr); + warning ("_vm->_game->_script->evalExpr: %d, the rest is not yet implemented",expr); } void Inter_Fascination::oFascin_cdUnknown5() { int16 retVal1,expr; warning("Fascination oFascin_cdUnknown5"); - evalExpr(&expr); - retVal1 = _vm->_parse->parseVarIndex(); - warning ("evalExpr: %d Variable index %d, the rest is not yet implemented",expr, retVal1); + _vm->_game->_script->evalExpr(&expr); + retVal1 = _vm->_game->_script->readVarIndex(); + warning ("_vm->_game->_script->evalExpr: %d Variable index %d, the rest is not yet implemented",expr, retVal1); } void Inter_Fascination::oFascin_cdUnknown6() { int16 retVal1,expr; warning("Fascination oFascin_cdUnknown6"); - evalExpr(&expr); - retVal1 = _vm->_parse->parseVarIndex(); - warning ("evalExpr: %d Variable index %d, the rest is not yet implemented",expr, retVal1); + _vm->_game->_script->evalExpr(&expr); + retVal1 = _vm->_game->_script->readVarIndex(); + warning ("_vm->_game->_script->evalExpr: %d Variable index %d, the rest is not yet implemented",expr, retVal1); } void Inter_Fascination::oFascin_setRenderFlags() { int16 expr; // warning("Fascination oFascin_cdUnknown10 (set render flags)"); - evalExpr(&expr); + _vm->_game->_script->evalExpr(&expr); warning("_draw_renderFlags <- %d",expr); _vm->_draw->_renderFlags = expr; } void Inter_Fascination::oFascin_cdUnknown11() { // warning("Fascination oFascin_cdUnknown11 (set variable)"); - evalExpr(0); -} - -bool Inter_Fascination::executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms) { - debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s)", - i, j, i, j, getOpcodeFuncDesc(i, j)); - - if ((i > 4) || (j > 16)) { - warning("Invalid opcodeFunc: %d.%d", i, j); - return false; - } - - OpcodeFuncProcFascination op = _opcodesFuncFascination[i*16 + j].proc; - - if (op == 0) - warning("unimplemented opcodeFunc: %d.%d", i, j); - else - return (this->*op) (params); - - return false; -} - -void Inter_Fascination::executeGoblinOpcode(int i, OpGobParams ¶ms) { - debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)", - i, i, getOpcodeGoblinDesc(i)); - - OpcodeGoblinProcFascination op = 0; - - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) { - op = _opcodesGoblinFascination[_goblinFuncLookUp[j][1]].proc; - break; - } - - if (op == 0) { - int16 val; - - _vm->_global->_inter_execPtr -= 2; - val = load16(); - _vm->_global->_inter_execPtr += val << 1; - warning("unimplemented opcodeGob: %d", i); - } else - (this->*op) (params); -} - -const char *Inter_Fascination::getOpcodeDrawDesc(byte i) { - return _opcodesDrawFascination[i].desc; -} - -const char *Inter_Fascination::getOpcodeFuncDesc(byte i, byte j) { - if ((i > 4) || (j > 15)) - return ""; - - return _opcodesFuncFascination[i*16 + j].desc; -} - -const char *Inter_Fascination::getOpcodeGoblinDesc(int i) { - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) - return _opcodesGoblinFascination[_goblinFuncLookUp[j][1]].desc; - warning("Error in getOpcodeGoblinDesc %d",i); - return ""; + _vm->_game->_script->evalExpr(0); } void Inter_Fascination::oFascin_playProtracker(OpGobParams ¶ms) { diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp index ace5a7a3be..d5d5fcad9a 100644 --- a/engines/gob/inter_v1.cpp +++ b/engines/gob/inter_v1.cpp @@ -34,692 +34,214 @@ #include "gob/dataio.h" #include "gob/draw.h" #include "gob/game.h" +#include "gob/expression.h" +#include "gob/script.h" +#include "gob/resources.h" #include "gob/goblin.h" #include "gob/inter.h" #include "gob/map.h" #include "gob/mult.h" #include "gob/palanim.h" -#include "gob/parse.h" #include "gob/scenery.h" #include "gob/video.h" #include "gob/sound/sound.h" namespace Gob { -#define OPCODE(x) _OPCODE(Inter_v1, x) - -const int Inter_v1::_goblinFuncLookUp[][2] = { - {1, 0}, - {2, 1}, - {3, 2}, - {4, 3}, - {5, 4}, - {6, 5}, - {7, 6}, - {8, 7}, - {9, 8}, - {10, 9}, - {12, 10}, - {13, 11}, - {14, 12}, - {15, 13}, - {16, 14}, - {21, 15}, - {22, 16}, - {23, 17}, - {24, 18}, - {25, 19}, - {26, 20}, - {27, 21}, - {28, 22}, - {29, 23}, - {30, 24}, - {32, 25}, - {33, 26}, - {34, 27}, - {35, 28}, - {36, 29}, - {37, 30}, - {40, 31}, - {41, 32}, - {42, 33}, - {43, 34}, - {44, 35}, - {50, 36}, - {52, 37}, - {53, 38}, - {150, 39}, - {152, 40}, - {200, 41}, - {201, 42}, - {202, 43}, - {203, 44}, - {204, 45}, - {250, 46}, - {251, 47}, - {252, 48}, - {500, 49}, - {502, 50}, - {503, 51}, - {600, 52}, - {601, 53}, - {602, 54}, - {603, 55}, - {604, 56}, - {605, 57}, - {1000, 58}, - {1001, 59}, - {1002, 60}, - {1003, 61}, - {1004, 62}, - {1005, 63}, - {1006, 64}, - {1008, 65}, - {1009, 66}, - {1010, 67}, - {1011, 68}, - {1015, 69}, - {2005, 70} -}; +#define OPCODEVER Inter_v1 +#define OPCODEDRAW(i, x) _opcodesDraw[i]._OPCODEDRAW(OPCODEVER, x) +#define OPCODEFUNC(i, x) _opcodesFunc[i]._OPCODEFUNC(OPCODEVER, x) +#define OPCODEGOB(i, x) _opcodesGob[i]._OPCODEGOB(OPCODEVER, x) Inter_v1::Inter_v1(GobEngine *vm) : Inter(vm) { - setupOpcodes(); -} - -void Inter_v1::setupOpcodes() { - static const OpcodeDrawEntryV1 opcodesDraw[256] = { - /* 00 */ - OPCODE(o1_loadMult), - OPCODE(o1_playMult), - OPCODE(o1_freeMultKeys), - {0, ""}, - /* 04 */ - {0, ""}, - {0, ""}, - {0, ""}, - OPCODE(o1_initCursor), - /* 08 */ - OPCODE(o1_initCursorAnim), - OPCODE(o1_clearCursorAnim), - OPCODE(o1_setRenderFlags), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - OPCODE(o1_loadAnim), - OPCODE(o1_freeAnim), - OPCODE(o1_updateAnim), - {0, ""}, - /* 14 */ - OPCODE(o1_initMult), - OPCODE(o1_freeMult), - OPCODE(o1_animate), - OPCODE(o1_loadMultObject), - /* 18 */ - OPCODE(o1_getAnimLayerInfo), - OPCODE(o1_getObjAnimSize), - OPCODE(o1_loadStatic), - OPCODE(o1_freeStatic), - /* 1C */ - OPCODE(o1_renderStatic), - OPCODE(o1_loadCurLayer), - {0, ""}, - {0, ""}, - /* 20 */ - OPCODE(o1_playCDTrack), - OPCODE(o1_getCDTrackPos), - OPCODE(o1_stopCD), - {0, ""}, - /* 24 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o1_loadFontToSprite), - OPCODE(o1_freeFontToSprite), - {0, ""}, - {0, ""}, - /* 34 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 38 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 3C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 40 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 44 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 48 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 4C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 50 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 54 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 58 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 5C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 60 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 64 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 68 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 6C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 70 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 74 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 78 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 7C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 80 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 84 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 88 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 8C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 90 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 94 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 98 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 9C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* AC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* BC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* CC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* DC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* EC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* FC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""} - }; - - static const OpcodeFuncEntryV1 opcodesFunc[80] = { - /* 00 */ - OPCODE(o1_callSub), - OPCODE(o1_callSub), - OPCODE(o1_printTotText), - OPCODE(o1_loadCursor), - /* 04 */ - {0, ""}, - OPCODE(o1_switch), - OPCODE(o1_repeatUntil), - OPCODE(o1_whileDo), - /* 08 */ - OPCODE(o1_if), - OPCODE(o1_assign), - OPCODE(o1_loadSpriteToPos), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - {0, ""}, - OPCODE(o1_printText), - OPCODE(o1_loadTot), - OPCODE(o1_palLoad), - /* 14 */ - OPCODE(o1_keyFunc), - OPCODE(o1_capturePush), - OPCODE(o1_capturePop), - OPCODE(o1_animPalInit), - /* 18 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 1C */ - {0, ""}, - {0, ""}, - OPCODE(o1_drawOperations), - OPCODE(o1_setcmdCount), - /* 20 */ - OPCODE(o1_return), - OPCODE(o1_renewTimeInVars), - OPCODE(o1_speakerOn), - OPCODE(o1_speakerOff), - /* 24 */ - OPCODE(o1_putPixel), - OPCODE(o1_goblinFunc), - OPCODE(o1_createSprite), - OPCODE(o1_freeSprite), - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o1_returnTo), - OPCODE(o1_loadSpriteContent), - OPCODE(o1_copySprite), - OPCODE(o1_fillRect), - /* 34 */ - OPCODE(o1_drawLine), - OPCODE(o1_strToLong), - OPCODE(o1_invalidate), - OPCODE(o1_setBackDelta), - /* 38 */ - OPCODE(o1_playSound), - OPCODE(o1_stopSound), - OPCODE(o1_loadSound), - OPCODE(o1_freeSoundSlot), - /* 3C */ - OPCODE(o1_waitEndPlay), - OPCODE(o1_playComposition), - OPCODE(o1_getFreeMem), - OPCODE(o1_checkData), - /* 40 */ - {0, ""}, - OPCODE(o1_prepareStr), - OPCODE(o1_insertStr), - OPCODE(o1_cutStr), - /* 44 */ - OPCODE(o1_strstr), - OPCODE(o1_istrlen), - OPCODE(o1_setMousePos), - OPCODE(o1_setFrameRate), - /* 48 */ - OPCODE(o1_animatePalette), - OPCODE(o1_animateCursor), - OPCODE(o1_blitCursor), - OPCODE(o1_loadFont), - /* 4C */ - OPCODE(o1_freeFont), - OPCODE(o1_readData), - OPCODE(o1_writeData), - OPCODE(o1_manageDataFile), - }; - - static const OpcodeGoblinEntryV1 opcodesGoblin[71] = { - /* 00 */ - OPCODE(o1_setState), - OPCODE(o1_setCurFrame), - OPCODE(o1_setNextState), - OPCODE(o1_setMultState), - /* 04 */ - OPCODE(o1_setOrder), - OPCODE(o1_setActionStartState), - OPCODE(o1_setCurLookDir), - OPCODE(o1_setType), - /* 08 */ - OPCODE(o1_setNoTick), - OPCODE(o1_setPickable), - OPCODE(o1_setXPos), - OPCODE(o1_setYPos), - /* 0C */ - OPCODE(o1_setDoAnim), - OPCODE(o1_setRelaxTime), - OPCODE(o1_setMaxTick), - OPCODE(o1_getState), - /* 10 */ - OPCODE(o1_getCurFrame), - OPCODE(o1_getNextState), - OPCODE(o1_getMultState), - OPCODE(o1_getOrder), - /* 14 */ - OPCODE(o1_getActionStartState), - OPCODE(o1_getCurLookDir), - OPCODE(o1_getType), - OPCODE(o1_getNoTick), - /* 18 */ - OPCODE(o1_getPickable), - OPCODE(o1_getObjMaxFrame), - OPCODE(o1_getXPos), - OPCODE(o1_getYPos), - /* 1C */ - OPCODE(o1_getDoAnim), - OPCODE(o1_getRelaxTime), - OPCODE(o1_getMaxTick), - OPCODE(o1_manipulateMap), - /* 20 */ - OPCODE(o1_getItem), - OPCODE(o1_manipulateMapIndirect), - OPCODE(o1_getItemIndirect), - OPCODE(o1_setPassMap), - /* 24 */ - OPCODE(o1_setGoblinPosH), - OPCODE(o1_getGoblinPosXH), - OPCODE(o1_getGoblinPosYH), - OPCODE(o1_setGoblinMultState), - /* 28 */ - OPCODE(o1_setGoblinUnk14), - OPCODE(o1_setItemIdInPocket), - OPCODE(o1_setItemIndInPocket), - OPCODE(o1_getItemIdInPocket), - /* 2C */ - OPCODE(o1_getItemIndInPocket), - OPCODE(o1_setItemPos), - OPCODE(o1_setGoblinPos), - OPCODE(o1_setGoblinState), - /* 30 */ - OPCODE(o1_setGoblinStateRedraw), - OPCODE(o1_decRelaxTime), - OPCODE(o1_getGoblinPosX), - OPCODE(o1_getGoblinPosY), - /* 34 */ - OPCODE(o1_clearPathExistence), - OPCODE(o1_setGoblinVisible), - OPCODE(o1_setGoblinInvisible), - OPCODE(o1_getObjectIntersect), - /* 38 */ - OPCODE(o1_getGoblinIntersect), - OPCODE(o1_setItemPos), - OPCODE(o1_loadObjects), - OPCODE(o1_freeObjects), - /* 3C */ - OPCODE(o1_animateObjects), - OPCODE(o1_drawObjects), - OPCODE(o1_loadMap), - OPCODE(o1_moveGoblin), - /* 40 */ - OPCODE(o1_switchGoblin), - OPCODE(o1_loadGoblin), - OPCODE(o1_writeTreatItem), - OPCODE(o1_moveGoblin0), - /* 44 */ - OPCODE(o1_setGoblinTarget), - OPCODE(o1_setGoblinObjectsPos), - OPCODE(o1_initGoblin) - }; - - _opcodesDrawV1 = opcodesDraw; - _opcodesFuncV1 = opcodesFunc; - _opcodesGoblinV1 = opcodesGoblin; -} - -void Inter_v1::executeDrawOpcode(byte i) { - debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)", - i, i, getOpcodeDrawDesc(i)); - - OpcodeDrawProcV1 op = _opcodesDrawV1[i].proc; - - if (op == 0) - warning("unimplemented opcodeDraw: %d", i); - else - (this->*op) (); -} - -bool Inter_v1::executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms) { - debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s)", - i, j, i, j, getOpcodeFuncDesc(i, j)); - - if ((i > 4) || (j > 15)) { - warning("unimplemented opcodeFunc: %d.%d", i, j); - return false; - } - - OpcodeFuncProcV1 op = _opcodesFuncV1[i*16 + j].proc; - - if (op == 0) - warning("unimplemented opcodeFunc: %d.%d", i, j); - else - return (this->*op) (params); - return false; } -void Inter_v1::executeGoblinOpcode(int i, OpGobParams ¶ms) { - debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)", - i, i, getOpcodeGoblinDesc(i)); +void Inter_v1::setupOpcodesDraw() { + OPCODEDRAW(0x00, o1_loadMult); + OPCODEDRAW(0x01, o1_playMult); + OPCODEDRAW(0x02, o1_freeMultKeys); - OpcodeGoblinProcV1 op = 0; + OPCODEDRAW(0x07, o1_initCursor); + + OPCODEDRAW(0x08, o1_initCursorAnim); + OPCODEDRAW(0x09, o1_clearCursorAnim); + OPCODEDRAW(0x0A, o1_setRenderFlags); - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) { - op = _opcodesGoblinV1[_goblinFuncLookUp[j][1]].proc; - break; - } - - if (op == 0) { - warning("unimplemented opcodeGoblin: %d", i); - _vm->_global->_inter_execPtr -= 2; - int16 cmd = load16(); - _vm->_global->_inter_execPtr += cmd * 2; - } else - (this->*op) (params); -} - -const char *Inter_v1::getOpcodeDrawDesc(byte i) { - return _opcodesDrawV1[i].desc; -} - -const char *Inter_v1::getOpcodeFuncDesc(byte i, byte j) { - if ((i > 4) || (j > 15)) - return ""; - - return _opcodesFuncV1[i*16 + j].desc; -} - -const char *Inter_v1::getOpcodeGoblinDesc(int i) { - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) - return _opcodesGoblinV1[_goblinFuncLookUp[j][1]].desc; - return ""; -} - -void Inter_v1::checkSwitchTable(byte **ppExec) { + OPCODEDRAW(0x10, o1_loadAnim); + OPCODEDRAW(0x11, o1_freeAnim); + OPCODEDRAW(0x12, o1_updateAnim); + + OPCODEDRAW(0x14, o1_initMult); + OPCODEDRAW(0x15, o1_freeMult); + OPCODEDRAW(0x16, o1_animate); + OPCODEDRAW(0x17, o1_loadMultObject); + + OPCODEDRAW(0x18, o1_getAnimLayerInfo); + OPCODEDRAW(0x19, o1_getObjAnimSize); + OPCODEDRAW(0x1A, o1_loadStatic); + OPCODEDRAW(0x1B, o1_freeStatic); + + OPCODEDRAW(0x1C, o1_renderStatic); + OPCODEDRAW(0x1D, o1_loadCurLayer); + + OPCODEDRAW(0x20, o1_playCDTrack); + OPCODEDRAW(0x21, o1_getCDTrackPos); + OPCODEDRAW(0x22, o1_stopCD); + + OPCODEDRAW(0x30, o1_loadFontToSprite); + OPCODEDRAW(0x31, o1_freeFontToSprite); +} + +void Inter_v1::setupOpcodesFunc() { + OPCODEFUNC(0x00, o1_callSub); + OPCODEFUNC(0x01, o1_callSub); + OPCODEFUNC(0x02, o1_printTotText); + OPCODEFUNC(0x03, o1_loadCursor); + + OPCODEFUNC(0x05, o1_switch); + OPCODEFUNC(0x06, o1_repeatUntil); + OPCODEFUNC(0x07, o1_whileDo); + + OPCODEFUNC(0x08, o1_if); + OPCODEFUNC(0x09, o1_assign); + OPCODEFUNC(0x0A, o1_loadSpriteToPos); + OPCODEFUNC(0x11, o1_printText); + OPCODEFUNC(0x12, o1_loadTot); + OPCODEFUNC(0x13, o1_palLoad); + + OPCODEFUNC(0x14, o1_keyFunc); + OPCODEFUNC(0x15, o1_capturePush); + OPCODEFUNC(0x16, o1_capturePop); + OPCODEFUNC(0x17, o1_animPalInit); + + OPCODEFUNC(0x1E, o1_drawOperations); + OPCODEFUNC(0x1F, o1_setcmdCount); + + OPCODEFUNC(0x20, o1_return); + OPCODEFUNC(0x21, o1_renewTimeInVars); + OPCODEFUNC(0x22, o1_speakerOn); + OPCODEFUNC(0x23, o1_speakerOff); + + OPCODEFUNC(0x24, o1_putPixel); + OPCODEFUNC(0x25, o1_goblinFunc); + OPCODEFUNC(0x26, o1_createSprite); + OPCODEFUNC(0x27, o1_freeSprite); + + OPCODEFUNC(0x30, o1_returnTo); + OPCODEFUNC(0x31, o1_loadSpriteContent); + OPCODEFUNC(0x32, o1_copySprite); + OPCODEFUNC(0x33, o1_fillRect); + + OPCODEFUNC(0x34, o1_drawLine); + OPCODEFUNC(0x35, o1_strToLong); + OPCODEFUNC(0x36, o1_invalidate); + OPCODEFUNC(0x37, o1_setBackDelta); + + OPCODEFUNC(0x38, o1_playSound); + OPCODEFUNC(0x39, o1_stopSound); + OPCODEFUNC(0x3A, o1_loadSound); + OPCODEFUNC(0x3B, o1_freeSoundSlot); + + OPCODEFUNC(0x3C, o1_waitEndPlay); + OPCODEFUNC(0x3D, o1_playComposition); + OPCODEFUNC(0x3E, o1_getFreeMem); + OPCODEFUNC(0x3F, o1_checkData); + + OPCODEFUNC(0x41, o1_prepareStr); + OPCODEFUNC(0x42, o1_insertStr); + OPCODEFUNC(0x43, o1_cutStr); + + OPCODEFUNC(0x44, o1_strstr); + OPCODEFUNC(0x45, o1_istrlen); + OPCODEFUNC(0x46, o1_setMousePos); + OPCODEFUNC(0x47, o1_setFrameRate); + + OPCODEFUNC(0x48, o1_animatePalette); + OPCODEFUNC(0x49, o1_animateCursor); + OPCODEFUNC(0x4A, o1_blitCursor); + OPCODEFUNC(0x4B, o1_loadFont); + + OPCODEFUNC(0x4C, o1_freeFont); + OPCODEFUNC(0x4D, o1_readData); + OPCODEFUNC(0x4E, o1_writeData); + OPCODEFUNC(0x4F, o1_manageDataFile); +} + +void Inter_v1::setupOpcodesGob() { + OPCODEGOB( 1, o1_setState); + OPCODEGOB( 2, o1_setCurFrame); + OPCODEGOB( 3, o1_setNextState); + OPCODEGOB( 4, o1_setMultState); + OPCODEGOB( 5, o1_setOrder); + OPCODEGOB( 6, o1_setActionStartState); + OPCODEGOB( 7, o1_setCurLookDir); + OPCODEGOB( 8, o1_setType); + OPCODEGOB( 9, o1_setNoTick); + OPCODEGOB( 10, o1_setPickable); + OPCODEGOB( 12, o1_setXPos); + OPCODEGOB( 13, o1_setYPos); + OPCODEGOB( 14, o1_setDoAnim); + OPCODEGOB( 15, o1_setRelaxTime); + OPCODEGOB( 16, o1_setMaxTick); + OPCODEGOB( 21, o1_getState); + OPCODEGOB( 22, o1_getCurFrame); + OPCODEGOB( 23, o1_getNextState); + OPCODEGOB( 24, o1_getMultState); + OPCODEGOB( 25, o1_getOrder); + OPCODEGOB( 26, o1_getActionStartState); + OPCODEGOB( 27, o1_getCurLookDir); + OPCODEGOB( 28, o1_getType); + OPCODEGOB( 29, o1_getNoTick); + OPCODEGOB( 30, o1_getPickable); + OPCODEGOB( 32, o1_getObjMaxFrame); + OPCODEGOB( 33, o1_getXPos); + OPCODEGOB( 34, o1_getYPos); + OPCODEGOB( 35, o1_getDoAnim); + OPCODEGOB( 36, o1_getRelaxTime); + OPCODEGOB( 37, o1_getMaxTick); + OPCODEGOB( 40, o1_manipulateMap); + OPCODEGOB( 41, o1_getItem); + OPCODEGOB( 42, o1_manipulateMapIndirect); + OPCODEGOB( 43, o1_getItemIndirect); + OPCODEGOB( 44, o1_setPassMap); + OPCODEGOB( 50, o1_setGoblinPosH); + OPCODEGOB( 52, o1_getGoblinPosXH); + OPCODEGOB( 53, o1_getGoblinPosYH); + OPCODEGOB( 150, o1_setGoblinMultState); + OPCODEGOB( 152, o1_setGoblinUnk14); + OPCODEGOB( 200, o1_setItemIdInPocket); + OPCODEGOB( 201, o1_setItemIndInPocket); + OPCODEGOB( 202, o1_getItemIdInPocket); + OPCODEGOB( 203, o1_getItemIndInPocket); + OPCODEGOB( 204, o1_setItemPos); + OPCODEGOB( 250, o1_setGoblinPos); + OPCODEGOB( 251, o1_setGoblinState); + OPCODEGOB( 252, o1_setGoblinStateRedraw); + OPCODEGOB( 500, o1_decRelaxTime); + OPCODEGOB( 502, o1_getGoblinPosX); + OPCODEGOB( 503, o1_getGoblinPosY); + OPCODEGOB( 600, o1_clearPathExistence); + OPCODEGOB( 601, o1_setGoblinVisible); + OPCODEGOB( 602, o1_setGoblinInvisible); + OPCODEGOB( 603, o1_getObjectIntersect); + OPCODEGOB( 604, o1_getGoblinIntersect); + OPCODEGOB( 605, o1_setItemPos); + OPCODEGOB(1000, o1_loadObjects); + OPCODEGOB(1001, o1_freeObjects); + OPCODEGOB(1002, o1_animateObjects); + OPCODEGOB(1003, o1_drawObjects); + OPCODEGOB(1004, o1_loadMap); + OPCODEGOB(1005, o1_moveGoblin); + OPCODEGOB(1006, o1_switchGoblin); + OPCODEGOB(1008, o1_loadGoblin); + OPCODEGOB(1009, o1_writeTreatItem); + OPCODEGOB(1010, o1_moveGoblin0); + OPCODEGOB(1011, o1_setGoblinTarget); + OPCODEGOB(1015, o1_setGoblinObjectsPos); + OPCODEGOB(2005, o1_initGoblin); +} + +void Inter_v1::checkSwitchTable(uint32 &offset) { int16 len; int32 value; bool found; @@ -727,56 +249,54 @@ void Inter_v1::checkSwitchTable(byte **ppExec) { found = false; notFound = true; - *ppExec = 0; - value = VAR_OFFSET(_vm->_parse->parseVarIndex()); + offset = 0; + value = VAR_OFFSET(_vm->_game->_script->readVarIndex()); - len = (int8) *_vm->_global->_inter_execPtr++; + len = _vm->_game->_script->readInt8(); while (len != -5) { for (int i = 0; i < len; i++) { - evalExpr(0); + _vm->_game->_script->evalExpr(0); if (_terminate) return; - if (_vm->_global->_inter_resVal == value) { + if (_vm->_game->_script->getResultInt() == value) { found = true; notFound = false; } } if (found) - *ppExec = _vm->_global->_inter_execPtr; + offset = _vm->_game->_script->pos(); - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2; + _vm->_game->_script->skip(_vm->_game->_script->peekUint16(2) + 2); found = false; - len = (int8) *_vm->_global->_inter_execPtr++; + len = _vm->_game->_script->readInt8(); } - if ((*_vm->_global->_inter_execPtr >> 4) != 4) + if ((_vm->_game->_script->peekByte() >> 4) != 4) return; - _vm->_global->_inter_execPtr++; + _vm->_game->_script->skip(1); if (notFound) - *ppExec = _vm->_global->_inter_execPtr; + offset = _vm->_game->_script->pos(); - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2; + _vm->_game->_script->skip(_vm->_game->_script->peekUint16(2) + 2); } void Inter_v1::o1_loadMult() { - _vm->_mult->loadMult(load16()); + _vm->_mult->loadMult(_vm->_game->_script->readInt16()); } void Inter_v1::o1_playMult() { int16 checkEscape; - checkEscape = load16(); + checkEscape = _vm->_game->_script->readInt16(); _vm->_mult->playMult(VAR(57), -1, checkEscape, 0); } void Inter_v1::o1_freeMultKeys() { - load16(); + _vm->_game->_script->readInt16(); _vm->_mult->freeMultKeys(); } @@ -785,20 +305,20 @@ void Inter_v1::o1_initCursor() { int16 height; int16 count; - _vm->_draw->_cursorHotspotXVar = _vm->_parse->parseVarIndex() / 4; - _vm->_draw->_cursorHotspotYVar = _vm->_parse->parseVarIndex() / 4; + _vm->_draw->_cursorHotspotXVar = _vm->_game->_script->readVarIndex() / 4; + _vm->_draw->_cursorHotspotYVar = _vm->_game->_script->readVarIndex() / 4; - width = load16(); + width = _vm->_game->_script->readInt16(); if (width < 16) width = 16; - height = load16(); + height = _vm->_game->_script->readInt16(); if (height < 16) height = 16; _vm->_draw->adjustCoords(0, &width, &height); - count = load16(); + count = _vm->_game->_script->readInt16(); if (count < 2) count = 2; @@ -846,24 +366,24 @@ void Inter_v1::o1_initCursorAnim() { int16 ind; _vm->_draw->_showCursor = 3; - ind = _vm->_parse->parseValExpr(); - _vm->_draw->_cursorAnimLow[ind] = load16(); - _vm->_draw->_cursorAnimHigh[ind] = load16(); - _vm->_draw->_cursorAnimDelays[ind] = load16(); + ind = _vm->_game->_script->readValExpr(); + _vm->_draw->_cursorAnimLow[ind] = _vm->_game->_script->readInt16(); + _vm->_draw->_cursorAnimHigh[ind] = _vm->_game->_script->readInt16(); + _vm->_draw->_cursorAnimDelays[ind] = _vm->_game->_script->readInt16(); } void Inter_v1::o1_clearCursorAnim() { int16 ind; _vm->_draw->_showCursor = 0; - ind = _vm->_parse->parseValExpr(); + ind = _vm->_game->_script->readValExpr(); _vm->_draw->_cursorAnimLow[ind] = -1; _vm->_draw->_cursorAnimHigh[ind] = 0; _vm->_draw->_cursorAnimDelays[ind] = 0; } void Inter_v1::o1_setRenderFlags() { - _vm->_draw->_renderFlags = _vm->_parse->parseValExpr(); + _vm->_draw->_renderFlags = _vm->_game->_script->readValExpr(); } void Inter_v1::o1_loadAnim() { @@ -882,12 +402,12 @@ void Inter_v1::o1_updateAnim() { int16 layer; int16 animation; - evalExpr(&deltaX); - evalExpr(&deltaY); - evalExpr(&animation); - evalExpr(&layer); - evalExpr(&frame); - flags = load16(); + _vm->_game->_script->evalExpr(&deltaX); + _vm->_game->_script->evalExpr(&deltaY); + _vm->_game->_script->evalExpr(&animation); + _vm->_game->_script->evalExpr(&layer); + _vm->_game->_script->evalExpr(&frame); + flags = _vm->_game->_script->readInt16(); _vm->_scenery->updateAnim(layer, frame, animation, flags, deltaX, deltaY, 1); } @@ -904,14 +424,14 @@ void Inter_v1::o1_initMult() { oldAnimHeight = _vm->_mult->_animHeight; oldObjCount = _vm->_mult->_objCount; - _vm->_mult->_animLeft = load16(); - _vm->_mult->_animTop = load16(); - _vm->_mult->_animWidth = load16(); - _vm->_mult->_animHeight = load16(); - _vm->_mult->_objCount = load16(); - posXVar = _vm->_parse->parseVarIndex(); - posYVar = _vm->_parse->parseVarIndex(); - animDataVar = _vm->_parse->parseVarIndex(); + _vm->_mult->_animLeft = _vm->_game->_script->readInt16(); + _vm->_mult->_animTop = _vm->_game->_script->readInt16(); + _vm->_mult->_animWidth = _vm->_game->_script->readInt16(); + _vm->_mult->_animHeight = _vm->_game->_script->readInt16(); + _vm->_mult->_objCount = _vm->_game->_script->readInt16(); + posXVar = _vm->_game->_script->readVarIndex(); + posYVar = _vm->_game->_script->readVarIndex(); + animDataVar = _vm->_game->_script->readVarIndex(); if (_vm->_mult->_objects && (oldObjCount != _vm->_mult->_objCount)) { @@ -944,8 +464,8 @@ void Inter_v1::o1_initMult() { uint32 offPosY = i * 4 + (posYVar / 4) * 4; uint32 offAnim = animDataVar + i * 4 * _vm->_global->_inter_animDataSize; - _vm->_mult->_objects[i].pPosX = new VariableReference(*_vm->_inter->_variables, offPosX); - _vm->_mult->_objects[i].pPosY = new VariableReference(*_vm->_inter->_variables, offPosY); + _vm->_mult->_objects[i].pPosX = new VariableReference(*_variables, offPosX); + _vm->_mult->_objects[i].pPosY = new VariableReference(*_variables, offPosY); _vm->_mult->_objects[i].pAnimData = (Mult::Mult_AnimData *) _variables->getAddressOff8(offAnim); @@ -998,21 +518,21 @@ void Inter_v1::o1_loadMultObject() { int16 objIndex; byte *multData; - evalExpr(&objIndex); - evalExpr(&val); + _vm->_game->_script->evalExpr(&objIndex); + _vm->_game->_script->evalExpr(&val); *_vm->_mult->_objects[objIndex].pPosX = val; - evalExpr(&val); + _vm->_game->_script->evalExpr(&val); *_vm->_mult->_objects[objIndex].pPosY = val; debugC(4, kDebugGameFlow, "Loading mult object %d", objIndex); multData = (byte *) _vm->_mult->_objects[objIndex].pAnimData; for (int i = 0; i < 11; i++) { - if (READ_LE_UINT16(_vm->_global->_inter_execPtr) != 99) { - evalExpr(&val); + if (_vm->_game->_script->peekUint16() != 99) { + _vm->_game->_script->evalExpr(&val); multData[i] = val; } else - _vm->_global->_inter_execPtr++; + _vm->_game->_script->skip(1); } } @@ -1023,13 +543,13 @@ void Inter_v1::o1_getAnimLayerInfo() { int16 varUnk0; int16 varFrames; - evalExpr(&anim); - evalExpr(&layer); + _vm->_game->_script->evalExpr(&anim); + _vm->_game->_script->evalExpr(&layer); - varDX = _vm->_parse->parseVarIndex(); - varDY = _vm->_parse->parseVarIndex(); - varUnk0 = _vm->_parse->parseVarIndex(); - varFrames = _vm->_parse->parseVarIndex(); + varDX = _vm->_game->_script->readVarIndex(); + varDY = _vm->_game->_script->readVarIndex(); + varUnk0 = _vm->_game->_script->readVarIndex(); + varFrames = _vm->_game->_script->readVarIndex(); _vm->_scenery->writeAnimLayerInfo(anim, layer, varDX, varDY, varUnk0, varFrames); @@ -1038,7 +558,7 @@ void Inter_v1::o1_getAnimLayerInfo() { void Inter_v1::o1_getObjAnimSize() { int16 objIndex; - evalExpr(&objIndex); + _vm->_game->_script->evalExpr(&objIndex); Mult::Mult_AnimData &animData = *(_vm->_mult->_objects[objIndex].pAnimData); if (animData.isStatic == 0) @@ -1048,10 +568,10 @@ void Inter_v1::o1_getObjAnimSize() { _vm->_scenery->_toRedrawLeft = MAX(_vm->_scenery->_toRedrawLeft, (int16) 0); _vm->_scenery->_toRedrawTop = MAX(_vm->_scenery->_toRedrawTop, (int16) 0); - WRITE_VAR_OFFSET(_vm->_parse->parseVarIndex(), _vm->_scenery->_toRedrawLeft); - WRITE_VAR_OFFSET(_vm->_parse->parseVarIndex(), _vm->_scenery->_toRedrawTop); - WRITE_VAR_OFFSET(_vm->_parse->parseVarIndex(), _vm->_scenery->_toRedrawRight); - WRITE_VAR_OFFSET(_vm->_parse->parseVarIndex(), _vm->_scenery->_toRedrawBottom); + WRITE_VAR_OFFSET(_vm->_game->_script->readVarIndex(), _vm->_scenery->_toRedrawLeft); + WRITE_VAR_OFFSET(_vm->_game->_script->readVarIndex(), _vm->_scenery->_toRedrawTop); + WRITE_VAR_OFFSET(_vm->_game->_script->readVarIndex(), _vm->_scenery->_toRedrawRight); + WRITE_VAR_OFFSET(_vm->_game->_script->readVarIndex(), _vm->_scenery->_toRedrawBottom); } void Inter_v1::o1_loadStatic() { @@ -1066,20 +586,20 @@ void Inter_v1::o1_renderStatic() { int16 layer; int16 index; - _vm->_inter->evalExpr(&index); - _vm->_inter->evalExpr(&layer); + _vm->_game->_script->evalExpr(&index); + _vm->_game->_script->evalExpr(&layer); _vm->_scenery->renderStatic(index, layer); } void Inter_v1::o1_loadCurLayer() { - evalExpr(&_vm->_scenery->_curStatic); - evalExpr(&_vm->_scenery->_curStaticLayer); + _vm->_game->_script->evalExpr(&_vm->_scenery->_curStatic); + _vm->_game->_script->evalExpr(&_vm->_scenery->_curStaticLayer); } void Inter_v1::o1_playCDTrack() { - evalExpr(0); + _vm->_game->_script->evalExpr(0); _vm->_sound->adlibPlayBgMusic(); // Mac version - _vm->_sound->cdPlay(_vm->_global->_inter_resStr); // PC CD version + _vm->_sound->cdPlay(_vm->_game->_script->getResultStr()); // PC CD version } void Inter_v1::o1_getCDTrackPos() { @@ -1103,15 +623,15 @@ void Inter_v1::o1_stopCD() { } void Inter_v1::o1_loadFontToSprite() { - int16 i = load16(); - _vm->_draw->_fontToSprite[i].sprite = load16(); - _vm->_draw->_fontToSprite[i].base = load16(); - _vm->_draw->_fontToSprite[i].width = load16(); - _vm->_draw->_fontToSprite[i].height = load16(); + int16 i = _vm->_game->_script->readInt16(); + _vm->_draw->_fontToSprite[i].sprite = _vm->_game->_script->readInt16(); + _vm->_draw->_fontToSprite[i].base = _vm->_game->_script->readInt16(); + _vm->_draw->_fontToSprite[i].width = _vm->_game->_script->readInt16(); + _vm->_draw->_fontToSprite[i].height = _vm->_game->_script->readInt16(); } void Inter_v1::o1_freeFontToSprite() { - int16 i = load16(); + int16 i = _vm->_game->_script->readInt16(); _vm->_draw->_fontToSprite[i].sprite = -1; _vm->_draw->_fontToSprite[i].base = -1; _vm->_draw->_fontToSprite[i].width = -1; @@ -1119,11 +639,7 @@ void Inter_v1::o1_freeFontToSprite() { } bool Inter_v1::o1_callSub(OpFuncParams ¶ms) { - byte *storedIP; - uint16 offset; - - offset = load16(); - storedIP = _vm->_global->_inter_execPtr; + uint16 offset = _vm->_game->_script->readUint16(); debugC(5, kDebugGameFlow, "tot = \"%s\", offset = %d", _vm->_game->_curTotFile, offset); @@ -1147,79 +663,89 @@ bool Inter_v1::o1_callSub(OpFuncParams ¶ms) { return false; } - _vm->_global->_inter_execPtr = _vm->_game->_totFileData + offset; + _vm->_game->_script->call(offset); - if ((params.counter == params.cmdCount) && (params.retFlag == 2)) + if ((params.counter == params.cmdCount) && (params.retFlag == 2)) { + _vm->_game->_script->pop(false); return true; + } callSub(2); - _vm->_global->_inter_execPtr = storedIP; + + _vm->_game->_script->pop(); return false; } bool Inter_v1::o1_printTotText(OpFuncParams ¶ms) { - _vm->_draw->printTotText(load16()); + _vm->_draw->printTotText(_vm->_game->_script->readInt16()); return false; } bool Inter_v1::o1_loadCursor(OpFuncParams ¶ms) { - int16 width, height; - byte *dataBuf; - int16 id; - int8 index; - - id = load16(); - index = (int8) *_vm->_global->_inter_execPtr++; + int16 id = _vm->_game->_script->readInt16(); + int8 index = _vm->_game->_script->readInt8(); if ((index * _vm->_draw->_cursorWidth) >= _vm->_draw->_cursorSprites->getWidth()) return false; - dataBuf = _vm->_game->loadTotResource(id, 0, &width, &height); + Resource *resource = _vm->_game->_resources->getResource(id); + if (!resource) + return false; _vm->_video->fillRect(*_vm->_draw->_cursorSprites, index * _vm->_draw->_cursorWidth, 0, index * _vm->_draw->_cursorWidth + _vm->_draw->_cursorWidth - 1, _vm->_draw->_cursorHeight - 1, 0); - _vm->_video->drawPackedSprite(dataBuf, width, height, + _vm->_video->drawPackedSprite(resource->getData(), + resource->getWidth(), resource->getHeight(), index * _vm->_draw->_cursorWidth, 0, 0, *_vm->_draw->_cursorSprites); _vm->_draw->_cursorAnimLow[index] = 0; + delete resource; return false; } bool Inter_v1::o1_switch(OpFuncParams ¶ms) { - byte *callAddr; + uint32 offset; + + checkSwitchTable(offset); - checkSwitchTable(&callAddr); - byte *storedIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr = callAddr; + _vm->_game->_script->call(offset); - if ((params.counter == params.cmdCount) && (params.retFlag == 2)) + if (offset == 0) + _vm->_game->_script->setFinished(true); + + if ((params.counter == params.cmdCount) && (params.retFlag == 2)) { + _vm->_game->_script->pop(false); return true; + } funcBlock(0); - _vm->_global->_inter_execPtr = storedIP; + + _vm->_game->_script->pop(); return false; } bool Inter_v1::o1_repeatUntil(OpFuncParams ¶ms) { - byte *blockPtr; int16 size; bool flag; _nestLevel[0]++; - blockPtr = _vm->_global->_inter_execPtr; + + uint32 blockPos = _vm->_game->_script->pos(); do { - _vm->_global->_inter_execPtr = blockPtr; - size = READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2; + _vm->_game->_script->seek(blockPos); + size = _vm->_game->_script->peekUint16(2) + 2; funcBlock(1); - _vm->_global->_inter_execPtr = blockPtr + size + 1; - flag = evalBoolResult(); + + _vm->_game->_script->seek(blockPos + size + 1); + + flag = _vm->_game->_script->evalBoolResult(); } while (!flag && !_break && !_terminate && !_vm->shouldQuit()); _nestLevel[0]--; @@ -1232,32 +758,31 @@ bool Inter_v1::o1_repeatUntil(OpFuncParams ¶ms) { } bool Inter_v1::o1_whileDo(OpFuncParams ¶ms) { - byte *blockPtr; - byte *savedIP; bool flag; int16 size; _nestLevel[0]++; do { - savedIP = _vm->_global->_inter_execPtr; - flag = evalBoolResult(); + uint32 startPos = _vm->_game->_script->pos(); + + flag = _vm->_game->_script->evalBoolResult(); if (_terminate) return false; - blockPtr = _vm->_global->_inter_execPtr; + uint32 blockPos = _vm->_game->_script->pos(); - size = READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2; + size = _vm->_game->_script->peekUint16(2) + 2; if (flag) { funcBlock(1); - _vm->_global->_inter_execPtr = savedIP; + _vm->_game->_script->seek(startPos); } else - _vm->_global->_inter_execPtr += size; + _vm->_game->_script->skip(size); if (_break || _terminate || _vm->shouldQuit()) { - _vm->_global->_inter_execPtr = blockPtr; - _vm->_global->_inter_execPtr += size; + _vm->_game->_script->seek(blockPos); + _vm->_game->_script->skip(size); break; } } while (flag); @@ -1273,76 +798,65 @@ bool Inter_v1::o1_whileDo(OpFuncParams ¶ms) { bool Inter_v1::o1_if(OpFuncParams ¶ms) { byte cmd; bool boolRes; - byte *storedIP; - boolRes = evalBoolResult(); + boolRes = _vm->_game->_script->evalBoolResult(); if (boolRes) { if ((params.counter == params.cmdCount) && (params.retFlag == 2)) return true; - storedIP = _vm->_global->_inter_execPtr; + _vm->_game->_script->push(); funcBlock(0); - _vm->_global->_inter_execPtr = storedIP; + _vm->_game->_script->pop(); - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2; + _vm->_game->_script->skip(_vm->_game->_script->peekUint16(2) + 2); - debugC(5, kDebugGameFlow, "cmd = %d", - (int16) *_vm->_global->_inter_execPtr); + debugC(5, kDebugGameFlow, "cmd = %d", (int16) _vm->_game->_script->peekByte()); - cmd = *_vm->_global->_inter_execPtr >> 4; - _vm->_global->_inter_execPtr++; + cmd = _vm->_game->_script->readByte() >> 4; if (cmd != 12) return false; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2; + _vm->_game->_script->skip(_vm->_game->_script->peekUint16(2) + 2); } else { - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2; + _vm->_game->_script->skip(_vm->_game->_script->peekUint16(2) + 2); - debugC(5, kDebugGameFlow, "cmd = %d", - (int16) *_vm->_global->_inter_execPtr); + debugC(5, kDebugGameFlow, "cmd = %d", (int16) _vm->_game->_script->peekByte()); - cmd = *_vm->_global->_inter_execPtr >> 4; - _vm->_global->_inter_execPtr++; + cmd = _vm->_game->_script->readByte() >> 4; if (cmd != 12) return false; if ((params.counter == params.cmdCount) && (params.retFlag == 2)) return true; - storedIP = _vm->_global->_inter_execPtr; + _vm->_game->_script->push(); funcBlock(0); - _vm->_global->_inter_execPtr = storedIP; + _vm->_game->_script->pop(); - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2; + _vm->_game->_script->skip(_vm->_game->_script->peekUint16(2) + 2); } return false; } bool Inter_v1::o1_assign(OpFuncParams ¶ms) { - byte *savedPos; - int16 token; + byte destType = _vm->_game->_script->peekByte(); + int16 dest = _vm->_game->_script->readVarIndex(); + int16 result; - int16 varOff; + int16 srcType = _vm->_game->_script->evalExpr(&result); - savedPos = _vm->_global->_inter_execPtr; - varOff = _vm->_parse->parseVarIndex(); - token = evalExpr(&result); - switch (savedPos[0]) { - case 23: - case 26: - WRITE_VAR_OFFSET(varOff, _vm->_global->_inter_resVal); + switch (destType) { + case TYPE_VAR_INT32: + case TYPE_ARRAY_INT32: + WRITE_VAR_OFFSET(dest, _vm->_game->_script->getResultInt()); break; - case 25: - case 28: - if (token == 20) - WRITE_VARO_UINT8(varOff, result); + case TYPE_VAR_STR: + case TYPE_ARRAY_STR: + if (srcType == TYPE_IMM_INT16) + WRITE_VARO_UINT8(dest, result); else - WRITE_VARO_STR(varOff, _vm->_global->_inter_resStr); + WRITE_VARO_STR(dest, _vm->_game->_script->getResultStr()); break; } @@ -1350,17 +864,17 @@ bool Inter_v1::o1_assign(OpFuncParams ¶ms) { } bool Inter_v1::o1_loadSpriteToPos(OpFuncParams ¶ms) { - _vm->_draw->_spriteLeft = load16(); + _vm->_draw->_spriteLeft = _vm->_game->_script->readInt16(); - _vm->_draw->_destSpriteX = _vm->_parse->parseValExpr(); - _vm->_draw->_destSpriteY = _vm->_parse->parseValExpr(); + _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr(); + _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr(); - _vm->_draw->_transparency = *_vm->_global->_inter_execPtr & 1; - _vm->_draw->_destSurface = ((int16) (*_vm->_global->_inter_execPtr >> 1)) - 1; + _vm->_draw->_transparency = _vm->_game->_script->peekByte() & 1; + _vm->_draw->_destSurface = ((int16) (_vm->_game->_script->peekByte() >> 1)) - 1; if (_vm->_draw->_destSurface < 0) _vm->_draw->_destSurface = 101; - _vm->_global->_inter_execPtr += 2; + _vm->_game->_script->skip(2); _vm->_draw->spriteOperation(DRAW_LOADSPRITE); @@ -1371,12 +885,12 @@ bool Inter_v1::o1_printText(OpFuncParams ¶ms) { char buf[60]; int i; - _vm->_draw->_destSpriteX = _vm->_parse->parseValExpr(); - _vm->_draw->_destSpriteY = _vm->_parse->parseValExpr(); + _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr(); + _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr(); - _vm->_draw->_backColor = _vm->_parse->parseValExpr(); - _vm->_draw->_frontColor = _vm->_parse->parseValExpr(); - _vm->_draw->_fontIndex = _vm->_parse->parseValExpr(); + _vm->_draw->_backColor = _vm->_game->_script->readValExpr(); + _vm->_draw->_frontColor = _vm->_game->_script->readValExpr(); + _vm->_draw->_fontIndex = _vm->_game->_script->readValExpr(); _vm->_draw->_destSurface = 21; _vm->_draw->_textToPrint = buf; _vm->_draw->_transparency = 0; @@ -1387,35 +901,35 @@ bool Inter_v1::o1_printText(OpFuncParams ¶ms) { } do { - for (i = 0; (((char) *_vm->_global->_inter_execPtr) != '.') && - (*_vm->_global->_inter_execPtr != 200); - i++, _vm->_global->_inter_execPtr++) { - buf[i] = (char) *_vm->_global->_inter_execPtr; + for (i = 0; ((_vm->_game->_script->peekChar()) != '.') && + (_vm->_game->_script->peekByte() != 200); + i++, _vm->_game->_script->skip(1)) { + buf[i] = _vm->_game->_script->peekChar(); } - if (*_vm->_global->_inter_execPtr != 200) { - _vm->_global->_inter_execPtr++; - switch (*_vm->_global->_inter_execPtr) { - case 23: - case 26: + if (_vm->_game->_script->peekByte() != 200) { + _vm->_game->_script->skip(1); + switch (_vm->_game->_script->peekByte()) { + case TYPE_VAR_INT32: + case TYPE_ARRAY_INT32: sprintf(buf + i, "%d", - VAR_OFFSET(_vm->_parse->parseVarIndex())); + VAR_OFFSET(_vm->_game->_script->readVarIndex())); break; - case 25: - case 28: + case TYPE_VAR_STR: + case TYPE_ARRAY_STR: sprintf(buf + i, "%s", - GET_VARO_STR(_vm->_parse->parseVarIndex())); + GET_VARO_STR(_vm->_game->_script->readVarIndex())); break; } - _vm->_global->_inter_execPtr++; + _vm->_game->_script->skip(1); } else buf[i] = 0; _vm->_draw->spriteOperation(DRAW_PRINTTEXT); - } while (*_vm->_global->_inter_execPtr != 200); + } while (_vm->_game->_script->peekByte() != 200); - _vm->_global->_inter_execPtr++; + _vm->_game->_script->skip(1); return false; } @@ -1424,16 +938,14 @@ bool Inter_v1::o1_loadTot(OpFuncParams ¶ms) { char buf[20]; int8 size; - if ((*_vm->_global->_inter_execPtr & 0x80) != 0) { - _vm->_global->_inter_execPtr++; - evalExpr(0); - strncpy0(buf, _vm->_global->_inter_resStr, 15); + if ((_vm->_game->_script->peekByte() & 0x80) != 0) { + _vm->_game->_script->skip(1); + _vm->_game->_script->evalExpr(0); + strncpy0(buf, _vm->_game->_script->getResultStr(), 15); } else { - size = (int8) *_vm->_global->_inter_execPtr++; - for (int i = 0; i < size; i++) - buf[i] = *_vm->_global->_inter_execPtr++; - - buf[size] = 0; + size = _vm->_game->_script->readInt8(); + memcpy(buf, _vm->_game->_script->readString(size), size); + buf[size] = '\0'; } // if (_vm->getGameType() == kGameTypeGeisha) @@ -1450,15 +962,15 @@ bool Inter_v1::o1_loadTot(OpFuncParams ¶ms) { bool Inter_v1::o1_palLoad(OpFuncParams ¶ms) { int index1, index2; - byte *palPtr; byte cmd; + Resource *resource; - cmd = *_vm->_global->_inter_execPtr++; + cmd = _vm->_game->_script->readByte(); switch (cmd & 0x7F) { case 48: if ((_vm->_global->_fakeVideoMode < 0x32) || (_vm->_global->_fakeVideoMode > 0x63)) { - _vm->_global->_inter_execPtr += 48; + _vm->_game->_script->skip(48); return false; } break; @@ -1466,35 +978,35 @@ bool Inter_v1::o1_palLoad(OpFuncParams ¶ms) { case 49: if ((_vm->_global->_fakeVideoMode != 5) && (_vm->_global->_fakeVideoMode != 7)) { - _vm->_global->_inter_execPtr += 18; + _vm->_game->_script->skip(18); return false; } break; case 50: if (_vm->_global->_colorCount == 256) { - _vm->_global->_inter_execPtr += 16; + _vm->_game->_script->skip(16); return false; } break; case 51: if (_vm->_global->_fakeVideoMode < 0x64) { - _vm->_global->_inter_execPtr += 2; + _vm->_game->_script->skip(2); return false; } break; case 52: if (_vm->_global->_colorCount == 256) { - _vm->_global->_inter_execPtr += 48; + _vm->_game->_script->skip(48); return false; } break; case 53: if (_vm->_global->_colorCount != 256) { - _vm->_global->_inter_execPtr += 2; + _vm->_game->_script->skip(2); return false; } break; @@ -1507,14 +1019,14 @@ bool Inter_v1::o1_palLoad(OpFuncParams ¶ms) { case 61: if (_vm->_global->_fakeVideoMode < 0x13) { - _vm->_global->_inter_execPtr += 4; + _vm->_game->_script->skip(4); return false; } break; } if ((cmd & 0x7F) == 0x30) { - _vm->_global->_inter_execPtr += 48; + _vm->_game->_script->skip(48); return false; } @@ -1525,7 +1037,7 @@ bool Inter_v1::o1_palLoad(OpFuncParams ¶ms) { bool allZero = true; for (int i = 2; i < 18; i++) { - if (_vm->_global->_inter_execPtr[i] != 0) { + if (_vm->_game->_script->peekByte(i) != 0) { allZero = false; break; } @@ -1533,28 +1045,30 @@ bool Inter_v1::o1_palLoad(OpFuncParams ¶ms) { if (!allZero) { _vm->_video->clearSurf(*_vm->_draw->_frontSurface); _vm->_draw->_noInvalidated57 = true; - _vm->_global->_inter_execPtr += 18; + _vm->_game->_script->skip(48); return false; } _vm->_draw->_noInvalidated57 = false; - for (int i = 0; i < 18; i++, _vm->_global->_inter_execPtr++) { + for (int i = 0; i < 18; i++) { if (i < 2) { if (!_vm->_draw->_applyPal) continue; - _vm->_draw->_unusedPalette1[i] = *_vm->_global->_inter_execPtr; + _vm->_draw->_unusedPalette1[i] = _vm->_game->_script->peekByte(); continue; } - index1 = *_vm->_global->_inter_execPtr >> 4; - index2 = (*_vm->_global->_inter_execPtr & 0xF); + index1 = _vm->_game->_script->peekByte() >> 4; + index2 = _vm->_game->_script->peekByte() & 0xF; _vm->_draw->_unusedPalette1[i] = ((_vm->_draw->_palLoadData1[index1] + _vm->_draw->_palLoadData2[index2]) << 8) + (_vm->_draw->_palLoadData2[index1] + _vm->_draw->_palLoadData1[index2]); + + _vm->_game->_script->skip(1); } _vm->_global->_pPaletteDesc->unused1 = _vm->_draw->_unusedPalette1; @@ -1564,21 +1078,25 @@ bool Inter_v1::o1_palLoad(OpFuncParams ¶ms) { switch (cmd) { case 50: - for (int i = 0; i < 16; i++, _vm->_global->_inter_execPtr++) - _vm->_draw->_unusedPalette2[i] = *_vm->_global->_inter_execPtr; + for (int i = 0; i < 16; i++) + _vm->_draw->_unusedPalette2[i] = _vm->_game->_script->readByte(); break; case 52: - for (int i = 0; i < 16; i++, _vm->_global->_inter_execPtr += 3) { - _vm->_draw->_vgaPalette[i].red = _vm->_global->_inter_execPtr[0]; - _vm->_draw->_vgaPalette[i].green = _vm->_global->_inter_execPtr[1]; - _vm->_draw->_vgaPalette[i].blue = _vm->_global->_inter_execPtr[2]; + for (int i = 0; i < 16; i++) { + _vm->_draw->_vgaPalette[i].red = _vm->_game->_script->readByte(); + _vm->_draw->_vgaPalette[i].green = _vm->_game->_script->readByte(); + _vm->_draw->_vgaPalette[i].blue = _vm->_game->_script->readByte(); } break; case 53: - palPtr = _vm->_game->loadTotResource(_vm->_inter->load16()); - memcpy((char *) _vm->_draw->_vgaPalette, palPtr, 768); + resource = _vm->_game->_resources->getResource(_vm->_game->_script->readInt16()); + if (!resource) + break; + + memcpy((char *) _vm->_draw->_vgaPalette, resource->getData(), MIN(768, resource->getSize())); + delete resource; break; case 54: @@ -1586,11 +1104,15 @@ bool Inter_v1::o1_palLoad(OpFuncParams ¶ms) { break; case 61: - index1 = *_vm->_global->_inter_execPtr++; - index2 = (*_vm->_global->_inter_execPtr++ - index1 + 1) * 3; - palPtr = _vm->_game->loadTotResource(_vm->_inter->load16()); + index1 = _vm->_game->_script->readByte(); + index2 = (_vm->_game->_script->readByte() - index1 + 1) * 3; + resource = _vm->_game->_resources->getResource(_vm->_game->_script->readInt16()); + if (!resource) + break; + memcpy((char *) _vm->_draw->_vgaPalette + index1 * 3, - palPtr + index1 * 3, index2); + resource->getData() + index1 * 3, index2); + delete resource; if (_vm->_draw->_applyPal) { _vm->_draw->_applyPal = false; @@ -1628,7 +1150,7 @@ bool Inter_v1::o1_keyFunc(OpFuncParams ¶ms) { int16 key; uint32 now; - cmd = load16(); + cmd = _vm->_game->_script->readInt16(); animPalette(); _vm->_draw->blitInvalidated(); @@ -1643,7 +1165,7 @@ bool Inter_v1::o1_keyFunc(OpFuncParams ¶ms) { // to become 5000. We deliberately slow down busy-waiting, so we shorten // the counting, too. if ((_vm->getGameType() == kGameTypeWeen) && (VAR(59) < 4000) && - ((_vm->_global->_inter_execPtr - _vm->_game->_totFileData) == 729) && + (_vm->_game->_script->pos() == 729) && !scumm_stricmp(_vm->_game->_curTotFile, "intro5.tot")) WRITE_VAR(59, 4000); @@ -1689,10 +1211,10 @@ bool Inter_v1::o1_capturePush(OpFuncParams ¶ms) { int16 left, top; int16 width, height; - left = _vm->_parse->parseValExpr(); - top = _vm->_parse->parseValExpr(); - width = _vm->_parse->parseValExpr(); - height = _vm->_parse->parseValExpr(); + left = _vm->_game->_script->readValExpr(); + top = _vm->_game->_script->readValExpr(); + width = _vm->_game->_script->readValExpr(); + height = _vm->_game->_script->readValExpr(); if ((width < 0) || (height < 0)) return false; @@ -1711,24 +1233,24 @@ bool Inter_v1::o1_capturePop(OpFuncParams ¶ms) { } bool Inter_v1::o1_animPalInit(OpFuncParams ¶ms) { - _animPalDir[0] = load16(); - _animPalLowIndex[0] = _vm->_parse->parseValExpr(); - _animPalHighIndex[0] = _vm->_parse->parseValExpr(); + _animPalDir[0] = _vm->_game->_script->readInt16(); + _animPalLowIndex[0] = _vm->_game->_script->readValExpr(); + _animPalHighIndex[0] = _vm->_game->_script->readValExpr(); return false; } bool Inter_v1::o1_drawOperations(OpFuncParams ¶ms) { byte cmd; - cmd = *_vm->_global->_inter_execPtr++; + cmd = _vm->_game->_script->readByte(); - executeDrawOpcode(cmd); + executeOpcodeDraw(cmd); return false; } bool Inter_v1::o1_setcmdCount(OpFuncParams ¶ms) { - params.cmdCount = *_vm->_global->_inter_execPtr++; + params.cmdCount = _vm->_game->_script->readByte(); params.counter = 0; return false; } @@ -1737,7 +1259,7 @@ bool Inter_v1::o1_return(OpFuncParams ¶ms) { if (params.retFlag != 2) _break = true; - _vm->_global->_inter_execPtr = 0; + _vm->_game->_script->setFinished(true); return true; } @@ -1747,7 +1269,7 @@ bool Inter_v1::o1_renewTimeInVars(OpFuncParams ¶ms) { } bool Inter_v1::o1_speakerOn(OpFuncParams ¶ms) { - _vm->_sound->speakerOn(_vm->_parse->parseValExpr(), -1); + _vm->_sound->speakerOn(_vm->_game->_script->readValExpr(), -1); return false; } @@ -1757,11 +1279,11 @@ bool Inter_v1::o1_speakerOff(OpFuncParams ¶ms) { } bool Inter_v1::o1_putPixel(OpFuncParams ¶ms) { - _vm->_draw->_destSurface = load16(); + _vm->_draw->_destSurface = _vm->_game->_script->readInt16(); - _vm->_draw->_destSpriteX = _vm->_parse->parseValExpr(); - _vm->_draw->_destSpriteY = _vm->_parse->parseValExpr(); - _vm->_draw->_frontColor = _vm->_parse->parseValExpr(); + _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr(); + _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr(); + _vm->_draw->_frontColor = _vm->_game->_script->readValExpr(); _vm->_draw->spriteOperation(DRAW_PUTPIXEL); return false; } @@ -1773,33 +1295,33 @@ bool Inter_v1::o1_goblinFunc(OpFuncParams ¶ms) { gobParams.extraData = 0; gobParams.objDesc = 0; - gobParams.retVarPtr.set(*_vm->_inter->_variables, 236); + gobParams.retVarPtr.set(*_variables, 236); - cmd = load16(); - _vm->_global->_inter_execPtr += 2; + cmd = _vm->_game->_script->readInt16(); + _vm->_game->_script->skip(2); if ((cmd > 0) && (cmd < 17)) { objDescSet = true; - gobParams.extraData = load16(); + gobParams.extraData = _vm->_game->_script->readInt16(); gobParams.objDesc = _vm->_goblin->_objects[gobParams.extraData]; - gobParams.extraData = load16(); + gobParams.extraData = _vm->_game->_script->readInt16(); } if ((cmd > 90) && (cmd < 107)) { objDescSet = true; - gobParams.extraData = load16(); + gobParams.extraData = _vm->_game->_script->readInt16(); gobParams.objDesc = _vm->_goblin->_goblins[gobParams.extraData]; - gobParams.extraData = load16(); + gobParams.extraData = _vm->_game->_script->readInt16(); cmd -= 90; } if ((cmd > 110) && (cmd < 128)) { objDescSet = true; - gobParams.extraData = load16(); + gobParams.extraData = _vm->_game->_script->readInt16(); gobParams.objDesc = _vm->_goblin->_goblins[gobParams.extraData]; cmd -= 90; } else if ((cmd > 20) && (cmd < 38)) { objDescSet = true; - gobParams.extraData = load16(); + gobParams.extraData = _vm->_game->_script->readInt16(); gobParams.objDesc = _vm->_goblin->_objects[gobParams.extraData]; } @@ -1815,7 +1337,7 @@ bool Inter_v1::o1_goblinFunc(OpFuncParams ¶ms) { if ((cmd < 40) && objDescSet && !gobParams.objDesc) return false; - executeGoblinOpcode(cmd, gobParams); + executeOpcodeGob(cmd, gobParams); return false; } @@ -1825,31 +1347,31 @@ bool Inter_v1::o1_createSprite(OpFuncParams ¶ms) { int16 width, height; int16 flag; - if (_vm->_global->_inter_execPtr[1] == 0) { - index = load16(); - width = load16(); - height = load16(); + if (_vm->_game->_script->peekByte(1) == 0) { + index = _vm->_game->_script->readInt16(); + width = _vm->_game->_script->readInt16(); + height = _vm->_game->_script->readInt16(); } else { - index = _vm->_parse->parseValExpr(); - width = _vm->_parse->parseValExpr(); - height = _vm->_parse->parseValExpr(); + index = _vm->_game->_script->readValExpr(); + width = _vm->_game->_script->readValExpr(); + height = _vm->_game->_script->readValExpr(); } - flag = load16(); + flag = _vm->_game->_script->readInt16(); _vm->_draw->initSpriteSurf(index, width, height, flag ? 2 : 0); return false; } bool Inter_v1::o1_freeSprite(OpFuncParams ¶ms) { - _vm->_draw->freeSprite(load16()); + _vm->_draw->freeSprite(_vm->_game->_script->readInt16()); return false; } bool Inter_v1::o1_returnTo(OpFuncParams ¶ms) { if (params.retFlag == 1) { _break = true; - _vm->_global->_inter_execPtr = 0; + _vm->_game->_script->setFinished(true); return true; } @@ -1858,14 +1380,14 @@ bool Inter_v1::o1_returnTo(OpFuncParams ¶ms) { *_breakFromLevel = *_nestLevel; _break = true; - _vm->_global->_inter_execPtr = 0; + _vm->_game->_script->setFinished(true); return true; } bool Inter_v1::o1_loadSpriteContent(OpFuncParams ¶ms) { - _vm->_draw->_spriteLeft = load16(); - _vm->_draw->_destSurface = load16(); - _vm->_draw->_transparency = load16(); + _vm->_draw->_spriteLeft = _vm->_game->_script->readInt16(); + _vm->_draw->_destSurface = _vm->_game->_script->readInt16(); + _vm->_draw->_transparency = _vm->_game->_script->readInt16(); _vm->_draw->_destSpriteX = 0; _vm->_draw->_destSpriteY = 0; @@ -1874,25 +1396,25 @@ bool Inter_v1::o1_loadSpriteContent(OpFuncParams ¶ms) { } bool Inter_v1::o1_copySprite(OpFuncParams ¶ms) { - if (_vm->_global->_inter_execPtr[1] == 0) - _vm->_draw->_sourceSurface = load16(); + if (_vm->_game->_script->peekByte(1) == 0) + _vm->_draw->_sourceSurface = _vm->_game->_script->readInt16(); else - _vm->_draw->_sourceSurface = _vm->_parse->parseValExpr(); + _vm->_draw->_sourceSurface = _vm->_game->_script->readValExpr(); - if (_vm->_global->_inter_execPtr[1] == 0) - _vm->_draw->_destSurface = load16(); + if (_vm->_game->_script->peekByte(1) == 0) + _vm->_draw->_destSurface = _vm->_game->_script->readInt16(); else - _vm->_draw->_destSurface = _vm->_parse->parseValExpr(); + _vm->_draw->_destSurface = _vm->_game->_script->readValExpr(); - _vm->_draw->_spriteLeft = _vm->_parse->parseValExpr(); - _vm->_draw->_spriteTop = _vm->_parse->parseValExpr(); - _vm->_draw->_spriteRight = _vm->_parse->parseValExpr(); - _vm->_draw->_spriteBottom = _vm->_parse->parseValExpr(); + _vm->_draw->_spriteLeft = _vm->_game->_script->readValExpr(); + _vm->_draw->_spriteTop = _vm->_game->_script->readValExpr(); + _vm->_draw->_spriteRight = _vm->_game->_script->readValExpr(); + _vm->_draw->_spriteBottom = _vm->_game->_script->readValExpr(); - _vm->_draw->_destSpriteX = _vm->_parse->parseValExpr(); - _vm->_draw->_destSpriteY = _vm->_parse->parseValExpr(); + _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr(); + _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr(); - _vm->_draw->_transparency = load16(); + _vm->_draw->_transparency = _vm->_game->_script->readInt16(); _vm->_draw->spriteOperation(DRAW_BLITSURF); return false; @@ -1901,14 +1423,14 @@ bool Inter_v1::o1_copySprite(OpFuncParams ¶ms) { bool Inter_v1::o1_fillRect(OpFuncParams ¶ms) { int16 destSurf; - _vm->_draw->_destSurface = destSurf = load16(); + _vm->_draw->_destSurface = destSurf = _vm->_game->_script->readInt16(); - _vm->_draw->_destSpriteX = _vm->_parse->parseValExpr(); - _vm->_draw->_destSpriteY = _vm->_parse->parseValExpr(); - _vm->_draw->_spriteRight = _vm->_parse->parseValExpr(); - _vm->_draw->_spriteBottom = _vm->_parse->parseValExpr(); + _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr(); + _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr(); + _vm->_draw->_spriteRight = _vm->_game->_script->readValExpr(); + _vm->_draw->_spriteBottom = _vm->_game->_script->readValExpr(); - _vm->_draw->_backColor = _vm->_parse->parseValExpr(); + _vm->_draw->_backColor = _vm->_game->_script->readValExpr(); if (!_vm->_draw->_spritesArray[(destSurf >= 100) ? (destSurf - 80) : destSurf]) return false; @@ -1927,14 +1449,14 @@ bool Inter_v1::o1_fillRect(OpFuncParams ¶ms) { } bool Inter_v1::o1_drawLine(OpFuncParams ¶ms) { - _vm->_draw->_destSurface = load16(); + _vm->_draw->_destSurface = _vm->_game->_script->readInt16(); - _vm->_draw->_destSpriteX = _vm->_parse->parseValExpr(); - _vm->_draw->_destSpriteY = _vm->_parse->parseValExpr(); - _vm->_draw->_spriteRight = _vm->_parse->parseValExpr(); - _vm->_draw->_spriteBottom = _vm->_parse->parseValExpr(); + _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr(); + _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr(); + _vm->_draw->_spriteRight = _vm->_game->_script->readValExpr(); + _vm->_draw->_spriteBottom = _vm->_game->_script->readValExpr(); - _vm->_draw->_frontColor = _vm->_parse->parseValExpr(); + _vm->_draw->_frontColor = _vm->_game->_script->readValExpr(); _vm->_draw->spriteOperation(DRAW_DRAWLINE); return false; } @@ -1945,28 +1467,28 @@ bool Inter_v1::o1_strToLong(OpFuncParams ¶ms) { int16 destVar; int32 res; - strVar = _vm->_parse->parseVarIndex(); + strVar = _vm->_game->_script->readVarIndex(); strncpy0(str, GET_VARO_STR(strVar), 19); res = atoi(str); - destVar = _vm->_parse->parseVarIndex(); + destVar = _vm->_game->_script->readVarIndex(); WRITE_VAR_OFFSET(destVar, res); return false; } bool Inter_v1::o1_invalidate(OpFuncParams ¶ms) { - _vm->_draw->_destSurface = load16(); - _vm->_draw->_destSpriteX = _vm->_parse->parseValExpr(); - _vm->_draw->_destSpriteY = _vm->_parse->parseValExpr(); - _vm->_draw->_spriteRight = _vm->_parse->parseValExpr(); - _vm->_draw->_frontColor = _vm->_parse->parseValExpr(); + _vm->_draw->_destSurface = _vm->_game->_script->readInt16(); + _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr(); + _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr(); + _vm->_draw->_spriteRight = _vm->_game->_script->readValExpr(); + _vm->_draw->_frontColor = _vm->_game->_script->readValExpr(); _vm->_draw->spriteOperation(DRAW_INVALIDATE); return false; } bool Inter_v1::o1_setBackDelta(OpFuncParams ¶ms) { - _vm->_draw->_backDeltaX = _vm->_parse->parseValExpr(); - _vm->_draw->_backDeltaY = _vm->_parse->parseValExpr(); + _vm->_draw->_backDeltaX = _vm->_game->_script->readValExpr(); + _vm->_draw->_backDeltaY = _vm->_game->_script->readValExpr(); return false; } @@ -1977,9 +1499,9 @@ bool Inter_v1::o1_playSound(OpFuncParams ¶ms) { int16 index; int16 endRep; - index = _vm->_parse->parseValExpr(); - repCount = _vm->_parse->parseValExpr(); - frequency = _vm->_parse->parseValExpr(); + index = _vm->_game->_script->readValExpr(); + repCount = _vm->_game->_script->readValExpr(); + frequency = _vm->_game->_script->readValExpr(); SoundDesc *sample = _vm->_sound->sampleGetBySlot(index); @@ -2002,7 +1524,7 @@ bool Inter_v1::o1_playSound(OpFuncParams ¶ms) { } if (sample->getType() == SOUND_ADL) { - _vm->_sound->adlibLoad(sample->getData(), sample->size(), index); + _vm->_sound->adlibLoadADL(sample->getData(), sample->size(), index); _vm->_sound->adlibSetRepeating(repCount - 1); _vm->_sound->adlibPlay(); } else { @@ -2015,7 +1537,7 @@ bool Inter_v1::o1_playSound(OpFuncParams ¶ms) { bool Inter_v1::o1_stopSound(OpFuncParams ¶ms) { _vm->_sound->adlibStop(); - _vm->_sound->blasterStop(_vm->_parse->parseValExpr()); + _vm->_sound->blasterStop(_vm->_game->_script->readValExpr()); _soundEndTimeKey = 0; return false; @@ -2041,8 +1563,8 @@ bool Inter_v1::o1_playComposition(OpFuncParams ¶ms) { int16 dataVar; int16 freqVal; - dataVar = _vm->_parse->parseVarIndex(); - freqVal = _vm->_parse->parseValExpr(); + dataVar = _vm->_game->_script->readVarIndex(); + freqVal = _vm->_game->_script->readValExpr(); for (int i = 0; i < 50; i++) composition[i] = (int16) VAR_OFFSET(dataVar + i * 4); @@ -2054,8 +1576,8 @@ bool Inter_v1::o1_getFreeMem(OpFuncParams ¶ms) { int16 freeVar; int16 maxFreeVar; - freeVar = _vm->_parse->parseVarIndex(); - maxFreeVar = _vm->_parse->parseVarIndex(); + freeVar = _vm->_game->_script->readVarIndex(); + maxFreeVar = _vm->_game->_script->readVarIndex(); // HACK WRITE_VAR_OFFSET(freeVar, 1000000); @@ -2067,22 +1589,22 @@ bool Inter_v1::o1_checkData(OpFuncParams ¶ms) { int16 handle; int16 varOff; - evalExpr(0); - varOff = _vm->_parse->parseVarIndex(); - handle = _vm->_dataIO->openData(_vm->_global->_inter_resStr); + _vm->_game->_script->evalExpr(0); + varOff = _vm->_game->_script->readVarIndex(); + handle = _vm->_dataIO->openData(_vm->_game->_script->getResultStr()); WRITE_VAR_OFFSET(varOff, handle); if (handle >= 0) _vm->_dataIO->closeData(handle); else - warning("File \"%s\" not found", _vm->_global->_inter_resStr); + warning("File \"%s\" not found", _vm->_game->_script->getResultStr()); return false; } bool Inter_v1::o1_prepareStr(OpFuncParams ¶ms) { int16 strVar; - strVar = _vm->_parse->parseVarIndex(); + strVar = _vm->_game->_script->readVarIndex(); _vm->_util->prepareStr(GET_VARO_FSTR(strVar)); return false; } @@ -2091,12 +1613,12 @@ bool Inter_v1::o1_insertStr(OpFuncParams ¶ms) { int16 pos; int16 strVar; - strVar = _vm->_parse->parseVarIndex(); - evalExpr(0); - pos = _vm->_parse->parseValExpr(); + strVar = _vm->_game->_script->readVarIndex(); + _vm->_game->_script->evalExpr(0); + pos = _vm->_game->_script->readValExpr(); char *str = GET_VARO_FSTR(strVar); - _vm->_util->insertStr(_vm->_global->_inter_resStr, str, pos); + _vm->_util->insertStr(_vm->_game->_script->getResultStr(), str, pos); return false; } @@ -2105,9 +1627,9 @@ bool Inter_v1::o1_cutStr(OpFuncParams ¶ms) { int16 pos; int16 size; - strVar = _vm->_parse->parseVarIndex(); - pos = _vm->_parse->parseValExpr(); - size = _vm->_parse->parseValExpr(); + strVar = _vm->_game->_script->readVarIndex(); + pos = _vm->_game->_script->readValExpr(); + size = _vm->_game->_script->readValExpr(); _vm->_util->cutFromStr(GET_VARO_STR(strVar), pos, size); return false; } @@ -2117,11 +1639,11 @@ bool Inter_v1::o1_strstr(OpFuncParams ¶ms) { int16 resVar; int16 pos; - strVar = _vm->_parse->parseVarIndex(); - evalExpr(0); - resVar = _vm->_parse->parseVarIndex(); + strVar = _vm->_game->_script->readVarIndex(); + _vm->_game->_script->evalExpr(0); + resVar = _vm->_game->_script->readVarIndex(); - char *res = strstr(GET_VARO_STR(strVar), _vm->_global->_inter_resStr); + char *res = strstr(GET_VARO_STR(strVar), _vm->_game->_script->getResultStr()); pos = res ? (res - (GET_VARO_STR(strVar))) : -1; WRITE_VAR_OFFSET(resVar, pos); return false; @@ -2131,17 +1653,17 @@ bool Inter_v1::o1_istrlen(OpFuncParams ¶ms) { int16 len; int16 strVar; - strVar = _vm->_parse->parseVarIndex(); + strVar = _vm->_game->_script->readVarIndex(); len = strlen(GET_VARO_STR(strVar)); - strVar = _vm->_parse->parseVarIndex(); + strVar = _vm->_game->_script->readVarIndex(); WRITE_VAR_OFFSET(strVar, len); return false; } bool Inter_v1::o1_setMousePos(OpFuncParams ¶ms) { - _vm->_global->_inter_mouseX = _vm->_parse->parseValExpr(); - _vm->_global->_inter_mouseY = _vm->_parse->parseValExpr(); + _vm->_global->_inter_mouseX = _vm->_game->_script->readValExpr(); + _vm->_global->_inter_mouseY = _vm->_game->_script->readValExpr(); _vm->_global->_inter_mouseX -= _vm->_video->_scrollOffsetX; _vm->_global->_inter_mouseY -= _vm->_video->_scrollOffsetY; if (_vm->_global->_useMouse != 0) @@ -2151,7 +1673,7 @@ bool Inter_v1::o1_setMousePos(OpFuncParams ¶ms) { } bool Inter_v1::o1_setFrameRate(OpFuncParams ¶ms) { - _vm->_util->setFrameRate(_vm->_parse->parseValExpr()); + _vm->_util->setFrameRate(_vm->_game->_script->readValExpr()); return false; } @@ -2177,27 +1699,23 @@ bool Inter_v1::o1_blitCursor(OpFuncParams ¶ms) { bool Inter_v1::o1_loadFont(OpFuncParams ¶ms) { int16 index; - evalExpr(0); - index = load16(); + _vm->_game->_script->evalExpr(0); + index = _vm->_game->_script->readInt16(); delete _vm->_draw->_fonts[index]; _vm->_draw->animateCursor(4); - if (_vm->_game->_extHandle >= 0) - _vm->_dataIO->closeData(_vm->_game->_extHandle); _vm->_draw->_fonts[index] = - _vm->_util->loadFont(_vm->_global->_inter_resStr); + _vm->_util->loadFont(_vm->_game->_script->getResultStr()); - if (_vm->_game->_extHandle >= 0) - _vm->_game->_extHandle = _vm->_dataIO->openData(_vm->_game->_curExtFile); return false; } bool Inter_v1::o1_freeFont(OpFuncParams ¶ms) { int16 index; - index = load16(); + index = _vm->_game->_script->readInt16(); delete _vm->_draw->_fonts[index]; _vm->_draw->_fonts[index] = 0; return false; @@ -2210,17 +1728,14 @@ bool Inter_v1::o1_readData(OpFuncParams ¶ms) { int16 offset; int16 handle; - evalExpr(0); - dataVar = _vm->_parse->parseVarIndex(); - size = _vm->_parse->parseValExpr(); - offset = _vm->_parse->parseValExpr(); + _vm->_game->_script->evalExpr(0); + dataVar = _vm->_game->_script->readVarIndex(); + size = _vm->_game->_script->readValExpr(); + offset = _vm->_game->_script->readValExpr(); retSize = 0; - if (_vm->_game->_extHandle >= 0) - _vm->_dataIO->closeData(_vm->_game->_extHandle); - WRITE_VAR(1, 1); - handle = _vm->_dataIO->openData(_vm->_global->_inter_resStr); + handle = _vm->_dataIO->openData(_vm->_game->_script->getResultStr()); if (handle >= 0) { DataStream *stream = _vm->_dataIO->openAsStream(handle, true); @@ -2241,8 +1756,6 @@ bool Inter_v1::o1_readData(OpFuncParams ¶ms) { delete stream; } - if (_vm->_game->_extHandle >= 0) - _vm->_game->_extHandle = _vm->_dataIO->openData(_vm->_game->_curExtFile); return false; } @@ -2255,22 +1768,22 @@ bool Inter_v1::o1_writeData(OpFuncParams ¶ms) { // (Gobliiins 1 doesn't use save file), so we just warn should it be // called regardless. - evalExpr(0); - dataVar = _vm->_parse->parseVarIndex(); - size = _vm->_parse->parseValExpr(); - offset = _vm->_parse->parseValExpr(); + _vm->_game->_script->evalExpr(0); + dataVar = _vm->_game->_script->readVarIndex(); + size = _vm->_game->_script->readValExpr(); + offset = _vm->_game->_script->readValExpr(); - warning("Attempted to write to file \"%s\"", _vm->_global->_inter_resStr); + warning("Attempted to write to file \"%s\"", _vm->_game->_script->getResultStr()); WRITE_VAR(1, 0); return false; } bool Inter_v1::o1_manageDataFile(OpFuncParams ¶ms) { - evalExpr(0); + _vm->_game->_script->evalExpr(0); - if (_vm->_global->_inter_resStr[0] != 0) - _vm->_dataIO->openDataFile(_vm->_global->_inter_resStr); + if (_vm->_game->_script->getResultStr()[0] != 0) + _vm->_dataIO->openDataFile(_vm->_game->_script->getResultStr()); else _vm->_dataIO->closeDataFile(); return false; @@ -2434,16 +1947,16 @@ void Inter_v1::o1_getMaxTick(OpGobParams ¶ms) { } void Inter_v1::o1_manipulateMap(OpGobParams ¶ms) { - int16 xPos = load16(); - int16 yPos = load16(); - int16 item = load16(); + int16 xPos = _vm->_game->_script->readInt16(); + int16 yPos = _vm->_game->_script->readInt16(); + int16 item = _vm->_game->_script->readInt16(); manipulateMap(xPos, yPos, item); } void Inter_v1::o1_getItem(OpGobParams ¶ms) { - int16 xPos = load16(); - int16 yPos = load16(); + int16 xPos = _vm->_game->_script->readInt16(); + int16 yPos = _vm->_game->_script->readInt16(); if ((_vm->_map->getItem(xPos, yPos) & 0xFF00) != 0) params.retVarPtr = (uint32) ((_vm->_map->getItem(xPos, yPos) & 0xFF00) >> 8); @@ -2452,9 +1965,9 @@ void Inter_v1::o1_getItem(OpGobParams ¶ms) { } void Inter_v1::o1_manipulateMapIndirect(OpGobParams ¶ms) { - int16 xPos = load16(); - int16 yPos = load16(); - int16 item = load16(); + int16 xPos = _vm->_game->_script->readInt16(); + int16 yPos = _vm->_game->_script->readInt16(); + int16 item = _vm->_game->_script->readInt16(); xPos = VAR(xPos); yPos = VAR(yPos); @@ -2464,8 +1977,8 @@ void Inter_v1::o1_manipulateMapIndirect(OpGobParams ¶ms) { } void Inter_v1::o1_getItemIndirect(OpGobParams ¶ms) { - int16 xPos = load16(); - int16 yPos = load16(); + int16 xPos = _vm->_game->_script->readInt16(); + int16 yPos = _vm->_game->_script->readInt16(); xPos = VAR(xPos); yPos = VAR(yPos); @@ -2477,17 +1990,17 @@ void Inter_v1::o1_getItemIndirect(OpGobParams ¶ms) { } void Inter_v1::o1_setPassMap(OpGobParams ¶ms) { - int16 xPos = load16(); - int16 yPos = load16(); - int16 val = load16(); + int16 xPos = _vm->_game->_script->readInt16(); + int16 yPos = _vm->_game->_script->readInt16(); + int16 val = _vm->_game->_script->readInt16(); _vm->_map->setPass(xPos, yPos, val); } void Inter_v1::o1_setGoblinPosH(OpGobParams ¶ms) { int16 layer; - int16 item = load16(); - int16 xPos = load16(); - int16 yPos = load16(); + int16 item = _vm->_game->_script->readInt16(); + int16 xPos = _vm->_game->_script->readInt16(); + int16 yPos = _vm->_game->_script->readInt16(); _vm->_goblin->_gobPositions[item].x = xPos * 2; _vm->_goblin->_gobPositions[item].y = yPos * 2; @@ -2522,20 +2035,20 @@ void Inter_v1::o1_setGoblinPosH(OpGobParams ¶ms) { } void Inter_v1::o1_getGoblinPosXH(OpGobParams ¶ms) { - int16 item = load16(); + int16 item = _vm->_game->_script->readInt16(); params.retVarPtr = (uint32) (_vm->_goblin->_gobPositions[item].x >> 1); } void Inter_v1::o1_getGoblinPosYH(OpGobParams ¶ms) { - int16 item = load16(); + int16 item = _vm->_game->_script->readInt16(); params.retVarPtr = (uint32) (_vm->_goblin->_gobPositions[item].y >> 1); } void Inter_v1::o1_setGoblinMultState(OpGobParams ¶ms) { int16 layer; - int16 item = load16(); - int16 xPos = load16(); - int16 yPos = load16(); + int16 item = _vm->_game->_script->readInt16(); + int16 xPos = _vm->_game->_script->readInt16(); + int16 yPos = _vm->_game->_script->readInt16(); params.objDesc = _vm->_goblin->_goblins[item]; if (yPos == 0) { @@ -2594,18 +2107,18 @@ void Inter_v1::o1_setGoblinMultState(OpGobParams ¶ms) { } void Inter_v1::o1_setGoblinUnk14(OpGobParams ¶ms) { - int16 item = load16(); - int16 val = load16(); + int16 item = _vm->_game->_script->readInt16(); + int16 val = _vm->_game->_script->readInt16(); params.objDesc = _vm->_goblin->_objects[item]; params.objDesc->unk14 = val; } void Inter_v1::o1_setItemIdInPocket(OpGobParams ¶ms) { - _vm->_goblin->_itemIdInPocket = load16(); + _vm->_goblin->_itemIdInPocket = _vm->_game->_script->readInt16(); } void Inter_v1::o1_setItemIndInPocket(OpGobParams ¶ms) { - _vm->_goblin->_itemIndInPocket = load16(); + _vm->_goblin->_itemIndInPocket = _vm->_game->_script->readInt16(); } void Inter_v1::o1_getItemIdInPocket(OpGobParams ¶ms) { @@ -2618,9 +2131,9 @@ void Inter_v1::o1_getItemIndInPocket(OpGobParams ¶ms) { void Inter_v1::o1_setGoblinPos(OpGobParams ¶ms) { int16 layer; - int16 item = load16(); - int16 xPos = load16(); - int16 yPos = load16(); + int16 item = _vm->_game->_script->readInt16(); + int16 xPos = _vm->_game->_script->readInt16(); + int16 yPos = _vm->_game->_script->readInt16(); _vm->_goblin->_gobPositions[item].x = xPos; _vm->_goblin->_gobPositions[item].y = yPos; @@ -2655,8 +2168,8 @@ void Inter_v1::o1_setGoblinPos(OpGobParams ¶ms) { void Inter_v1::o1_setGoblinState(OpGobParams ¶ms) { int16 layer; - int16 item = load16(); - int16 state = load16(); + int16 item = _vm->_game->_script->readInt16(); + int16 state = _vm->_game->_script->readInt16(); params.objDesc = _vm->_goblin->_goblins[item]; params.objDesc->nextState = state; @@ -2680,8 +2193,8 @@ void Inter_v1::o1_setGoblinState(OpGobParams ¶ms) { void Inter_v1::o1_setGoblinStateRedraw(OpGobParams ¶ms) { int16 layer; - int16 item = load16(); - int16 state = load16(); + int16 item = _vm->_game->_script->readInt16(); + int16 state = _vm->_game->_script->readInt16(); params.objDesc = _vm->_goblin->_objects[item]; params.objDesc->nextState = state; @@ -2708,7 +2221,7 @@ void Inter_v1::o1_setGoblinStateRedraw(OpGobParams ¶ms) { } void Inter_v1::o1_decRelaxTime(OpGobParams ¶ms) { - params.extraData = load16(); + params.extraData = _vm->_game->_script->readInt16(); params.objDesc = _vm->_goblin->_objects[params.extraData]; params.objDesc->relaxTime--; @@ -2722,12 +2235,12 @@ void Inter_v1::o1_decRelaxTime(OpGobParams ¶ms) { } void Inter_v1::o1_getGoblinPosX(OpGobParams ¶ms) { - int16 item = load16(); + int16 item = _vm->_game->_script->readInt16(); params.retVarPtr = (uint32) _vm->_goblin->_gobPositions[item].x; } void Inter_v1::o1_getGoblinPosY(OpGobParams ¶ms) { - int16 item = load16(); + int16 item = _vm->_game->_script->readInt16(); params.retVarPtr = (uint32) _vm->_goblin->_gobPositions[item].y; } @@ -2736,18 +2249,18 @@ void Inter_v1::o1_clearPathExistence(OpGobParams ¶ms) { } void Inter_v1::o1_setGoblinVisible(OpGobParams ¶ms) { - params.extraData = load16(); + params.extraData = _vm->_game->_script->readInt16(); _vm->_goblin->_goblins[params.extraData]->visible = 1; } void Inter_v1::o1_setGoblinInvisible(OpGobParams ¶ms) { - params.extraData = load16(); + params.extraData = _vm->_game->_script->readInt16(); _vm->_goblin->_goblins[params.extraData]->visible = 0; } void Inter_v1::o1_getObjectIntersect(OpGobParams ¶ms) { - params.extraData = load16(); - int16 item = load16(); + params.extraData = _vm->_game->_script->readInt16(); + int16 item = _vm->_game->_script->readInt16(); params.objDesc = _vm->_goblin->_objects[params.extraData]; if (_vm->_goblin->objIntersected(params.objDesc, @@ -2758,8 +2271,8 @@ void Inter_v1::o1_getObjectIntersect(OpGobParams ¶ms) { } void Inter_v1::o1_getGoblinIntersect(OpGobParams ¶ms) { - params.extraData = load16(); - int16 item = load16(); + params.extraData = _vm->_game->_script->readInt16(); + int16 item = _vm->_game->_script->readInt16(); params.objDesc = _vm->_goblin->_goblins[params.extraData]; if (_vm->_goblin->objIntersected(params.objDesc, @@ -2770,10 +2283,10 @@ void Inter_v1::o1_getGoblinIntersect(OpGobParams ¶ms) { } void Inter_v1::o1_setItemPos(OpGobParams ¶ms) { - int16 item = load16(); - int16 xPos = load16(); - int16 yPos = load16(); - int16 val = load16(); + int16 item = _vm->_game->_script->readInt16(); + int16 xPos = _vm->_game->_script->readInt16(); + int16 yPos = _vm->_game->_script->readInt16(); + int16 val = _vm->_game->_script->readInt16(); _vm->_map->_itemPoses[item].x = xPos; _vm->_map->_itemPoses[item].y = yPos; @@ -2781,12 +2294,9 @@ void Inter_v1::o1_setItemPos(OpGobParams ¶ms) { } void Inter_v1::o1_loadObjects(OpGobParams ¶ms) { - params.extraData = load16(); - if (_vm->_game->_extHandle >= 0) - _vm->_dataIO->closeData(_vm->_game->_extHandle); + params.extraData = _vm->_game->_script->readInt16(); _vm->_goblin->loadObjects((char *) VAR_ADDRESS(params.extraData)); - _vm->_game->_extHandle = _vm->_dataIO->openData(_vm->_game->_curExtFile); } void Inter_v1::o1_freeObjects(OpGobParams ¶ms) { @@ -2811,8 +2321,8 @@ void Inter_v1::o1_loadMap(OpGobParams ¶ms) { void Inter_v1::o1_moveGoblin(OpGobParams ¶ms) { int16 item; - params.extraData = load16(); - int16 xPos = load16(); + params.extraData = _vm->_game->_script->readInt16(); + int16 xPos = _vm->_game->_script->readInt16(); if ((uint16) VAR(xPos) == 0) { item = @@ -2837,9 +2347,9 @@ void Inter_v1::o1_loadGoblin(OpGobParams ¶ms) { } void Inter_v1::o1_writeTreatItem(OpGobParams ¶ms) { - params.extraData = load16(); - int16 cmd = load16(); - int16 xPos = load16(); + params.extraData = _vm->_game->_script->readInt16(); + int16 cmd = _vm->_game->_script->readInt16(); + int16 xPos = _vm->_game->_script->readInt16(); if ((uint16) VAR(xPos) == 0) { WRITE_VAR(cmd, _vm->_goblin->treatItem((uint16) VAR(params.extraData))); @@ -2855,7 +2365,7 @@ void Inter_v1::o1_moveGoblin0(OpGobParams ¶ms) { } void Inter_v1::o1_setGoblinTarget(OpGobParams ¶ms) { - params.extraData = load16(); + params.extraData = _vm->_game->_script->readInt16(); if (VAR(params.extraData) != 0) _vm->_goblin->_goesAtTarget = 1; else @@ -2863,11 +2373,11 @@ void Inter_v1::o1_setGoblinTarget(OpGobParams ¶ms) { } void Inter_v1::o1_setGoblinObjectsPos(OpGobParams ¶ms) { - params.extraData = load16(); + params.extraData = _vm->_game->_script->readInt16(); params.extraData = VAR(params.extraData); _vm->_goblin->_objects[10]->xPos = params.extraData; - params.extraData = load16(); + params.extraData = _vm->_game->_script->readInt16(); params.extraData = VAR(params.extraData); _vm->_goblin->_objects[10]->yPos = params.extraData; } @@ -2961,38 +2471,24 @@ void Inter_v1::o1_initGoblin(OpGobParams ¶ms) { } int16 Inter_v1::loadSound(int16 slot) { - byte *dataPtr; - int16 id; - uint32 dataSize; - SoundSource source; - if (slot == -1) - slot = _vm->_parse->parseValExpr(); + slot = _vm->_game->_script->readValExpr(); - id = load16(); - if (id == -1) { - _vm->_global->_inter_execPtr += 9; + uint16 id = _vm->_game->_script->readUint16(); + if (id == 0xFFFF) { + _vm->_game->_script->skip(9); return 0; } - if (id >= 30000) { - source = SOUND_EXT; - - dataPtr = (byte *) _vm->_game->loadExtData(id, 0, 0, &dataSize); - } else { - int16 totSize; - - source = SOUND_TOT; + Resource *resource = _vm->_game->_resources->getResource(id); + if (!resource) + return 0; - dataPtr = (byte *) _vm->_game->loadTotResource(id, &totSize); - dataSize = (uint32) ((int32) totSize); - } + SoundDesc *sample = _vm->_sound->sampleGetBySlot(slot); + if (!sample) + return 0; - if (dataPtr) { - SoundDesc *sample = _vm->_sound->sampleGetBySlot(slot); - if (sample) - sample->load(SOUND_SND, source, dataPtr, dataSize); - } + sample->load(SOUND_SND, resource); return 0; } diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp index 3107fcf9bc..82822330b1 100644 --- a/engines/gob/inter_v2.cpp +++ b/engines/gob/inter_v2.cpp @@ -36,10 +36,12 @@ #include "gob/dataio.h" #include "gob/draw.h" #include "gob/game.h" +#include "gob/expression.h" +#include "gob/script.h" +#include "gob/resources.h" #include "gob/goblin.h" #include "gob/map.h" #include "gob/mult.h" -#include "gob/parse.h" #include "gob/scenery.h" #include "gob/video.h" #include "gob/save/saveload.h" @@ -48,673 +50,126 @@ namespace Gob { -#define OPCODE(x) _OPCODE(Inter_v2, x) - -const int Inter_v2::_goblinFuncLookUp[][2] = { - {0, 0}, - {1, 1}, - {2, 2}, - {4, 3}, - {5, 4}, - {6, 5}, - {7, 6}, - {8, 7}, - {9, 8}, - {10, 9}, - {12, 10}, - {13, 11}, - {14, 12}, - {15, 13}, - {16, 14}, - {21, 15}, - {22, 16}, - {23, 17}, - {24, 18}, - {25, 19}, - {26, 20}, - {27, 21}, - {28, 22}, - {29, 23}, - {30, 24}, - {32, 25}, - {33, 26}, - {34, 27}, - {35, 28}, - {36, 29}, - {37, 30}, - {40, 31}, - {41, 32}, - {42, 33}, - {43, 34}, - {44, 35}, - {50, 36}, - {52, 37}, - {53, 38}, - {100, 39}, - {500, 40}, - {501, 41} -}; +#define OPCODEVER Inter_v2 +#define OPCODEDRAW(i, x) _opcodesDraw[i]._OPCODEDRAW(OPCODEVER, x) +#define OPCODEFUNC(i, x) _opcodesFunc[i]._OPCODEFUNC(OPCODEVER, x) +#define OPCODEGOB(i, x) _opcodesGob[i]._OPCODEGOB(OPCODEVER, x) Inter_v2::Inter_v2(GobEngine *vm) : Inter_v1(vm) { - setupOpcodes(); } -void Inter_v2::setupOpcodes() { - static const OpcodeDrawEntryV2 opcodesDraw[256] = { - /* 00 */ - OPCODE(o1_loadMult), - OPCODE(o2_playMult), - OPCODE(o2_freeMultKeys), - {0, ""}, - /* 04 */ - {0, ""}, - {0, ""}, - {0, ""}, - OPCODE(o1_initCursor), - /* 08 */ - OPCODE(o1_initCursorAnim), - OPCODE(o1_clearCursorAnim), - OPCODE(o2_setRenderFlags), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - OPCODE(o1_loadAnim), - OPCODE(o1_freeAnim), - OPCODE(o1_updateAnim), - OPCODE(o2_multSub), - /* 14 */ - OPCODE(o2_initMult), - OPCODE(o1_freeMult), - OPCODE(o1_animate), - OPCODE(o2_loadMultObject), - /* 18 */ - OPCODE(o1_getAnimLayerInfo), - OPCODE(o1_getObjAnimSize), - OPCODE(o1_loadStatic), - OPCODE(o1_freeStatic), - /* 1C */ - OPCODE(o2_renderStatic), - OPCODE(o2_loadCurLayer), - {0, ""}, - {0, ""}, - /* 20 */ - OPCODE(o2_playCDTrack), - OPCODE(o2_waitCDTrackEnd), - OPCODE(o2_stopCD), - OPCODE(o2_readLIC), - /* 24 */ - OPCODE(o2_freeLIC), - OPCODE(o2_getCDTrackPos), - {0, ""}, - {0, ""}, - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o2_loadFontToSprite), - OPCODE(o1_freeFontToSprite), - {0, ""}, - {0, ""}, - /* 34 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 38 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 3C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 40 */ - OPCODE(o2_totSub), - OPCODE(o2_switchTotSub), - OPCODE(o2_pushVars), - OPCODE(o2_popVars), - /* 44 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 48 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 4C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 50 */ - OPCODE(o2_loadMapObjects), - OPCODE(o2_freeGoblins), - OPCODE(o2_moveGoblin), - OPCODE(o2_writeGoblinPos), - /* 54 */ - OPCODE(o2_stopGoblin), - OPCODE(o2_setGoblinState), - OPCODE(o2_placeGoblin), - {0, ""}, - /* 58 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 5C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 60 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 64 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 68 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 6C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 70 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 74 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 78 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 7C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 80 */ - OPCODE(o2_initScreen), - OPCODE(o2_scroll), - OPCODE(o2_setScrollOffset), - OPCODE(o2_playImd), - /* 84 */ - OPCODE(o2_getImdInfo), - OPCODE(o2_openItk), - OPCODE(o2_closeItk), - OPCODE(o2_setImdFrontSurf), - /* 88 */ - OPCODE(o2_resetImdFrontSurf), - {0, ""}, - {0, ""}, - {0, ""}, - /* 8C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 90 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 94 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 98 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 9C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* AC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* BC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* CC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* DC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* EC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* FC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""} - }; - - static const OpcodeFuncEntryV2 opcodesFunc[80] = { - /* 00 */ - OPCODE(o1_callSub), - OPCODE(o1_callSub), - OPCODE(o1_printTotText), - OPCODE(o1_loadCursor), - /* 04 */ - {0, ""}, - OPCODE(o1_switch), - OPCODE(o1_repeatUntil), - OPCODE(o1_whileDo), - /* 08 */ - OPCODE(o1_if), - OPCODE(o2_assign), - OPCODE(o1_loadSpriteToPos), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - {0, ""}, - OPCODE(o2_printText), - OPCODE(o1_loadTot), - OPCODE(o1_palLoad), - /* 14 */ - OPCODE(o1_keyFunc), - OPCODE(o1_capturePush), - OPCODE(o1_capturePop), - OPCODE(o2_animPalInit), - /* 18 */ - OPCODE(o2_addCollision), - OPCODE(o2_freeCollision), - {0, ""}, - {0, ""}, - /* 1C */ - {0, ""}, - {0, ""}, - OPCODE(o1_drawOperations), - OPCODE(o1_setcmdCount), - /* 20 */ - OPCODE(o1_return), - OPCODE(o1_renewTimeInVars), - OPCODE(o1_speakerOn), - OPCODE(o1_speakerOff), - /* 24 */ - OPCODE(o1_putPixel), - OPCODE(o2_goblinFunc), - OPCODE(o1_createSprite), - OPCODE(o1_freeSprite), - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o1_returnTo), - OPCODE(o1_loadSpriteContent), - OPCODE(o1_copySprite), - OPCODE(o1_fillRect), - /* 34 */ - OPCODE(o1_drawLine), - OPCODE(o1_strToLong), - OPCODE(o1_invalidate), - OPCODE(o1_setBackDelta), - /* 38 */ - OPCODE(o1_playSound), - OPCODE(o2_stopSound), - OPCODE(o2_loadSound), - OPCODE(o1_freeSoundSlot), - /* 3C */ - OPCODE(o1_waitEndPlay), - OPCODE(o1_playComposition), - OPCODE(o2_getFreeMem), - OPCODE(o2_checkData), - /* 40 */ - {0, ""}, - OPCODE(o1_prepareStr), - OPCODE(o1_insertStr), - OPCODE(o1_cutStr), - /* 44 */ - OPCODE(o1_strstr), - OPCODE(o1_istrlen), - OPCODE(o1_setMousePos), - OPCODE(o1_setFrameRate), - /* 48 */ - OPCODE(o1_animatePalette), - OPCODE(o1_animateCursor), - OPCODE(o1_blitCursor), - OPCODE(o1_loadFont), - /* 4C */ - OPCODE(o1_freeFont), - OPCODE(o2_readData), - OPCODE(o2_writeData), - OPCODE(o1_manageDataFile), - }; - - static const OpcodeGoblinEntryV2 opcodesGoblin[71] = { - /* 00 */ - OPCODE(o2_loadInfogramesIns), - OPCODE(o2_startInfogrames), - OPCODE(o2_stopInfogrames), - {0, ""}, - /* 04 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 08 */ - {0, ""}, - OPCODE(o2_playInfogrames), - {0, ""}, - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 14 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 18 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 1C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 20 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 24 */ - {0, ""}, - {0, ""}, - {0, ""}, - OPCODE(o2_handleGoblins), - /* 28 */ - OPCODE(o2_playProtracker), - OPCODE(o2_stopProtracker), - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 34 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 38 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 3C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 40 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 44 */ - {0, ""}, - {0, ""}, - {0, ""}, - }; - - _opcodesDrawV2 = opcodesDraw; - _opcodesFuncV2 = opcodesFunc; - _opcodesGoblinV2 = opcodesGoblin; -} +void Inter_v2::setupOpcodesDraw() { + Inter_v1::setupOpcodesDraw(); -void Inter_v2::executeDrawOpcode(byte i) { - debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)", - i, i, getOpcodeDrawDesc(i)); + OPCODEDRAW(0x01, o2_playMult); + OPCODEDRAW(0x02, o2_freeMultKeys); - OpcodeDrawProcV2 op = _opcodesDrawV2[i].proc; + OPCODEDRAW(0x0A, o2_setRenderFlags); - if (op == 0) - warning("unimplemented opcodeDraw: %d", i); - else - (this->*op) (); -} + OPCODEDRAW(0x13, o2_multSub); -bool Inter_v2::executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms) { - debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s)", - i, j, i, j, getOpcodeFuncDesc(i, j)); + OPCODEDRAW(0x14, o2_initMult); - if ((i > 4) || (j > 15)) { - warning("unimplemented opcodeFunc: %d.%d", i, j); - return false; - } + OPCODEDRAW(0x17, o2_loadMultObject); - OpcodeFuncProcV2 op = _opcodesFuncV2[i*16 + j].proc; + OPCODEDRAW(0x1C, o2_renderStatic); + OPCODEDRAW(0x1D, o2_loadCurLayer); - if (op == 0) - warning("unimplemented opcodeFunc: %d.%d", i, j); - else - return (this->*op) (params); + OPCODEDRAW(0x20, o2_playCDTrack); + OPCODEDRAW(0x21, o2_waitCDTrackEnd); + OPCODEDRAW(0x22, o2_stopCD); + OPCODEDRAW(0x23, o2_readLIC); - return false; -} + OPCODEDRAW(0x24, o2_freeLIC); + OPCODEDRAW(0x25, o2_getCDTrackPos); -void Inter_v2::executeGoblinOpcode(int i, OpGobParams ¶ms) { - debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)", - i, i, getOpcodeGoblinDesc(i)); + OPCODEDRAW(0x30, o2_loadFontToSprite); - OpcodeGoblinProcV2 op = 0; + OPCODEDRAW(0x40, o2_totSub); + OPCODEDRAW(0x41, o2_switchTotSub); + OPCODEDRAW(0x42, o2_pushVars); + OPCODEDRAW(0x43, o2_popVars); - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) { - op = _opcodesGoblinV2[_goblinFuncLookUp[j][1]].proc; - break; - } + OPCODEDRAW(0x50, o2_loadMapObjects); + OPCODEDRAW(0x51, o2_freeGoblins); + OPCODEDRAW(0x52, o2_moveGoblin); + OPCODEDRAW(0x53, o2_writeGoblinPos); - if (op == 0) { - int16 val; + OPCODEDRAW(0x54, o2_stopGoblin); + OPCODEDRAW(0x55, o2_setGoblinState); + OPCODEDRAW(0x56, o2_placeGoblin); - _vm->_global->_inter_execPtr -= 2; - val = load16(); - _vm->_global->_inter_execPtr += val << 1; - } else - (this->*op) (params); -} + OPCODEDRAW(0x80, o2_initScreen); + OPCODEDRAW(0x81, o2_scroll); + OPCODEDRAW(0x82, o2_setScrollOffset); + OPCODEDRAW(0x83, o2_playImd); + + OPCODEDRAW(0x84, o2_getImdInfo); + OPCODEDRAW(0x85, o2_openItk); + OPCODEDRAW(0x86, o2_closeItk); + OPCODEDRAW(0x87, o2_setImdFrontSurf); -const char *Inter_v2::getOpcodeDrawDesc(byte i) { - return _opcodesDrawV2[i].desc; + OPCODEDRAW(0x88, o2_resetImdFrontSurf); } -const char *Inter_v2::getOpcodeFuncDesc(byte i, byte j) { - if ((i > 4) || (j > 15)) - return ""; +void Inter_v2::setupOpcodesFunc() { + Inter_v1::setupOpcodesFunc(); + + OPCODEFUNC(0x09, o2_assign); + + OPCODEFUNC(0x11, o2_printText); + + OPCODEFUNC(0x17, o2_animPalInit); - return _opcodesFuncV2[i*16 + j].desc; + OPCODEFUNC(0x18, o2_addCollision); + OPCODEFUNC(0x19, o2_freeCollision); + + OPCODEFUNC(0x25, o2_goblinFunc); + + OPCODEFUNC(0x39, o2_stopSound); + OPCODEFUNC(0x3A, o2_loadSound); + + OPCODEFUNC(0x3E, o2_getFreeMem); + OPCODEFUNC(0x3F, o2_checkData); + + OPCODEFUNC(0x4D, o2_readData); + OPCODEFUNC(0x4E, o2_writeData); } -const char *Inter_v2::getOpcodeGoblinDesc(int i) { - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) - return _opcodesGoblinV2[_goblinFuncLookUp[j][1]].desc; - return ""; +void Inter_v2::setupOpcodesGob() { + OPCODEGOB( 0, o2_loadInfogramesIns); + OPCODEGOB( 1, o2_startInfogrames); + OPCODEGOB( 2, o2_stopInfogrames); + + OPCODEGOB( 10, o2_playInfogrames); + + OPCODEGOB(100, o2_handleGoblins); + + OPCODEGOB(500, o2_playProtracker); + OPCODEGOB(501, o2_stopProtracker); } -void Inter_v2::checkSwitchTable(byte **ppExec) { - byte cmd; +void Inter_v2::checkSwitchTable(uint32 &offset) { + byte type; int16 len; int32 value; bool found; found = false; - *ppExec = 0; + offset = 0; - cmd = *_vm->_global->_inter_execPtr; + type = _vm->_game->_script->peekByte(); - value = _vm->_parse->parseVarIndex(); + value = _vm->_game->_script->readVarIndex(); - switch (cmd) { - case 16: - case 18: + switch (type) { + case TYPE_VAR_INT8: + case TYPE_ARRAY_INT8: value = (int8) READ_VARO_UINT8(value); break; - case 23: - case 26: + case TYPE_VAR_INT32: + case TYPE_ARRAY_INT32: value = READ_VARO_UINT32(value); break; @@ -726,78 +181,74 @@ void Inter_v2::checkSwitchTable(byte **ppExec) { if (_terminate) return; - len = (int8) *_vm->_global->_inter_execPtr++; + len = _vm->_game->_script->readInt8(); while (len != -5) { for (int i = 0; i < len; i++) { - cmd = *_vm->_global->_inter_execPtr; + type = _vm->_game->_script->peekByte(); - switch (cmd) { - case 19: - _vm->_global->_inter_execPtr++; + switch (type) { + case TYPE_IMM_INT32: + _vm->_game->_script->skip(1); if (!found && - (value == - (int32) (READ_LE_UINT32(_vm->_global->_inter_execPtr)))) + (value == _vm->_game->_script->peekInt32())) found = true; - _vm->_global->_inter_execPtr += 5; + _vm->_game->_script->skip(5); break; - case 20: - _vm->_global->_inter_execPtr++; + case TYPE_IMM_INT16: + _vm->_game->_script->skip(1); if (!found && - (value == - (int16) (READ_LE_UINT16(_vm->_global->_inter_execPtr)))) + (value == _vm->_game->_script->peekInt16())) found = true; - _vm->_global->_inter_execPtr += 3; + _vm->_game->_script->skip(3); break; - case 21: - _vm->_global->_inter_execPtr++; - if (!found && (value == (int8) *_vm->_global->_inter_execPtr)) + case TYPE_IMM_INT8: + _vm->_game->_script->skip(1); + if (!found && (value == _vm->_game->_script->peekInt8())) found = true; - _vm->_global->_inter_execPtr += 2; + _vm->_game->_script->skip(2); break; default: if (!found) { - evalExpr(0); - if (value == _vm->_global->_inter_resVal) + _vm->_game->_script->evalExpr(0); + if (value == _vm->_game->_script->getResultInt()) found = true; } else - _vm->_parse->skipExpr(99); + _vm->_game->_script->skipExpr(99); break; } } - if (found && !*ppExec) - *ppExec = _vm->_global->_inter_execPtr; + if (found && (offset == 0)) + offset = _vm->_game->_script->pos(); - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2; - len = (int8) *_vm->_global->_inter_execPtr++; + _vm->_game->_script->skip(_vm->_game->_script->peekUint16(2) + 2); + len = _vm->_game->_script->readInt8(); } - if ((*_vm->_global->_inter_execPtr >> 4) != 4) + if ((_vm->_game->_script->peekByte() >> 4) != 4) return; - _vm->_global->_inter_execPtr++; - if (!*ppExec) - *ppExec = _vm->_global->_inter_execPtr; + _vm->_game->_script->skip(1); + if (offset == 0) + offset = _vm->_game->_script->pos(); - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2; + _vm->_game->_script->skip(_vm->_game->_script->peekUint16(2) + 2); } void Inter_v2::o2_playMult() { int16 checkEscape; - checkEscape = load16(); + checkEscape = _vm->_game->_script->readInt16(); _vm->_mult->setMultData(checkEscape >> 1); _vm->_mult->playMult(VAR(57), -1, checkEscape & 0x1, 0); } void Inter_v2::o2_freeMultKeys() { - uint16 index = load16(); + uint16 index = _vm->_game->_script->readUint16(); if (!_vm->_mult->hasMultData(index)) return; @@ -810,7 +261,7 @@ void Inter_v2::o2_freeMultKeys() { void Inter_v2::o2_setRenderFlags() { int16 expr; - expr = _vm->_parse->parseValExpr(); + expr = _vm->_game->_script->readValExpr(); if (expr & 0x8000) { _vm->_draw->_renderFlags |= expr & 0x3FFF; @@ -823,7 +274,7 @@ void Inter_v2::o2_setRenderFlags() { } void Inter_v2::o2_multSub() { - _vm->_mult->multSub(_vm->_parse->parseValExpr()); + _vm->_mult->multSub(_vm->_game->_script->readValExpr()); } void Inter_v2::o2_initMult() { @@ -838,14 +289,14 @@ void Inter_v2::o2_initMult() { oldAnimHeight = _vm->_mult->_animHeight; oldObjCount = _vm->_mult->_objCount; - _vm->_mult->_animLeft = load16(); - _vm->_mult->_animTop = load16(); - _vm->_mult->_animWidth = load16(); - _vm->_mult->_animHeight = load16(); - _vm->_mult->_objCount = load16(); - posXVar = _vm->_parse->parseVarIndex(); - posYVar = _vm->_parse->parseVarIndex(); - animDataVar = _vm->_parse->parseVarIndex(); + _vm->_mult->_animLeft = _vm->_game->_script->readInt16(); + _vm->_mult->_animTop = _vm->_game->_script->readInt16(); + _vm->_mult->_animWidth = _vm->_game->_script->readInt16(); + _vm->_mult->_animHeight = _vm->_game->_script->readInt16(); + _vm->_mult->_objCount = _vm->_game->_script->readInt16(); + posXVar = _vm->_game->_script->readVarIndex(); + posYVar = _vm->_game->_script->readVarIndex(); + animDataVar = _vm->_game->_script->readVarIndex(); if (_vm->_mult->_objects && (oldObjCount != _vm->_mult->_objCount)) { warning("Initializing new objects without having " @@ -947,20 +398,20 @@ void Inter_v2::o2_loadMultObject() { int16 layer; byte *multData; - objIndex = _vm->_parse->parseValExpr(); - val = _vm->_parse->parseValExpr(); + objIndex = _vm->_game->_script->readValExpr(); + val = _vm->_game->_script->readValExpr(); *_vm->_mult->_objects[objIndex].pPosX = val; - val = _vm->_parse->parseValExpr(); + val = _vm->_game->_script->readValExpr(); *_vm->_mult->_objects[objIndex].pPosY = val; debugC(4, kDebugGameFlow, "Loading mult object %d", objIndex); multData = (byte *) _vm->_mult->_objects[objIndex].pAnimData; for (int i = 0; i < 11; i++) { - if (*_vm->_global->_inter_execPtr != 99) - multData[i] = _vm->_parse->parseValExpr(); + if (_vm->_game->_script->peekByte() != 99) + multData[i] = _vm->_game->_script->readValExpr(); else - _vm->_global->_inter_execPtr++; + _vm->_game->_script->skip(1); } Mult::Mult_Object &obj = _vm->_mult->_objects[objIndex]; @@ -1043,22 +494,22 @@ void Inter_v2::o2_renderStatic() { int16 layer; int16 index; - index = _vm->_parse->parseValExpr(); - layer = _vm->_parse->parseValExpr(); + index = _vm->_game->_script->readValExpr(); + layer = _vm->_game->_script->readValExpr(); _vm->_scenery->renderStatic(index, layer); } void Inter_v2::o2_loadCurLayer() { - _vm->_scenery->_curStatic = _vm->_parse->parseValExpr(); - _vm->_scenery->_curStaticLayer = _vm->_parse->parseValExpr(); + _vm->_scenery->_curStatic = _vm->_game->_script->readValExpr(); + _vm->_scenery->_curStaticLayer = _vm->_game->_script->readValExpr(); } void Inter_v2::o2_playCDTrack() { if (!(_vm->_draw->_renderFlags & RENDERFLAG_NOBLITINVALIDATED)) _vm->_draw->blitInvalidated(); - evalExpr(0); - _vm->_sound->cdPlay(_vm->_global->_inter_resStr); + _vm->_game->_script->evalExpr(0); + _vm->_sound->cdPlay(_vm->_game->_script->getResultStr()); } void Inter_v2::o2_waitCDTrackEnd() { @@ -1075,8 +526,8 @@ void Inter_v2::o2_stopCD() { void Inter_v2::o2_readLIC() { char path[40]; - evalExpr(0); - strncpy0(path, _vm->_global->_inter_resStr, 35); + _vm->_game->_script->evalExpr(0); + strncpy0(path, _vm->_game->_script->getResultStr(), 35); strcat(path, ".LIC"); _vm->_sound->cdLoadLIC(path); @@ -1092,24 +543,24 @@ void Inter_v2::o2_getCDTrackPos() { _vm->_util->longDelay(1); - varPos = _vm->_parse->parseVarIndex(); - varName = _vm->_parse->parseVarIndex(); + varPos = _vm->_game->_script->readVarIndex(); + varName = _vm->_game->_script->readVarIndex(); WRITE_VAR_OFFSET(varPos, _vm->_sound->cdGetTrackPos(GET_VARO_STR(varName))); WRITE_VARO_STR(varName, _vm->_sound->cdGetCurrentTrack()); } void Inter_v2::o2_loadFontToSprite() { - int16 i = load16(); - - _vm->_draw->_fontToSprite[i].sprite = *_vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += 2; - _vm->_draw->_fontToSprite[i].base = *_vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += 2; - _vm->_draw->_fontToSprite[i].width = *_vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += 2; - _vm->_draw->_fontToSprite[i].height = *_vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += 2; + int16 i = _vm->_game->_script->readInt16(); + + _vm->_draw->_fontToSprite[i].sprite = _vm->_game->_script->readByte(); + _vm->_game->_script->skip(1); + _vm->_draw->_fontToSprite[i].base = _vm->_game->_script->readByte(); + _vm->_game->_script->skip(1); + _vm->_draw->_fontToSprite[i].width = _vm->_game->_script->readByte(); + _vm->_game->_script->skip(1); + _vm->_draw->_fontToSprite[i].height = _vm->_game->_script->readByte(); + _vm->_game->_script->skip(1); } void Inter_v2::o2_totSub() { @@ -1118,16 +569,16 @@ void Inter_v2::o2_totSub() { int flags; int i; - length = *_vm->_global->_inter_execPtr++; + length = _vm->_game->_script->readByte(); if ((length & 0x7F) > 13) error("Length in o2_totSub is greater than 13 (%d)", length); if (length & 0x80) { - evalExpr(0); - strcpy(totFile, _vm->_global->_inter_resStr); + _vm->_game->_script->evalExpr(0); + strcpy(totFile, _vm->_game->_script->getResultStr()); } else { for (i = 0; i < length; i++) - totFile[i] = (char) *_vm->_global->_inter_execPtr++; + totFile[i] = _vm->_game->_script->readChar(); totFile[i] = 0; } @@ -1135,7 +586,7 @@ void Inter_v2::o2_totSub() { if (!scumm_stricmp(totFile, "edit")) _vm->_util->forceMouseUp(); - flags = *_vm->_global->_inter_execPtr++; + flags = _vm->_game->_script->readByte(); _vm->_game->totSub(flags, totFile); } @@ -1143,8 +594,8 @@ void Inter_v2::o2_switchTotSub() { int16 index; int16 skipPlay; - index = load16(); - skipPlay = load16(); + index = _vm->_game->_script->readInt16(); + skipPlay = _vm->_game->_script->readInt16(); _vm->_game->switchTotSub(index, skipPlay); } @@ -1153,13 +604,13 @@ void Inter_v2::o2_pushVars() { byte count; int16 varOff; - count = *_vm->_global->_inter_execPtr++; + count = _vm->_game->_script->readByte(); for (int i = 0; i < count; i++, _varStackPos++) { - if ((*_vm->_global->_inter_execPtr == 25) || - (*_vm->_global->_inter_execPtr == 28)) { + if ((_vm->_game->_script->peekByte() == 25) || + (_vm->_game->_script->peekByte() == 28)) { - varOff = _vm->_parse->parseVarIndex(); - _vm->_global->_inter_execPtr++; + varOff = _vm->_game->_script->readVarIndex(); + _vm->_game->_script->skip(1); _variables->copyTo(varOff, _varStack + _varStackPos, _vm->_global->_inter_animDataSize * 4); @@ -1167,10 +618,12 @@ void Inter_v2::o2_pushVars() { _varStack[_varStackPos] = _vm->_global->_inter_animDataSize * 4; } else { - if (evalExpr(&varOff) != 20) - _vm->_global->_inter_resVal = 0; + int32 n = _vm->_game->_script->getResultInt(); + + if (_vm->_game->_script->evalExpr(&varOff) != 20) + n = 0; - memcpy(_varStack + _varStackPos, &_vm->_global->_inter_resVal, 4); + memcpy(_varStack + _varStackPos, &n, 4); _varStackPos += 4; _varStack[_varStackPos] = 4; } @@ -1182,9 +635,9 @@ void Inter_v2::o2_popVars() { int16 varOff; int16 size; - count = *_vm->_global->_inter_execPtr++; + count = _vm->_game->_script->readByte(); for (int i = 0; i < count; i++) { - varOff = _vm->_parse->parseVarIndex(); + varOff = _vm->_game->_script->readVarIndex(); size = _varStack[--_varStackPos]; _varStackPos -= size; @@ -1204,9 +657,9 @@ void Inter_v2::o2_moveGoblin() { int16 destX, destY; int16 index; - destX = _vm->_parse->parseValExpr(); - destY = _vm->_parse->parseValExpr(); - index = _vm->_parse->parseValExpr(); + destX = _vm->_game->_script->readValExpr(); + destY = _vm->_game->_script->readValExpr(); + index = _vm->_game->_script->readValExpr(); _vm->_goblin->move(destX, destY, index); } @@ -1214,15 +667,15 @@ void Inter_v2::o2_writeGoblinPos() { int16 varX, varY; int16 index; - varX = _vm->_parse->parseVarIndex(); - varY = _vm->_parse->parseVarIndex(); - index = _vm->_parse->parseValExpr(); + varX = _vm->_game->_script->readVarIndex(); + varY = _vm->_game->_script->readVarIndex(); + index = _vm->_game->_script->readValExpr(); WRITE_VAR_OFFSET(varX, _vm->_mult->_objects[index].goblinX); WRITE_VAR_OFFSET(varY, _vm->_mult->_objects[index].goblinY); } void Inter_v2::o2_stopGoblin() { - int16 index = _vm->_parse->parseValExpr(); + int16 index = _vm->_game->_script->readValExpr(); _vm->_mult->_objects[index].pAnimData->pathExistence = 4; } @@ -1236,9 +689,9 @@ void Inter_v2::o2_setGoblinState() { int16 deltaX, deltaY; int16 deltaWidth, deltaHeight; - index = _vm->_parse->parseValExpr(); - state = _vm->_parse->parseValExpr(); - type = _vm->_parse->parseValExpr(); + index = _vm->_game->_script->readValExpr(); + state = _vm->_game->_script->readValExpr(); + type = _vm->_game->_script->readValExpr(); Mult::Mult_Object &obj = _vm->_mult->_objects[index]; Mult::Mult_AnimData &objAnim = *(obj.pAnimData); @@ -1334,10 +787,10 @@ void Inter_v2::o2_placeGoblin() { int16 x, y; int16 state; - index = _vm->_parse->parseValExpr(); - x = _vm->_parse->parseValExpr(); - y = _vm->_parse->parseValExpr(); - state = _vm->_parse->parseValExpr(); + index = _vm->_game->_script->readValExpr(); + x = _vm->_game->_script->readValExpr(); + y = _vm->_game->_script->readValExpr(); + state = _vm->_game->_script->readValExpr(); _vm->_goblin->placeObject(0, 0, index, x, y, state); } @@ -1347,13 +800,13 @@ void Inter_v2::o2_initScreen() { int16 videoMode; int16 width, height; - offY = load16(); + offY = _vm->_game->_script->readInt16(); videoMode = offY & 0xFF; offY = (offY >> 8) & 0xFF; - width = _vm->_parse->parseValExpr(); - height = _vm->_parse->parseValExpr(); + width = _vm->_game->_script->readValExpr(); + height = _vm->_game->_script->readValExpr(); _vm->_video->clearScreen(); @@ -1441,16 +894,16 @@ void Inter_v2::o2_scroll() { int16 curX; int16 curY; - startX = CLIP((int) _vm->_parse->parseValExpr(), 0, + startX = CLIP((int) _vm->_game->_script->readValExpr(), 0, _vm->_video->_surfWidth - _vm->_width); - startY = CLIP((int) _vm->_parse->parseValExpr(), 0, + startY = CLIP((int) _vm->_game->_script->readValExpr(), 0, _vm->_video->_surfHeight - _vm->_height); - endX = CLIP((int) _vm->_parse->parseValExpr(), 0, + endX = CLIP((int) _vm->_game->_script->readValExpr(), 0, _vm->_video->_surfWidth - _vm->_width); - endY = CLIP((int) _vm->_parse->parseValExpr(), 0, + endY = CLIP((int) _vm->_game->_script->readValExpr(), 0, _vm->_video->_surfHeight - _vm->_height); - stepX = _vm->_parse->parseValExpr(); - stepY = _vm->_parse->parseValExpr(); + stepX = _vm->_game->_script->readValExpr(); + stepY = _vm->_game->_script->readValExpr(); curX = startX; curY = startY; @@ -1470,8 +923,8 @@ void Inter_v2::o2_scroll() { void Inter_v2::o2_setScrollOffset() { int16 offsetX, offsetY; - offsetX = _vm->_parse->parseValExpr(); - offsetY = _vm->_parse->parseValExpr(); + offsetX = _vm->_game->_script->readValExpr(); + offsetY = _vm->_game->_script->readValExpr(); if (offsetX == -1) { WRITE_VAR(2, _vm->_draw->_scrollOffsetX); @@ -1506,22 +959,22 @@ void Inter_v2::o2_playImd() { uint16 palCmd; bool close; - evalExpr(0); - _vm->_global->_inter_resStr[8] = 0; - strncpy0(imd, _vm->_global->_inter_resStr, 127); - - x = _vm->_parse->parseValExpr(); - y = _vm->_parse->parseValExpr(); - startFrame = _vm->_parse->parseValExpr(); - lastFrame = _vm->_parse->parseValExpr(); - breakKey = _vm->_parse->parseValExpr(); - flags = _vm->_parse->parseValExpr(); - palStart = _vm->_parse->parseValExpr(); - palEnd = _vm->_parse->parseValExpr(); + _vm->_game->_script->evalExpr(0); + _vm->_game->_script->getResultStr()[8] = 0; + strncpy0(imd, _vm->_game->_script->getResultStr(), 127); + + x = _vm->_game->_script->readValExpr(); + y = _vm->_game->_script->readValExpr(); + startFrame = _vm->_game->_script->readValExpr(); + lastFrame = _vm->_game->_script->readValExpr(); + breakKey = _vm->_game->_script->readValExpr(); + flags = _vm->_game->_script->readValExpr(); + palStart = _vm->_game->_script->readValExpr(); + palEnd = _vm->_game->_script->readValExpr(); palCmd = 1 << (flags & 0x3F); debugC(1, kDebugVideo, "Playing video \"%s\" @ %d+%d, frames %d - %d, " - "paletteCmd %d (%d - %d), flags %X", _vm->_global->_inter_resStr, x, y, + "paletteCmd %d (%d - %d), flags %X", _vm->_game->_script->getResultStr(), x, y, startFrame, lastFrame, palCmd, palStart, palEnd, flags); if ((imd[0] != 0) && !_vm->_vidPlayer->primaryOpen(imd, x, y, flags)) { @@ -1550,28 +1003,28 @@ void Inter_v2::o2_getImdInfo() { int16 varFrames; int16 varWidth, varHeight; - evalExpr(0); - varX = _vm->_parse->parseVarIndex(); - varY = _vm->_parse->parseVarIndex(); - varFrames = _vm->_parse->parseVarIndex(); - varWidth = _vm->_parse->parseVarIndex(); - varHeight = _vm->_parse->parseVarIndex(); + _vm->_game->_script->evalExpr(0); + varX = _vm->_game->_script->readVarIndex(); + varY = _vm->_game->_script->readVarIndex(); + varFrames = _vm->_game->_script->readVarIndex(); + varWidth = _vm->_game->_script->readVarIndex(); + varHeight = _vm->_game->_script->readVarIndex(); // WORKAROUND: The nut rolling animation in the administration center // in Woodruff is called "noixroul", but the scripts think it's "noixroule". if ((_vm->getGameType() == kGameTypeWoodruff) && - (!scumm_stricmp(_vm->_global->_inter_resStr, "noixroule"))) - strcpy(_vm->_global->_inter_resStr, "noixroul"); + (!scumm_stricmp(_vm->_game->_script->getResultStr(), "noixroule"))) + strcpy(_vm->_game->_script->getResultStr(), "noixroul"); - _vm->_vidPlayer->writeVideoInfo(_vm->_global->_inter_resStr, varX, varY, + _vm->_vidPlayer->writeVideoInfo(_vm->_game->_script->getResultStr(), varX, varY, varFrames, varWidth, varHeight); } void Inter_v2::o2_openItk() { char fileName[32]; - evalExpr(0); - strncpy0(fileName, _vm->_global->_inter_resStr, 27); + _vm->_game->_script->evalExpr(0); + strncpy0(fileName, _vm->_game->_script->getResultStr(), 27); if (!strchr(fileName, '.')) strcat(fileName, ".ITK"); @@ -1589,49 +1042,46 @@ void Inter_v2::o2_resetImdFrontSurf() { } bool Inter_v2::o2_assign(OpFuncParams ¶ms) { - byte *savedPos; - int16 varOff; - int16 token; - int16 result; - byte loopCount; - - savedPos = _vm->_global->_inter_execPtr; - varOff = _vm->_parse->parseVarIndex(); + byte destType = _vm->_game->_script->peekByte(); + int16 dest = _vm->_game->_script->readVarIndex(); - if (*_vm->_global->_inter_execPtr == 99) { - _vm->_global->_inter_execPtr++; - loopCount = *_vm->_global->_inter_execPtr++; + byte loopCount; + if (_vm->_game->_script->peekByte() == 99) { + _vm->_game->_script->skip(1); + loopCount = _vm->_game->_script->readByte(); } else loopCount = 1; for (int i = 0; i < loopCount; i++) { - token = evalExpr(&result); - switch (savedPos[0]) { - case 16: - case 18: - WRITE_VARO_UINT8(varOff + i, _vm->_global->_inter_resVal); + int16 result; + int16 srcType = _vm->_game->_script->evalExpr(&result); + + switch (destType) { + case TYPE_VAR_INT8: + case TYPE_ARRAY_INT8: + WRITE_VARO_UINT8(dest + i, _vm->_game->_script->getResultInt()); break; - case 17: - case 27: - WRITE_VARO_UINT16(varOff + i * 2, _vm->_global->_inter_resVal); + case TYPE_VAR_INT16: + case TYPE_ARRAY_INT16: + WRITE_VARO_UINT16(dest + i * 2, _vm->_game->_script->getResultInt()); break; - case 23: - case 26: - WRITE_VAR_OFFSET(varOff + i * 4, _vm->_global->_inter_resVal); + case TYPE_VAR_INT32: + case TYPE_ARRAY_INT32: + WRITE_VAR_OFFSET(dest + i * 4, _vm->_game->_script->getResultInt()); break; - case 24: - WRITE_VARO_UINT16(varOff + i * 4, _vm->_global->_inter_resVal); + case TYPE_VAR_INT32_AS_INT16: + WRITE_VARO_UINT16(dest + i * 4, _vm->_game->_script->getResultInt()); break; - case 25: - case 28: - if (token == 20) - WRITE_VARO_UINT8(varOff, result); + case TYPE_VAR_STR: + case TYPE_ARRAY_STR: + if (srcType == TYPE_IMM_INT16) + WRITE_VARO_UINT8(dest, result); else - WRITE_VARO_STR(varOff, _vm->_global->_inter_resStr); + WRITE_VARO_STR(dest, _vm->_game->_script->getResultStr()); break; } } @@ -1643,12 +1093,12 @@ bool Inter_v2::o2_printText(OpFuncParams ¶ms) { char buf[60]; int i; - _vm->_draw->_destSpriteX = _vm->_parse->parseValExpr(); - _vm->_draw->_destSpriteY = _vm->_parse->parseValExpr(); + _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr(); + _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr(); - _vm->_draw->_backColor = _vm->_parse->parseValExpr(); - _vm->_draw->_frontColor = _vm->_parse->parseValExpr(); - _vm->_draw->_fontIndex = _vm->_parse->parseValExpr(); + _vm->_draw->_backColor = _vm->_game->_script->readValExpr(); + _vm->_draw->_frontColor = _vm->_game->_script->readValExpr(); + _vm->_draw->_fontIndex = _vm->_game->_script->readValExpr(); _vm->_draw->_destSurface = 21; _vm->_draw->_textToPrint = buf; _vm->_draw->_transparency = 0; @@ -1659,48 +1109,47 @@ bool Inter_v2::o2_printText(OpFuncParams ¶ms) { } do { - for (i = 0; (((char) *_vm->_global->_inter_execPtr) != '.') && - (*_vm->_global->_inter_execPtr != 200); - i++, _vm->_global->_inter_execPtr++) { - buf[i] = (char) *_vm->_global->_inter_execPtr; + for (i = 0; (_vm->_game->_script->peekChar() != '.') && + (_vm->_game->_script->peekByte() != 200); i++) { + buf[i] = _vm->_game->_script->readChar(); } - if (*_vm->_global->_inter_execPtr != 200) { - _vm->_global->_inter_execPtr++; - switch (*_vm->_global->_inter_execPtr) { - case 16: - case 18: + if (_vm->_game->_script->peekByte() != 200) { + _vm->_game->_script->skip(1); + switch (_vm->_game->_script->peekByte()) { + case TYPE_VAR_INT8: + case TYPE_ARRAY_INT8: sprintf(buf + i, "%d", - (int8) READ_VARO_UINT8(_vm->_parse->parseVarIndex())); + (int8) READ_VARO_UINT8(_vm->_game->_script->readVarIndex())); break; - case 17: - case 24: - case 27: + case TYPE_VAR_INT16: + case TYPE_VAR_INT32_AS_INT16: + case TYPE_ARRAY_INT16: sprintf(buf + i, "%d", - (int16) READ_VARO_UINT16(_vm->_parse->parseVarIndex())); + (int16) READ_VARO_UINT16(_vm->_game->_script->readVarIndex())); break; - case 23: - case 26: + case TYPE_VAR_INT32: + case TYPE_ARRAY_INT32: sprintf(buf + i, "%d", - VAR_OFFSET(_vm->_parse->parseVarIndex())); + VAR_OFFSET(_vm->_game->_script->readVarIndex())); break; - case 25: - case 28: + case TYPE_VAR_STR: + case TYPE_ARRAY_STR: sprintf(buf + i, "%s", - GET_VARO_STR(_vm->_parse->parseVarIndex())); + GET_VARO_STR(_vm->_game->_script->readVarIndex())); break; } - _vm->_global->_inter_execPtr++; + _vm->_game->_script->skip(1); } else buf[i] = 0; _vm->_draw->spriteOperation(DRAW_PRINTTEXT); - } while (*_vm->_global->_inter_execPtr != 200); + } while (_vm->_game->_script->peekByte() != 200); - _vm->_global->_inter_execPtr++; + _vm->_game->_script->skip(1); return false; } @@ -1708,20 +1157,20 @@ bool Inter_v2::o2_printText(OpFuncParams ¶ms) { bool Inter_v2::o2_animPalInit(OpFuncParams ¶ms) { int16 index; - index = load16(); + index = _vm->_game->_script->readInt16(); if (index > 0) { index--; - _animPalLowIndex[index] = _vm->_parse->parseValExpr(); - _animPalHighIndex[index] = _vm->_parse->parseValExpr(); + _animPalLowIndex[index] = _vm->_game->_script->readValExpr(); + _animPalHighIndex[index] = _vm->_game->_script->readValExpr(); _animPalDir[index] = 1; } else if (index == 0) { memset(_animPalDir, 0, 8 * sizeof(int16)); - _vm->_parse->parseValExpr(); - _vm->_parse->parseValExpr(); + _vm->_game->_script->readValExpr(); + _vm->_game->_script->readValExpr(); } else { index = -index - 1; - _animPalLowIndex[index] = _vm->_parse->parseValExpr(); - _animPalHighIndex[index] = _vm->_parse->parseValExpr(); + _animPalLowIndex[index] = _vm->_game->_script->readValExpr(); + _animPalHighIndex[index] = _vm->_game->_script->readValExpr(); _animPalDir[index] = -1; } return false; @@ -1734,14 +1183,14 @@ bool Inter_v2::o2_addCollision(OpFuncParams ¶ms) { int16 key; int16 funcSub; - id = _vm->_parse->parseValExpr(); - funcSub = _vm->_global->_inter_execPtr - _vm->_game->_totFileData; - left = _vm->_parse->parseValExpr(); - top = _vm->_parse->parseValExpr(); - width = _vm->_parse->parseValExpr(); - height = _vm->_parse->parseValExpr(); - flags = _vm->_parse->parseValExpr(); - key = load16(); + id = _vm->_game->_script->readValExpr(); + funcSub = _vm->_game->_script->pos(); + left = _vm->_game->_script->readValExpr(); + top = _vm->_game->_script->readValExpr(); + width = _vm->_game->_script->readValExpr(); + height = _vm->_game->_script->readValExpr(); + flags = _vm->_game->_script->readValExpr(); + key = _vm->_game->_script->readInt16(); if (key == 0) key = ABS(id) + 41960; @@ -1775,7 +1224,7 @@ bool Inter_v2::o2_addCollision(OpFuncParams ¶ms) { bool Inter_v2::o2_freeCollision(OpFuncParams ¶ms) { int16 id; - id = _vm->_parse->parseValExpr(); + id = _vm->_game->_script->readValExpr(); if (id == -2) { for (int i = 0; i < 150; i++) { if ((_vm->_game->_collisionAreas[i].id & 0xF000) == 0xD000) @@ -1797,9 +1246,9 @@ bool Inter_v2::o2_goblinFunc(OpFuncParams ¶ms) { // It's not yet implemented, so we fudge our way through // and pretend we've won. if (_vm->getGameType() == kGameTypeInca2) { - _vm->_global->_inter_execPtr += 4; - uint16 resVar = (uint16) load16(); - _vm->_global->_inter_execPtr += 4; + _vm->_game->_script->skip(4); + uint16 resVar = _vm->_game->_script->readUint16(); + _vm->_game->_script->skip(4); WRITE_VAR(resVar, 1); return false; @@ -1808,18 +1257,20 @@ bool Inter_v2::o2_goblinFunc(OpFuncParams ¶ms) { OpGobParams gobParams; int16 cmd; - cmd = load16(); - _vm->_global->_inter_execPtr += 2; + cmd = _vm->_game->_script->readInt16(); + + gobParams.paramCount = _vm->_game->_script->readInt16(); + gobParams.extraData = cmd; if (cmd != 101) - executeGoblinOpcode(cmd, gobParams); + executeOpcodeGob(cmd, gobParams); return false; } bool Inter_v2::o2_stopSound(OpFuncParams ¶ms) { int16 expr; - expr = _vm->_parse->parseValExpr(); + expr = _vm->_game->_script->readValExpr(); if (expr < 0) { _vm->_sound->adlibStop(); @@ -1839,13 +1290,13 @@ bool Inter_v2::o2_getFreeMem(OpFuncParams ¶ms) { int16 freeVar; int16 maxFreeVar; - freeVar = _vm->_parse->parseVarIndex(); - maxFreeVar = _vm->_parse->parseVarIndex(); + freeVar = _vm->_game->_script->readVarIndex(); + maxFreeVar = _vm->_game->_script->readVarIndex(); // HACK WRITE_VAR_OFFSET(freeVar, 1000000); WRITE_VAR_OFFSET(maxFreeVar, 1000000); - WRITE_VAR(16, READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4); + WRITE_VAR(16, _vm->_game->_script->getVariablesCount() * 4); return false; } @@ -1855,23 +1306,22 @@ bool Inter_v2::o2_checkData(OpFuncParams ¶ms) { int32 size; SaveLoad::SaveMode mode; - evalExpr(0); - varOff = _vm->_parse->parseVarIndex(); + _vm->_game->_script->evalExpr(0); + varOff = _vm->_game->_script->readVarIndex(); size = -1; handle = 1; - mode = _vm->_saveLoad->getSaveMode(_vm->_global->_inter_resStr); + mode = _vm->_saveLoad->getSaveMode(_vm->_game->_script->getResultStr()); if (mode == SaveLoad::kSaveModeNone) { - handle = _vm->_dataIO->openData(_vm->_global->_inter_resStr); - if (handle >= 0) { - _vm->_dataIO->closeData(handle); - size = _vm->_dataIO->getDataSize(_vm->_global->_inter_resStr); - } else - warning("File \"%s\" not found", _vm->_global->_inter_resStr); + if (_vm->_dataIO->existData(_vm->_game->_script->getResultStr())) + size = _vm->_dataIO->getDataSize(_vm->_game->_script->getResultStr()); + else + warning("File \"%s\" not found", _vm->_game->_script->getResultStr()); + } else if (mode == SaveLoad::kSaveModeSave) - size = _vm->_saveLoad->getSize(_vm->_global->_inter_resStr); + size = _vm->_saveLoad->getSize(_vm->_game->_script->getResultStr()); else if (mode == SaveLoad::kSaveModeExists) size = 23; @@ -1879,7 +1329,7 @@ bool Inter_v2::o2_checkData(OpFuncParams ¶ms) { handle = -1; debugC(2, kDebugFileIO, "Requested size of file \"%s\": %d", - _vm->_global->_inter_resStr, size); + _vm->_game->_script->getResultStr(), size); WRITE_VAR_OFFSET(varOff, handle); WRITE_VAR(16, (uint32) size); @@ -1896,20 +1346,20 @@ bool Inter_v2::o2_readData(OpFuncParams ¶ms) { byte *buf; SaveLoad::SaveMode mode; - evalExpr(0); - dataVar = _vm->_parse->parseVarIndex(); - size = _vm->_parse->parseValExpr(); - evalExpr(0); - offset = _vm->_global->_inter_resVal; + _vm->_game->_script->evalExpr(0); + dataVar = _vm->_game->_script->readVarIndex(); + size = _vm->_game->_script->readValExpr(); + _vm->_game->_script->evalExpr(0); + offset = _vm->_game->_script->getResultInt(); retSize = 0; debugC(2, kDebugFileIO, "Read from file \"%s\" (%d, %d bytes at %d)", - _vm->_global->_inter_resStr, dataVar, size, offset); + _vm->_game->_script->getResultStr(), dataVar, size, offset); - mode = _vm->_saveLoad->getSaveMode(_vm->_global->_inter_resStr); + mode = _vm->_saveLoad->getSaveMode(_vm->_game->_script->getResultStr()); if (mode == SaveLoad::kSaveModeSave) { WRITE_VAR(1, 1); - if (_vm->_saveLoad->load(_vm->_global->_inter_resStr, dataVar, size, offset)) + if (_vm->_saveLoad->load(_vm->_game->_script->getResultStr(), dataVar, size, offset)) WRITE_VAR(1, 0); return false; } else if (mode == SaveLoad::kSaveModeIgnore) @@ -1917,22 +1367,22 @@ bool Inter_v2::o2_readData(OpFuncParams ¶ms) { if (size < 0) { warning("Attempted to read a raw sprite from file \"%s\"", - _vm->_global->_inter_resStr); + _vm->_game->_script->getResultStr()); return false ; } else if (size == 0) { dataVar = 0; - size = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4; + size = _vm->_game->_script->getVariablesCount() * 4; } buf = _variables->getAddressOff8(dataVar); - if (_vm->_global->_inter_resStr[0] == 0) { + if (_vm->_game->_script->getResultStr()[0] == 0) { WRITE_VAR(1, size); return false; } WRITE_VAR(1, 1); - handle = _vm->_dataIO->openData(_vm->_global->_inter_resStr); + handle = _vm->_dataIO->openData(_vm->_game->_script->getResultStr()); if (handle < 0) return false; @@ -1967,23 +1417,23 @@ bool Inter_v2::o2_writeData(OpFuncParams ¶ms) { int16 dataVar; SaveLoad::SaveMode mode; - evalExpr(0); - dataVar = _vm->_parse->parseVarIndex(); - size = _vm->_parse->parseValExpr(); - evalExpr(0); - offset = _vm->_global->_inter_resVal; + _vm->_game->_script->evalExpr(0); + dataVar = _vm->_game->_script->readVarIndex(); + size = _vm->_game->_script->readValExpr(); + _vm->_game->_script->evalExpr(0); + offset = _vm->_game->_script->getResultInt(); debugC(2, kDebugFileIO, "Write to file \"%s\" (%d, %d bytes at %d)", - _vm->_global->_inter_resStr, dataVar, size, offset); + _vm->_game->_script->getResultStr(), dataVar, size, offset); WRITE_VAR(1, 1); - mode = _vm->_saveLoad->getSaveMode(_vm->_global->_inter_resStr); + mode = _vm->_saveLoad->getSaveMode(_vm->_game->_script->getResultStr()); if (mode == SaveLoad::kSaveModeSave) { - if (_vm->_saveLoad->save(_vm->_global->_inter_resStr, dataVar, size, offset)) + if (_vm->_saveLoad->save(_vm->_game->_script->getResultStr(), dataVar, size, offset)) WRITE_VAR(1, 0); } else if (mode == SaveLoad::kSaveModeNone) - warning("Attempted to write to file \"%s\"", _vm->_global->_inter_resStr); + warning("Attempted to write to file \"%s\"", _vm->_game->_script->getResultStr()); return false; } @@ -1992,7 +1442,7 @@ void Inter_v2::o2_loadInfogramesIns(OpGobParams ¶ms) { int16 varName; char fileName[20]; - varName = load16(); + varName = _vm->_game->_script->readInt16(); strncpy0(fileName, GET_VAR_STR(varName), 15); strcat(fileName, ".INS"); @@ -2004,7 +1454,7 @@ void Inter_v2::o2_playInfogrames(OpGobParams ¶ms) { int16 varName; char fileName[20]; - varName = load16(); + varName = _vm->_game->_script->readInt16(); strncpy0(fileName, GET_VAR_STR(varName), 15); strcat(fileName, ".DUM"); @@ -2014,13 +1464,13 @@ void Inter_v2::o2_playInfogrames(OpGobParams ¶ms) { } void Inter_v2::o2_startInfogrames(OpGobParams ¶ms) { - load16(); + _vm->_game->_script->readInt16(); _vm->_sound->infogramesPlay(); } void Inter_v2::o2_stopInfogrames(OpGobParams ¶ms) { - load16(); + _vm->_game->_script->readInt16(); _vm->_sound->infogramesStop(); } @@ -2034,12 +1484,12 @@ void Inter_v2::o2_stopProtracker(OpGobParams ¶ms) { } void Inter_v2::o2_handleGoblins(OpGobParams ¶ms) { - _vm->_goblin->_gob1NoTurn = VAR(load16()) != 0; - _vm->_goblin->_gob2NoTurn = VAR(load16()) != 0; - _vm->_goblin->_gob1RelaxTimeVar = load16(); - _vm->_goblin->_gob2RelaxTimeVar = load16(); - _vm->_goblin->_gob1Busy = VAR(load16()) != 0; - _vm->_goblin->_gob2Busy = VAR(load16()) != 0; + _vm->_goblin->_gob1NoTurn = VAR(_vm->_game->_script->readInt16()) != 0; + _vm->_goblin->_gob2NoTurn = VAR(_vm->_game->_script->readInt16()) != 0; + _vm->_goblin->_gob1RelaxTimeVar = _vm->_game->_script->readInt16(); + _vm->_goblin->_gob2RelaxTimeVar = _vm->_game->_script->readInt16(); + _vm->_goblin->_gob1Busy = VAR(_vm->_game->_script->readInt16()) != 0; + _vm->_goblin->_gob2Busy = VAR(_vm->_game->_script->readInt16()) != 0; _vm->_goblin->handleGoblins(); } @@ -2050,21 +1500,20 @@ int16 Inter_v2::loadSound(int16 search) { uint16 slotIdMask; uint32 dataSize; SoundType type; - SoundSource source; type = SOUND_SND; slotIdMask = 0; dataSize = 0; if (!search) { - slot = _vm->_parse->parseValExpr(); + slot = _vm->_game->_script->readValExpr(); if (slot < 0) { type = SOUND_ADL; slot = -slot; } - id = load16(); + id = _vm->_game->_script->readInt16(); } else { - id = load16(); + id = _vm->_game->_script->readInt16(); for (slot = 0; slot < Sound::kSoundsCount; slot++) if (_vm->_sound->sampleGetBySlot(slot)->isId(id)) { @@ -2093,37 +1542,37 @@ int16 Inter_v2::loadSound(int16 search) { if (id == -1) { char sndfile[14]; - source = SOUND_FILE; - - strncpy0(sndfile, (const char *) _vm->_global->_inter_execPtr, 9); - _vm->_global->_inter_execPtr += 9; + strncpy0(sndfile, _vm->_game->_script->readString(9), 9); if (type == SOUND_ADL) strcat(sndfile, ".ADL"); else strcat(sndfile, ".SND"); - dataPtr = (byte *) _vm->_dataIO->getData(sndfile); - if (dataPtr) - dataSize = _vm->_dataIO->getDataSize(sndfile); - } else if (id >= 30000) { - source = SOUND_EXT; - - dataPtr = (byte *) _vm->_game->loadExtData(id, 0, 0, &dataSize); - } else { - int16 totSize; + dataPtr = _vm->_dataIO->getData(sndfile); + dataSize = _vm->_dataIO->getDataSize(sndfile); + if (!dataPtr) + return 0; - source = SOUND_TOT; + if (!sample->load(type, dataPtr, dataSize)) { + delete[] dataPtr; + return 0; + } - dataPtr = (byte *) _vm->_game->loadTotResource(id, &totSize); - dataSize = (uint32) ((int32) totSize); + sample->_id = id; + return slot | slotIdMask; } - if (dataPtr) { - sample->load(type, source, dataPtr, dataSize); - sample->_id = id; + Resource *resource = _vm->_game->_resources->getResource(id); + if (!resource) + return 0; + + if (!sample->load(type, resource)) { + delete resource; + return 0; } + sample->_id = id; return slot | slotIdMask; } diff --git a/engines/gob/inter_v3.cpp b/engines/gob/inter_v3.cpp index 6819b369b8..17ce7feafa 100644 --- a/engines/gob/inter_v3.cpp +++ b/engines/gob/inter_v3.cpp @@ -32,683 +32,38 @@ #include "gob/dataio.h" #include "gob/draw.h" #include "gob/game.h" -#include "gob/parse.h" +#include "gob/script.h" +#include "gob/resources.h" namespace Gob { -#define OPCODE(x) _OPCODE(Inter_v3, x) - -const int Inter_v3::_goblinFuncLookUp[][2] = { - {0, 0}, - {1, 1}, - {2, 2}, - {4, 3}, - {5, 4}, - {6, 5}, - {7, 6}, - {8, 7}, - {9, 8}, - {10, 9}, - {12, 10}, - {13, 11}, - {14, 12}, - {15, 13}, - {16, 14}, - {21, 15}, - {22, 16}, - {23, 17}, - {24, 18}, - {25, 19}, - {26, 20}, - {27, 21}, - {28, 22}, - {29, 23}, - {30, 24}, - {32, 25}, - {33, 26}, - {34, 27}, - {35, 28}, - {36, 29}, - {37, 30}, - {40, 31}, - {41, 32}, - {42, 33}, - {43, 34}, - {44, 35}, - {50, 36}, - {52, 37}, - {53, 38}, - {100, 39}, - {152, 40}, - {200, 41}, - {201, 42}, - {202, 43}, - {203, 44}, - {204, 45}, - {250, 46}, - {251, 47}, - {252, 48}, - {500, 49}, - {502, 50}, - {503, 51}, - {600, 52}, - {601, 53}, - {602, 54}, - {603, 55}, - {604, 56}, - {605, 57}, - {1000, 58}, - {1001, 59}, - {1002, 60}, - {1003, 61}, - {1004, 62}, - {1005, 63}, - {1006, 64}, - {1008, 65}, - {1009, 66}, - {1010, 67}, - {1011, 68}, - {1015, 69}, - {2005, 70} -}; +#define OPCODEVER Inter_v3 +#define OPCODEDRAW(i, x) _opcodesDraw[i]._OPCODEDRAW(OPCODEVER, x) +#define OPCODEFUNC(i, x) _opcodesFunc[i]._OPCODEFUNC(OPCODEVER, x) +#define OPCODEGOB(i, x) _opcodesGob[i]._OPCODEGOB(OPCODEVER, x) Inter_v3::Inter_v3(GobEngine *vm) : Inter_v2(vm) { - setupOpcodes(); } -void Inter_v3::setupOpcodes() { - static const OpcodeDrawEntryV3 opcodesDraw[256] = { - /* 00 */ - OPCODE(o1_loadMult), - OPCODE(o2_playMult), - OPCODE(o2_freeMultKeys), - {0, ""}, - /* 04 */ - {0, ""}, - {0, ""}, - {0, ""}, - OPCODE(o1_initCursor), - /* 08 */ - OPCODE(o1_initCursorAnim), - OPCODE(o1_clearCursorAnim), - OPCODE(o2_setRenderFlags), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - OPCODE(o1_loadAnim), - OPCODE(o1_freeAnim), - OPCODE(o1_updateAnim), - OPCODE(o2_multSub), - /* 14 */ - OPCODE(o2_initMult), - OPCODE(o1_freeMult), - OPCODE(o1_animate), - OPCODE(o2_loadMultObject), - /* 18 */ - OPCODE(o1_getAnimLayerInfo), - OPCODE(o1_getObjAnimSize), - OPCODE(o1_loadStatic), - OPCODE(o1_freeStatic), - /* 1C */ - OPCODE(o2_renderStatic), - OPCODE(o2_loadCurLayer), - {0, ""}, - {0, ""}, - /* 20 */ - OPCODE(o2_playCDTrack), - OPCODE(o2_waitCDTrackEnd), - OPCODE(o2_stopCD), - OPCODE(o2_readLIC), - /* 24 */ - OPCODE(o2_freeLIC), - OPCODE(o2_getCDTrackPos), - {0, ""}, - {0, ""}, - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o2_loadFontToSprite), - OPCODE(o1_freeFontToSprite), - {0, ""}, - {0, ""}, - /* 34 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 38 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 3C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 40 */ - OPCODE(o2_totSub), - OPCODE(o2_switchTotSub), - OPCODE(o2_pushVars), - OPCODE(o2_popVars), - /* 44 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 48 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 4C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 50 */ - OPCODE(o2_loadMapObjects), - OPCODE(o2_freeGoblins), - OPCODE(o2_moveGoblin), - OPCODE(o2_writeGoblinPos), - /* 54 */ - OPCODE(o2_stopGoblin), - OPCODE(o2_setGoblinState), - OPCODE(o2_placeGoblin), - {0, ""}, - /* 58 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 5C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 60 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 64 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 68 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 6C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 70 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 74 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 78 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 7C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 80 */ - OPCODE(o2_initScreen), - OPCODE(o2_scroll), - OPCODE(o2_setScrollOffset), - OPCODE(o2_playImd), - /* 84 */ - OPCODE(o2_getImdInfo), - OPCODE(o2_openItk), - OPCODE(o2_closeItk), - OPCODE(o2_setImdFrontSurf), - /* 88 */ - OPCODE(o2_resetImdFrontSurf), - {0, ""}, - {0, ""}, - {0, ""}, - /* 8C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 90 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 94 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 98 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 9C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* AC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* BC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* CC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* DC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* EC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* FC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""} - }; - - static const OpcodeFuncEntryV3 opcodesFunc[80] = { - /* 00 */ - OPCODE(o1_callSub), - OPCODE(o1_callSub), - OPCODE(o1_printTotText), - OPCODE(o1_loadCursor), - /* 04 */ - {0, ""}, - OPCODE(o1_switch), - OPCODE(o1_repeatUntil), - OPCODE(o1_whileDo), - /* 08 */ - OPCODE(o1_if), - OPCODE(o2_assign), - OPCODE(o1_loadSpriteToPos), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - {0, ""}, - OPCODE(o2_printText), - OPCODE(o1_loadTot), - OPCODE(o1_palLoad), - /* 14 */ - OPCODE(o1_keyFunc), - OPCODE(o1_capturePush), - OPCODE(o1_capturePop), - OPCODE(o2_animPalInit), - /* 18 */ - OPCODE(o2_addCollision), - OPCODE(o2_freeCollision), - OPCODE(o3_getTotTextItemPart), - {0, ""}, - /* 1C */ - {0, ""}, - {0, ""}, - OPCODE(o1_drawOperations), - OPCODE(o1_setcmdCount), - /* 20 */ - OPCODE(o1_return), - OPCODE(o1_renewTimeInVars), - OPCODE(o1_speakerOn), - OPCODE(o1_speakerOff), - /* 24 */ - OPCODE(o1_putPixel), - OPCODE(o2_goblinFunc), - OPCODE(o1_createSprite), - OPCODE(o1_freeSprite), - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o1_returnTo), - OPCODE(o1_loadSpriteContent), - OPCODE(o3_copySprite), - OPCODE(o1_fillRect), - /* 34 */ - OPCODE(o1_drawLine), - OPCODE(o1_strToLong), - OPCODE(o1_invalidate), - OPCODE(o1_setBackDelta), - /* 38 */ - OPCODE(o1_playSound), - OPCODE(o2_stopSound), - OPCODE(o2_loadSound), - OPCODE(o1_freeSoundSlot), - /* 3C */ - OPCODE(o1_waitEndPlay), - OPCODE(o1_playComposition), - OPCODE(o2_getFreeMem), - OPCODE(o2_checkData), - /* 40 */ - {0, ""}, - OPCODE(o1_prepareStr), - OPCODE(o1_insertStr), - OPCODE(o1_cutStr), - /* 44 */ - OPCODE(o1_strstr), - OPCODE(o1_istrlen), - OPCODE(o1_setMousePos), - OPCODE(o1_setFrameRate), - /* 48 */ - OPCODE(o1_animatePalette), - OPCODE(o1_animateCursor), - OPCODE(o1_blitCursor), - OPCODE(o1_loadFont), - /* 4C */ - OPCODE(o1_freeFont), - OPCODE(o2_readData), - OPCODE(o2_writeData), - OPCODE(o1_manageDataFile), - }; - - static const OpcodeGoblinEntryV3 opcodesGoblin[71] = { - /* 00 */ - OPCODE(o2_loadInfogramesIns), - OPCODE(o2_startInfogrames), - OPCODE(o2_stopInfogrames), - {0, ""}, - /* 04 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 08 */ - {0, ""}, - OPCODE(o2_playInfogrames), - {0, ""}, - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 14 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 18 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 1C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 20 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 24 */ - {0, ""}, - {0, ""}, - {0, ""}, - OPCODE(o3_wobble), - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 34 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 38 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 3C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 40 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 44 */ - {0, ""}, - {0, ""}, - {0, ""}, - }; - - _opcodesDrawV3 = opcodesDraw; - _opcodesFuncV3 = opcodesFunc; - _opcodesGoblinV3 = opcodesGoblin; +void Inter_v3::setupOpcodesDraw() { + Inter_v2::setupOpcodesDraw(); } -void Inter_v3::executeDrawOpcode(byte i) { - debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)", - i, i, getOpcodeDrawDesc(i)); +void Inter_v3::setupOpcodesFunc() { + Inter_v2::setupOpcodesFunc(); - OpcodeDrawProcV3 op = _opcodesDrawV3[i].proc; - - if (op == 0) - warning("unimplemented opcodeDraw: %d", i); - else - (this->*op) (); -} - -bool Inter_v3::executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms) { - debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s)", - i, j, i, j, getOpcodeFuncDesc(i, j)); - - if ((i > 4) || (j > 15)) { - warning("unimplemented opcodeFunc: %d.%d", i, j); - return false; - } - - OpcodeFuncProcV3 op = _opcodesFuncV3[i*16 + j].proc; - - if (op == 0) - warning("unimplemented opcodeFunc: %d.%d", i, j); - else - return (this->*op) (params); - - return false; -} - -void Inter_v3::executeGoblinOpcode(int i, OpGobParams ¶ms) { - debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)", - i, i, getOpcodeGoblinDesc(i)); - - OpcodeGoblinProcV3 op = 0; - - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) { - op = _opcodesGoblinV3[_goblinFuncLookUp[j][1]].proc; - break; - } - - if (op == 0) { - int16 val; - - _vm->_global->_inter_execPtr -= 2; - val = load16(); - _vm->_global->_inter_execPtr += val << 1; - } else - (this->*op) (params); + OPCODEFUNC(0x1A, o3_getTotTextItemPart); + OPCODEFUNC(0x32, o3_copySprite); } -const char *Inter_v3::getOpcodeDrawDesc(byte i) { - return _opcodesDrawV3[i].desc; -} +void Inter_v3::setupOpcodesGob() { + OPCODEGOB( 0, o2_loadInfogramesIns); + OPCODEGOB( 1, o2_startInfogrames); + OPCODEGOB( 2, o2_stopInfogrames); -const char *Inter_v3::getOpcodeFuncDesc(byte i, byte j) { - if ((i > 4) || (j > 15)) - return ""; + OPCODEGOB( 10, o2_playInfogrames); - return _opcodesFuncV3[i*16 + j].desc; -} - -const char *Inter_v3::getOpcodeGoblinDesc(int i) { - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) - return _opcodesGoblinV3[_goblinFuncLookUp[j][1]].desc; - return ""; + OPCODEGOB(100, o3_wobble); } bool Inter_v3::o3_getTotTextItemPart(OpFuncParams ¶ms) { @@ -720,18 +75,18 @@ bool Inter_v3::o3_getTotTextItemPart(OpFuncParams ¶ms) { uint32 stringStartVar, stringVar; bool end; - totTextItem = load16(); - stringStartVar = _vm->_parse->parseVarIndex(); - part = _vm->_parse->parseValExpr(); + totTextItem = _vm->_game->_script->readInt16(); + stringStartVar = _vm->_game->_script->readVarIndex(); + part = _vm->_game->_script->readValExpr(); stringVar = stringStartVar; WRITE_VARO_UINT8(stringVar, 0); - if (!_vm->_game->_totTextData) + TextItem *textItem = _vm->_game->_resources->getTextItem(totTextItem); + if (!textItem) return false; - totData = _vm->_game->_totTextData->dataPtr + - _vm->_game->_totTextData->items[totTextItem].offset; + totData = textItem->getData(); // Skip background rectangles while (((int16) READ_LE_UINT16(totData)) != -1) @@ -782,6 +137,7 @@ bool Inter_v3::o3_getTotTextItemPart(OpFuncParams ¶ms) { if ((n != 0) || (*totData == 1) || (*totData == 6) || (*totData == 7)) { WRITE_VARO_UINT8(stringVar, 0); + delete textItem; return false; } @@ -813,8 +169,9 @@ bool Inter_v3::o3_getTotTextItemPart(OpFuncParams ¶ms) { WRITE_VARO_UINT16(stringVar, offX); WRITE_VARO_UINT16(stringVar + 2, offY); WRITE_VARO_UINT16(stringVar + 4, - totData - _vm->_game->_totTextData->dataPtr); + totData - _vm->_game->_resources->getTexts()); WRITE_VARO_UINT8(stringVar + 6, 0); + delete textItem; return false; } @@ -860,8 +217,10 @@ bool Inter_v3::o3_getTotTextItemPart(OpFuncParams ¶ms) { if (((*totData != 2) && (*totData != 5)) || (ABS(offY - READ_LE_UINT16(totData + 3)) > 1)) { - if (curPart == part) + if (curPart == part) { + delete textItem; return false; + } stringVar = stringStartVar; WRITE_VARO_UINT8(stringVar, 0); @@ -881,6 +240,7 @@ bool Inter_v3::o3_getTotTextItemPart(OpFuncParams ¶ms) { } } + delete textItem; return false; } diff --git a/engines/gob/inter_v4.cpp b/engines/gob/inter_v4.cpp index 6ab55d70af..48378a5987 100644 --- a/engines/gob/inter_v4.cpp +++ b/engines/gob/inter_v4.cpp @@ -32,689 +32,32 @@ #include "gob/global.h" #include "gob/draw.h" #include "gob/game.h" -#include "gob/parse.h" +#include "gob/script.h" #include "gob/videoplayer.h" #include "gob/sound/sound.h" namespace Gob { -#define OPCODE(x) _OPCODE(Inter_v4, x) - -const int Inter_v4::_goblinFuncLookUp[][2] = { - {0, 0}, - {1, 1}, - {2, 2}, - {4, 3}, - {5, 4}, - {6, 5}, - {7, 6}, - {8, 7}, - {9, 8}, - {10, 9}, - {12, 10}, - {13, 11}, - {14, 12}, - {15, 13}, - {16, 14}, - {21, 15}, - {22, 16}, - {23, 17}, - {24, 18}, - {25, 19}, - {26, 20}, - {27, 21}, - {28, 22}, - {29, 23}, - {30, 24}, - {32, 25}, - {33, 26}, - {34, 27}, - {35, 28}, - {36, 29}, - {37, 30}, - {40, 31}, - {41, 32}, - {42, 33}, - {43, 34}, - {44, 35}, - {50, 36}, - {52, 37}, - {53, 38}, - {100, 39}, - {152, 40}, - {200, 41}, - {201, 42}, - {202, 43}, - {203, 44}, - {204, 45}, - {250, 46}, - {251, 47}, - {252, 48}, - {500, 49}, - {502, 50}, - {503, 51}, - {600, 52}, - {601, 53}, - {602, 54}, - {603, 55}, - {604, 56}, - {605, 57}, - {1000, 58}, - {1001, 59}, - {1002, 60}, - {1003, 61}, - {1004, 62}, - {1005, 63}, - {1006, 64}, - {1008, 65}, - {1009, 66}, - {1010, 67}, - {1011, 68}, - {1015, 69}, - {2005, 70} -}; +#define OPCODEVER Inter_v4 +#define OPCODEDRAW(i, x) _opcodesDraw[i]._OPCODEDRAW(OPCODEVER, x) +#define OPCODEFUNC(i, x) _opcodesFunc[i]._OPCODEFUNC(OPCODEVER, x) +#define OPCODEGOB(i, x) _opcodesGob[i]._OPCODEGOB(OPCODEVER, x) Inter_v4::Inter_v4(GobEngine *vm) : Inter_v3(vm) { - setupOpcodes(); } -void Inter_v4::setupOpcodes() { - static const OpcodeDrawEntryV4 opcodesDraw[256] = { - /* 00 */ - OPCODE(o1_loadMult), - OPCODE(o2_playMult), - OPCODE(o2_freeMultKeys), - {0, ""}, - /* 04 */ - {0, ""}, - {0, ""}, - {0, ""}, - OPCODE(o1_initCursor), - /* 08 */ - OPCODE(o1_initCursorAnim), - OPCODE(o1_clearCursorAnim), - OPCODE(o2_setRenderFlags), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - OPCODE(o1_loadAnim), - OPCODE(o1_freeAnim), - OPCODE(o1_updateAnim), - OPCODE(o2_multSub), - /* 14 */ - OPCODE(o2_initMult), - OPCODE(o1_freeMult), - OPCODE(o1_animate), - OPCODE(o2_loadMultObject), - /* 18 */ - OPCODE(o1_getAnimLayerInfo), - OPCODE(o1_getObjAnimSize), - OPCODE(o1_loadStatic), - OPCODE(o1_freeStatic), - /* 1C */ - OPCODE(o2_renderStatic), - OPCODE(o2_loadCurLayer), - {0, ""}, - {0, ""}, - /* 20 */ - OPCODE(o2_playCDTrack), - OPCODE(o2_waitCDTrackEnd), - OPCODE(o2_stopCD), - OPCODE(o2_readLIC), - /* 24 */ - OPCODE(o2_freeLIC), - OPCODE(o2_getCDTrackPos), - {0, ""}, - {0, ""}, - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o2_loadFontToSprite), - OPCODE(o1_freeFontToSprite), - {0, ""}, - {0, ""}, - /* 34 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 38 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 3C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 40 */ - OPCODE(o2_totSub), - OPCODE(o2_switchTotSub), - OPCODE(o2_pushVars), - OPCODE(o2_popVars), - /* 44 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 48 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 4C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 50 */ - OPCODE(o2_loadMapObjects), - OPCODE(o2_freeGoblins), - OPCODE(o2_moveGoblin), - OPCODE(o2_writeGoblinPos), - /* 54 */ - OPCODE(o2_stopGoblin), - OPCODE(o2_setGoblinState), - OPCODE(o2_placeGoblin), - {0, ""}, - /* 58 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 5C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 60 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 64 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 68 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 6C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 70 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 74 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 78 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 7C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 80 */ - OPCODE(o4_initScreen), - OPCODE(o2_scroll), - OPCODE(o2_setScrollOffset), - OPCODE(o4_playVmdOrMusic), - /* 84 */ - OPCODE(o2_getImdInfo), - OPCODE(o2_openItk), - OPCODE(o2_closeItk), - OPCODE(o2_setImdFrontSurf), - /* 88 */ - OPCODE(o2_resetImdFrontSurf), - {0, ""}, - {0, ""}, - {0, ""}, - /* 8C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 90 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 94 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 98 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 9C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* AC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* BC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* CC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* DC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* EC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* FC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""} - }; - - static const OpcodeFuncEntryV4 opcodesFunc[80] = { - /* 00 */ - OPCODE(o1_callSub), - OPCODE(o1_callSub), - OPCODE(o1_printTotText), - OPCODE(o1_loadCursor), - /* 04 */ - {0, ""}, - OPCODE(o1_switch), - OPCODE(o1_repeatUntil), - OPCODE(o1_whileDo), - /* 08 */ - OPCODE(o1_if), - OPCODE(o2_assign), - OPCODE(o1_loadSpriteToPos), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - {0, ""}, - OPCODE(o2_printText), - OPCODE(o1_loadTot), - OPCODE(o1_palLoad), - /* 14 */ - OPCODE(o1_keyFunc), - OPCODE(o1_capturePush), - OPCODE(o1_capturePop), - OPCODE(o2_animPalInit), - /* 18 */ - OPCODE(o2_addCollision), - OPCODE(o2_freeCollision), - OPCODE(o3_getTotTextItemPart), - {0, ""}, - /* 1C */ - {0, ""}, - {0, ""}, - OPCODE(o1_drawOperations), - OPCODE(o1_setcmdCount), - /* 20 */ - OPCODE(o1_return), - OPCODE(o1_renewTimeInVars), - OPCODE(o1_speakerOn), - OPCODE(o1_speakerOff), - /* 24 */ - OPCODE(o1_putPixel), - OPCODE(o2_goblinFunc), - OPCODE(o1_createSprite), - OPCODE(o1_freeSprite), - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o1_returnTo), - OPCODE(o1_loadSpriteContent), - OPCODE(o1_copySprite), - OPCODE(o1_fillRect), - /* 34 */ - OPCODE(o1_drawLine), - OPCODE(o1_strToLong), - OPCODE(o1_invalidate), - OPCODE(o1_setBackDelta), - /* 38 */ - OPCODE(o1_playSound), - OPCODE(o2_stopSound), - OPCODE(o2_loadSound), - OPCODE(o1_freeSoundSlot), - /* 3C */ - OPCODE(o1_waitEndPlay), - OPCODE(o1_playComposition), - OPCODE(o2_getFreeMem), - OPCODE(o2_checkData), - /* 40 */ - {0, ""}, - OPCODE(o1_prepareStr), - OPCODE(o1_insertStr), - OPCODE(o1_cutStr), - /* 44 */ - OPCODE(o1_strstr), - OPCODE(o1_istrlen), - OPCODE(o1_setMousePos), - OPCODE(o1_setFrameRate), - /* 48 */ - OPCODE(o1_animatePalette), - OPCODE(o1_animateCursor), - OPCODE(o1_blitCursor), - OPCODE(o1_loadFont), - /* 4C */ - OPCODE(o1_freeFont), - OPCODE(o2_readData), - OPCODE(o2_writeData), - OPCODE(o1_manageDataFile), - }; - - static const OpcodeGoblinEntryV4 opcodesGoblin[71] = { - /* 00 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 04 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 08 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 14 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 18 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 1C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 20 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 24 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 34 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 38 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 3C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 40 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 44 */ - {0, ""}, - {0, ""}, - {0, ""}, - }; - - _opcodesDrawV4 = opcodesDraw; - _opcodesFuncV4 = opcodesFunc; - _opcodesGoblinV4 = opcodesGoblin; -} - -void Inter_v4::executeDrawOpcode(byte i) { - debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)", - i, i, getOpcodeDrawDesc(i)); - - OpcodeDrawProcV4 op = _opcodesDrawV4[i].proc; - - if (op == 0) - warning("unimplemented opcodeDraw: %d", i); - else - (this->*op) (); -} - -bool Inter_v4::executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms) { - debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s) - %s, %d, %d", - i, j, i, j, getOpcodeFuncDesc(i, j), _vm->_game->_curTotFile, - (uint) (_vm->_global->_inter_execPtr - _vm->_game->_totFileData), - (uint) (_vm->_global->_inter_execPtr - _vm->_game->_totFileData - params.counter - 4)); - - if ((i > 4) || (j > 15)) { - warning("unimplemented opcodeFunc: %d.%d", i, j); - return false; - } - - OpcodeFuncProcV4 op = _opcodesFuncV4[i*16 + j].proc; - - if (op == 0) - warning("unimplemented opcodeFunc: %d.%d", i, j); - else - return (this->*op) (params); +void Inter_v4::setupOpcodesDraw() { + Inter_v3::setupOpcodesDraw(); - return false; + OPCODEDRAW(0x80, o4_initScreen); + OPCODEDRAW(0x83, o4_playVmdOrMusic); } -void Inter_v4::executeGoblinOpcode(int i, OpGobParams ¶ms) { - debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)", - i, i, getOpcodeGoblinDesc(i)); - - OpcodeGoblinProcV4 op = 0; - - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) { - op = _opcodesGoblinV4[_goblinFuncLookUp[j][1]].proc; - break; - } - - if (op == 0) { - warning("unimplemented opcodeGoblin: %d", i); - - int16 val; - - _vm->_global->_inter_execPtr -= 2; - val = load16(); - _vm->_global->_inter_execPtr += val << 1; - } else - (this->*op) (params); -} - -const char *Inter_v4::getOpcodeDrawDesc(byte i) { - return _opcodesDrawV4[i].desc; -} - -const char *Inter_v4::getOpcodeFuncDesc(byte i, byte j) { - if ((i > 4) || (j > 15)) - return ""; - - return _opcodesFuncV4[i*16 + j].desc; +void Inter_v4::setupOpcodesFunc() { + Inter_v3::setupOpcodesFunc(); } -const char *Inter_v4::getOpcodeGoblinDesc(int i) { - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) - return _opcodesGoblinV4[_goblinFuncLookUp[j][1]].desc; - return ""; +void Inter_v4::setupOpcodesGob() { } void Inter_v4::o4_initScreen() { @@ -722,13 +65,13 @@ void Inter_v4::o4_initScreen() { int16 videoMode; int16 width, height; - offY = load16(); + offY = _vm->_game->_script->readInt16(); videoMode = offY & 0xFF; offY = (offY >> 8) & 0xFF; - width = _vm->_parse->parseValExpr(); - height = _vm->_parse->parseValExpr(); + width = _vm->_game->_script->readValExpr(); + height = _vm->_game->_script->readValExpr(); _vm->_video->clearScreen(); @@ -809,8 +152,8 @@ void Inter_v4::o4_playVmdOrMusic() { uint16 palCmd; bool close; - evalExpr(0); - strncpy0(fileName, _vm->_global->_inter_resStr, 127); + _vm->_game->_script->evalExpr(0); + strncpy0(fileName, _vm->_game->_script->getResultStr(), 127); // WORKAROUND: The nut rolling animation in the administration center // in Woodruff is called "noixroul", but the scripts think it's "noixroule". @@ -818,14 +161,14 @@ void Inter_v4::o4_playVmdOrMusic() { (!scumm_stricmp(fileName, "noixroule"))) strcpy(fileName, "noixroul"); - x = _vm->_parse->parseValExpr(); - y = _vm->_parse->parseValExpr(); - startFrame = _vm->_parse->parseValExpr(); - lastFrame = _vm->_parse->parseValExpr(); - breakKey = _vm->_parse->parseValExpr(); - flags = _vm->_parse->parseValExpr(); - palStart = _vm->_parse->parseValExpr(); - palEnd = _vm->_parse->parseValExpr(); + x = _vm->_game->_script->readValExpr(); + y = _vm->_game->_script->readValExpr(); + startFrame = _vm->_game->_script->readValExpr(); + lastFrame = _vm->_game->_script->readValExpr(); + breakKey = _vm->_game->_script->readValExpr(); + flags = _vm->_game->_script->readValExpr(); + palStart = _vm->_game->_script->readValExpr(); + palEnd = _vm->_game->_script->readValExpr(); palCmd = 1 << (flags & 0x3F); debugC(1, kDebugVideo, "Playing video \"%s\" @ %d+%d, frames %d - %d, " diff --git a/engines/gob/inter_v5.cpp b/engines/gob/inter_v5.cpp index cb5b28cb67..1c20851c8d 100644 --- a/engines/gob/inter_v5.cpp +++ b/engines/gob/inter_v5.cpp @@ -30,652 +30,73 @@ #include "gob/inter.h" #include "gob/global.h" #include "gob/game.h" -#include "gob/parse.h" +#include "gob/script.h" #include "gob/draw.h" namespace Gob { -#define OPCODE(x) _OPCODE(Inter_v5, x) - -const int Inter_v5::_goblinFuncLookUp[][2] = { - {0, 0}, - {1, 0}, - {3, 0}, - {2, 0}, - {33, 0}, - {80, 1}, - {81, 2}, - {82, 3}, - {83, 4}, - {84, 5}, - {85, 6}, - {86, 7}, - {87, 0}, - {88, 0}, - {89, 0}, - {90, 0}, - {91, 0}, - {92, 8}, - {93, 0}, - {94, 0}, - {95, 9}, - {96, 10}, - {97, 11}, - {98, 12}, - {99, 0}, - {100, 13}, - {200, 14} -}; +#define OPCODEVER Inter_v5 +#define OPCODEDRAW(i, x) _opcodesDraw[i]._OPCODEDRAW(OPCODEVER, x) +#define OPCODEFUNC(i, x) _opcodesFunc[i]._OPCODEFUNC(OPCODEVER, x) +#define OPCODEGOB(i, x) _opcodesGob[i]._OPCODEGOB(OPCODEVER, x) Inter_v5::Inter_v5(GobEngine *vm) : Inter_v4(vm) { - setupOpcodes(); } -void Inter_v5::setupOpcodes() { - static const OpcodeDrawEntryV5 opcodesDraw[256] = { - /* 00 */ - OPCODE(o1_loadMult), - OPCODE(o2_playMult), - OPCODE(o2_freeMultKeys), - {0, ""}, - /* 04 */ - {0, ""}, - {0, ""}, - {0, ""}, - OPCODE(o1_initCursor), - /* 08 */ - OPCODE(o1_initCursorAnim), - OPCODE(o1_clearCursorAnim), - OPCODE(o2_setRenderFlags), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - OPCODE(o1_loadAnim), - OPCODE(o1_freeAnim), - OPCODE(o1_updateAnim), - OPCODE(o2_multSub), - /* 14 */ - OPCODE(o2_initMult), - OPCODE(o1_freeMult), - OPCODE(o1_animate), - OPCODE(o2_loadMultObject), - /* 18 */ - OPCODE(o1_getAnimLayerInfo), - OPCODE(o1_getObjAnimSize), - OPCODE(o1_loadStatic), - OPCODE(o1_freeStatic), - /* 1C */ - OPCODE(o2_renderStatic), - OPCODE(o2_loadCurLayer), - {0, ""}, - {0, ""}, - /* 20 */ - OPCODE(o2_playCDTrack), - OPCODE(o2_waitCDTrackEnd), - OPCODE(o2_stopCD), - OPCODE(o2_readLIC), - /* 24 */ - OPCODE(o2_freeLIC), - OPCODE(o2_getCDTrackPos), - {0, ""}, - {0, ""}, - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o2_loadFontToSprite), - OPCODE(o1_freeFontToSprite), - {0, ""}, - {0, ""}, - /* 34 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 38 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 3C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 40 */ - OPCODE(o2_totSub), - OPCODE(o2_switchTotSub), - OPCODE(o2_pushVars), - OPCODE(o2_popVars), - /* 44 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 48 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 4C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 50 */ - OPCODE(o2_loadMapObjects), - OPCODE(o2_freeGoblins), - OPCODE(o2_moveGoblin), - OPCODE(o2_writeGoblinPos), - /* 54 */ - OPCODE(o2_stopGoblin), - OPCODE(o2_setGoblinState), - OPCODE(o2_placeGoblin), - {0, ""}, - /* 58 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 5C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 60 */ - {0, ""}, - OPCODE(o5_deleteFile), - {0, ""}, - {0, ""}, - /* 64 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 68 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 6C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 70 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 74 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 78 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 7C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 80 */ - OPCODE(o5_initScreen), - OPCODE(o2_scroll), - OPCODE(o2_setScrollOffset), - OPCODE(o4_playVmdOrMusic), - /* 84 */ - OPCODE(o2_getImdInfo), - OPCODE(o2_openItk), - OPCODE(o2_closeItk), - OPCODE(o2_setImdFrontSurf), - /* 88 */ - OPCODE(o2_resetImdFrontSurf), - {0, ""}, - {0, ""}, - {0, ""}, - /* 8C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 90 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 94 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 98 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 9C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* AC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* BC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* CC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* DC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* EC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* FC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""} - }; - - static const OpcodeFuncEntryV5 opcodesFunc[80] = { - /* 00 */ - OPCODE(o1_callSub), - OPCODE(o1_callSub), - OPCODE(o1_printTotText), - OPCODE(o1_loadCursor), - /* 04 */ - {0, ""}, - OPCODE(o1_switch), - OPCODE(o1_repeatUntil), - OPCODE(o1_whileDo), - /* 08 */ - OPCODE(o1_if), - OPCODE(o2_assign), - OPCODE(o1_loadSpriteToPos), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - {0, ""}, - OPCODE(o2_printText), - OPCODE(o1_loadTot), - OPCODE(o1_palLoad), - /* 14 */ - OPCODE(o1_keyFunc), - OPCODE(o1_capturePush), - OPCODE(o1_capturePop), - OPCODE(o2_animPalInit), - /* 18 */ - OPCODE(o2_addCollision), - OPCODE(o2_freeCollision), - OPCODE(o3_getTotTextItemPart), - {0, ""}, - /* 1C */ - {0, ""}, - {0, ""}, - OPCODE(o1_drawOperations), - OPCODE(o1_setcmdCount), - /* 20 */ - OPCODE(o1_return), - OPCODE(o1_renewTimeInVars), - OPCODE(o1_speakerOn), - OPCODE(o1_speakerOff), - /* 24 */ - OPCODE(o1_putPixel), - OPCODE(o2_goblinFunc), - OPCODE(o1_createSprite), - OPCODE(o1_freeSprite), - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o1_returnTo), - OPCODE(o1_loadSpriteContent), - OPCODE(o1_copySprite), - OPCODE(o1_fillRect), - /* 34 */ - OPCODE(o1_drawLine), - OPCODE(o1_strToLong), - OPCODE(o1_invalidate), - OPCODE(o1_setBackDelta), - /* 38 */ - OPCODE(o1_playSound), - OPCODE(o2_stopSound), - OPCODE(o2_loadSound), - OPCODE(o1_freeSoundSlot), - /* 3C */ - OPCODE(o1_waitEndPlay), - OPCODE(o1_playComposition), - OPCODE(o2_getFreeMem), - OPCODE(o2_checkData), - /* 40 */ - {0, ""}, - OPCODE(o1_prepareStr), - OPCODE(o1_insertStr), - OPCODE(o1_cutStr), - /* 44 */ - OPCODE(o1_strstr), - OPCODE(o5_istrlen), - OPCODE(o1_setMousePos), - OPCODE(o1_setFrameRate), - /* 48 */ - OPCODE(o1_animatePalette), - OPCODE(o1_animateCursor), - OPCODE(o1_blitCursor), - OPCODE(o1_loadFont), - /* 4C */ - OPCODE(o1_freeFont), - OPCODE(o2_readData), - OPCODE(o2_writeData), - OPCODE(o1_manageDataFile), - }; - - static const OpcodeGoblinEntryV5 opcodesGoblin[71] = { - /* 00 */ - OPCODE(o5_spaceShooter), - OPCODE(o5_getSystemCDSpeed), - OPCODE(o5_getSystemRAM), - OPCODE(o5_getSystemCPUSpeed), - /* 04 */ - OPCODE(o5_getSystemDrawSpeed), - OPCODE(o5_totalSystemSpecs), - OPCODE(o5_saveSystemSpecs), - OPCODE(o5_loadSystemSpecs), - /* 08 */ - OPCODE(o5_gob92), - OPCODE(o5_gob95), - OPCODE(o5_gob96), - OPCODE(o5_gob97), - /* 0C */ - OPCODE(o5_gob98), - OPCODE(o5_gob100), - OPCODE(o5_gob200), - {0, ""}, - /* 10 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 14 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 18 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 1C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 20 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 24 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 34 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 38 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 3C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 40 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 44 */ - {0, ""}, - {0, ""}, - {0, ""}, - }; - - _opcodesDrawV5 = opcodesDraw; - _opcodesFuncV5 = opcodesFunc; - _opcodesGoblinV5 = opcodesGoblin; -} - -void Inter_v5::executeDrawOpcode(byte i) { - debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)", - i, i, getOpcodeDrawDesc(i)); - - OpcodeDrawProcV5 op = _opcodesDrawV5[i].proc; +void Inter_v5::setupOpcodesDraw() { + Inter_v4::setupOpcodesDraw(); - if (op == 0) - warning("unimplemented opcodeDraw: %d", i); - else - (this->*op) (); + OPCODEDRAW(0x61, o5_deleteFile); + OPCODEDRAW(0x80, o5_initScreen); } -bool Inter_v5::executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms) { - debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s) - %s, %d, %d", - i, j, i, j, getOpcodeFuncDesc(i, j), _vm->_game->_curTotFile, - (uint) (_vm->_global->_inter_execPtr - _vm->_game->_totFileData), - (uint) (_vm->_global->_inter_execPtr - _vm->_game->_totFileData - params.counter - 4)); - - if ((i > 4) || (j > 15)) { - warning("unimplemented opcodeFunc: %d.%d", i, j); - return false; - } +void Inter_v5::setupOpcodesFunc() { + Inter_v4::setupOpcodesFunc(); - OpcodeFuncProcV5 op = _opcodesFuncV5[i*16 + j].proc; - - if (op == 0) - warning("unimplemented opcodeFunc: %d.%d", i, j); - else - return (this->*op) (params); - - return false; -} - -void Inter_v5::executeGoblinOpcode(int i, OpGobParams ¶ms) { - debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)", - i, i, getOpcodeGoblinDesc(i)); - - OpcodeGoblinProcV5 op = 0; - - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) { - op = _opcodesGoblinV5[_goblinFuncLookUp[j][1]].proc; - break; - } - - _vm->_global->_inter_execPtr -= 2; - - if (op == 0) { - warning("unimplemented opcodeGoblin: %d", i); - - int16 paramCount = load16(); - _vm->_global->_inter_execPtr += paramCount * 2; - } else { - params.extraData = i; - - (this->*op) (params); - } + OPCODEFUNC(0x45, o5_istrlen); } -const char *Inter_v5::getOpcodeDrawDesc(byte i) { - return _opcodesDrawV5[i].desc; -} - -const char *Inter_v5::getOpcodeFuncDesc(byte i, byte j) { - if ((i > 4) || (j > 15)) - return ""; - - return _opcodesFuncV5[i*16 + j].desc; -} - -const char *Inter_v5::getOpcodeGoblinDesc(int i) { - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) - return _opcodesGoblinV5[_goblinFuncLookUp[j][1]].desc; - return ""; +void Inter_v5::setupOpcodesGob() { + OPCODEGOB( 0, o5_spaceShooter); + OPCODEGOB( 1, o5_spaceShooter); + OPCODEGOB( 2, o5_spaceShooter); + OPCODEGOB( 3, o5_spaceShooter); + + OPCODEGOB( 33, o5_spaceShooter); + + OPCODEGOB( 80, o5_getSystemCDSpeed); + OPCODEGOB( 81, o5_getSystemRAM); + OPCODEGOB( 82, o5_getSystemCPUSpeed); + OPCODEGOB( 83, o5_getSystemDrawSpeed); + OPCODEGOB( 84, o5_totalSystemSpecs); + + OPCODEGOB( 85, o5_saveSystemSpecs); + OPCODEGOB( 86, o5_loadSystemSpecs); + + OPCODEGOB( 87, o5_spaceShooter); + OPCODEGOB( 88, o5_spaceShooter); + OPCODEGOB( 89, o5_spaceShooter); + OPCODEGOB( 90, o5_spaceShooter); + + OPCODEGOB( 91, o5_spaceShooter); + OPCODEGOB( 92, o5_gob92); + OPCODEGOB( 93, o5_spaceShooter); + OPCODEGOB( 94, o5_spaceShooter); + + OPCODEGOB( 95, o5_gob95); + OPCODEGOB( 96, o5_gob96); + OPCODEGOB( 97, o5_gob97); + OPCODEGOB( 98, o5_gob98); + + OPCODEGOB( 99, o5_spaceShooter); + OPCODEGOB(100, o5_gob100); + OPCODEGOB(200, o5_gob200); } void Inter_v5::o5_deleteFile() { - evalExpr(0); + _vm->_game->_script->evalExpr(0); - warning("Dynasty Stub: deleteFile \"%s\"", _vm->_global->_inter_resStr); + warning("Dynasty Stub: deleteFile \"%s\"", _vm->_game->_script->getResultStr()); } void Inter_v5::o5_initScreen() { @@ -683,13 +104,13 @@ void Inter_v5::o5_initScreen() { int16 videoMode; int16 width, height; - offY = load16(); + offY = _vm->_game->_script->readInt16(); videoMode = offY & 0xFF; offY = (offY >> 8) & 0xFF; - width = _vm->_parse->parseValExpr(); - height = _vm->_parse->parseValExpr(); + width = _vm->_game->_script->readValExpr(); + height = _vm->_game->_script->readValExpr(); warning("initScreen: %d, %d, %d, %d", width, height, offY, videoMode); @@ -784,18 +205,18 @@ bool Inter_v5::o5_istrlen(OpFuncParams ¶ms) { int16 len; uint16 type; - if (*_vm->_global->_inter_execPtr == 0x80) { - _vm->_global->_inter_execPtr++; + if (_vm->_game->_script->peekByte() == 0x80) { + _vm->_game->_script->skip(1); - strVar1 = _vm->_parse->parseVarIndex(); - strVar2 = _vm->_parse->parseVarIndex(0, &type); + strVar1 = _vm->_game->_script->readVarIndex(); + strVar2 = _vm->_game->_script->readVarIndex(0, &type); len = _vm->_draw->stringLength(GET_VARO_STR(strVar1), READ_VARO_UINT16(strVar2)); } else { - strVar1 = _vm->_parse->parseVarIndex(); - strVar2 = _vm->_parse->parseVarIndex(0, &type); + strVar1 = _vm->_game->_script->readVarIndex(); + strVar2 = _vm->_game->_script->readVarIndex(0, &type); if (_vm->_global->_language == 10) { // Extra handling for Japanese strings @@ -814,40 +235,36 @@ bool Inter_v5::o5_istrlen(OpFuncParams ¶ms) { } void Inter_v5::o5_spaceShooter(OpGobParams ¶ms) { - int16 paramCount = load16(); - warning("Dynasty Stub: Space shooter: %d, %d, %s", - params.extraData, paramCount, _vm->_game->_curTotFile); + params.extraData, params.paramCount, _vm->_game->_curTotFile); - if (paramCount < 4) { + if (params.paramCount < 4) { warning("Space shooter variable counter < 4"); - _vm->_global->_inter_execPtr += paramCount * 2; + _vm->_game->_script->skip(params.paramCount * 2); return; } - uint32 var1 = load16() * 4; - uint32 var2 = load16() * 4; + uint32 var1 = _vm->_game->_script->readInt16() * 4; + uint32 var2 = _vm->_game->_script->readInt16() * 4; - load16(); - load16(); + _vm->_game->_script->readInt16(); + _vm->_game->_script->readInt16(); if (params.extraData != 0) { WRITE_VARO_UINT32(var1, 2); WRITE_VARO_UINT32(var2, 0); } else { - if (paramCount < 5) { + if (params.paramCount < 5) { warning("Space shooter variable counter < 5"); return; } - _vm->_global->_inter_execPtr += (paramCount - 4) * 2; + _vm->_game->_script->skip((params.paramCount - 4) * 2); } } void Inter_v5::o5_getSystemCDSpeed(OpGobParams ¶ms) { - _vm->_global->_inter_execPtr += 2; - - WRITE_VAR_UINT32(load16(), 100); // Fudging 100% + WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 100); // Fudging 100% Video::FontDesc *font; if ((font = _vm->_util->loadFont("SPEED.LET"))) { @@ -859,9 +276,7 @@ void Inter_v5::o5_getSystemCDSpeed(OpGobParams ¶ms) { } void Inter_v5::o5_getSystemRAM(OpGobParams ¶ms) { - _vm->_global->_inter_execPtr += 2; - - WRITE_VAR_UINT32(load16(), 100); // Fudging 100% + WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 100); // Fudging 100% Video::FontDesc *font; if ((font = _vm->_util->loadFont("SPEED.LET"))) { @@ -873,9 +288,7 @@ void Inter_v5::o5_getSystemRAM(OpGobParams ¶ms) { } void Inter_v5::o5_getSystemCPUSpeed(OpGobParams ¶ms) { - _vm->_global->_inter_execPtr += 2; - - WRITE_VAR_UINT32(load16(), 100); // Fudging 100% + WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 100); // Fudging 100% Video::FontDesc *font; if ((font = _vm->_util->loadFont("SPEED.LET"))) { @@ -887,9 +300,7 @@ void Inter_v5::o5_getSystemCPUSpeed(OpGobParams ¶ms) { } void Inter_v5::o5_getSystemDrawSpeed(OpGobParams ¶ms) { - _vm->_global->_inter_execPtr += 2; - - WRITE_VAR_UINT32(load16(), 100); // Fudging 100% + WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 100); // Fudging 100% Video::FontDesc *font; if ((font = _vm->_util->loadFont("SPEED.LET"))) { @@ -901,9 +312,7 @@ void Inter_v5::o5_getSystemDrawSpeed(OpGobParams ¶ms) { } void Inter_v5::o5_totalSystemSpecs(OpGobParams ¶ms) { - _vm->_global->_inter_execPtr += 2; - - WRITE_VAR_UINT32(load16(), 100); // Fudging 100% + WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 100); // Fudging 100% Video::FontDesc *font; if ((font = _vm->_util->loadFont("SPEED.LET"))) { @@ -917,8 +326,6 @@ void Inter_v5::o5_totalSystemSpecs(OpGobParams ¶ms) { void Inter_v5::o5_saveSystemSpecs(OpGobParams ¶ms) { warning("Dynasty Stub: Saving system specifications"); - _vm->_global->_inter_execPtr += 2; - /* FILE *f = fopen("SAVE\\SPEED.INF", w); fwrite(&_cdSpeed, sizeof(_cdSpeed), 1, f); @@ -933,8 +340,6 @@ void Inter_v5::o5_saveSystemSpecs(OpGobParams ¶ms) { void Inter_v5::o5_loadSystemSpecs(OpGobParams ¶ms) { warning("Dynasty Stub: Loading system specifications"); - _vm->_global->_inter_execPtr += 2; - /* FILE *f = fopen("SAVE\\SPEED.INF", r); fread(&_cdSpeed, sizeof(_cdSpeed), 1, f); @@ -971,32 +376,26 @@ void Inter_v5::o5_loadSystemSpecs(OpGobParams ¶ms) { void Inter_v5::o5_gob92(OpGobParams ¶ms) { warning("Dynasty Stub: GobFunc 92"); - _vm->_global->_inter_execPtr += 2; - - WRITE_VAR_UINT32(load16(), 0 /* (uint32) ((int32) ((int8) _gob92_1)) */); + WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 0 /* (uint32) ((int32) ((int8) _gob92_1)) */); } void Inter_v5::o5_gob95(OpGobParams ¶ms) { warning("Dynasty Stub: GobFunc 95"); - _vm->_global->_inter_execPtr += 2; - - WRITE_VAR_UINT32(load16(), 0 /* (uint32) ((int32) ((int16) speedThrottle4)) */); - WRITE_VAR_UINT32(load16(), 0 /* (uint32) ((int32) ((int8) speedThrottle3)) */); - WRITE_VAR_UINT32(load16(), 0 /* (uint32) ((int32) ((int8) speedThrottle2)) */); - WRITE_VAR_UINT32(load16(), 0 /* (uint32) ((int32) ((int16) speedThrottle1)) */); + WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 0 /* (uint32) ((int32) ((int16) speedThrottle4)) */); + WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 0 /* (uint32) ((int32) ((int8) speedThrottle3)) */); + WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 0 /* (uint32) ((int32) ((int8) speedThrottle2)) */); + WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 0 /* (uint32) ((int32) ((int16) speedThrottle1)) */); } void Inter_v5::o5_gob96(OpGobParams ¶ms) { int16 speedThrottle4, speedThrottle1; byte speedThrottle3, speedThrottle2; - _vm->_global->_inter_execPtr += 2; - - speedThrottle4 = READ_VAR_UINT16(load16()); - speedThrottle3 = READ_VAR_UINT8(load16()); - speedThrottle2 = READ_VAR_UINT8(load16()); - speedThrottle1 = READ_VAR_UINT16(load16()); + speedThrottle4 = READ_VAR_UINT16(_vm->_game->_script->readInt16()); + speedThrottle3 = READ_VAR_UINT8(_vm->_game->_script->readInt16()); + speedThrottle2 = READ_VAR_UINT8(_vm->_game->_script->readInt16()); + speedThrottle1 = READ_VAR_UINT16(_vm->_game->_script->readInt16()); warning("Dynasty Stub: GobFunc 96: %d, %d, %d, %d", speedThrottle4, speedThrottle3, speedThrottle2, speedThrottle1); @@ -1006,23 +405,17 @@ void Inter_v5::o5_gob96(OpGobParams ¶ms) { void Inter_v5::o5_gob97(OpGobParams ¶ms) { _gob_97_98_val = 1; - - _vm->_global->_inter_execPtr += 2; } void Inter_v5::o5_gob98(OpGobParams ¶ms) { _gob_97_98_val = 0; - - _vm->_global->_inter_execPtr += 2; } void Inter_v5::o5_gob100(OpGobParams ¶ms) { - _vm->_global->_inter_execPtr += 2; - - uint16 var1 = READ_VAR_UINT16(load16()); - uint16 var2 = READ_VAR_UINT16(load16()); - uint16 var3 = READ_VAR_UINT16(load16()); - uint16 var4 = READ_VAR_UINT16(load16()); + uint16 var1 = READ_VAR_UINT16(_vm->_game->_script->readInt16()); + uint16 var2 = READ_VAR_UINT16(_vm->_game->_script->readInt16()); + uint16 var3 = READ_VAR_UINT16(_vm->_game->_script->readInt16()); + uint16 var4 = READ_VAR_UINT16(_vm->_game->_script->readInt16()); warning("Dynasty Stub: GobFunc 100: %d, %d, %d, %d", var1, var2, var3, var4); @@ -1031,11 +424,9 @@ void Inter_v5::o5_gob100(OpGobParams ¶ms) { } void Inter_v5::o5_gob200(OpGobParams ¶ms) { - _vm->_global->_inter_execPtr += 2; - - uint16 var1 = load16(); // index into the spritesArray - uint16 var2 = load16(); - uint16 var3 = load16(); + uint16 var1 = _vm->_game->_script->readUint16(); // index into the spritesArray + uint16 var2 = _vm->_game->_script->readUint16(); + uint16 var3 = _vm->_game->_script->readUint16(); warning("Dynasty Stub: GobFunc 200: %d, %d, %d", var1, var2, var3); } diff --git a/engines/gob/inter_v6.cpp b/engines/gob/inter_v6.cpp index f40314f87e..506de821d4 100644 --- a/engines/gob/inter_v6.cpp +++ b/engines/gob/inter_v6.cpp @@ -32,626 +32,43 @@ #include "gob/helper.h" #include "gob/global.h" #include "gob/game.h" -#include "gob/parse.h" +#include "gob/expression.h" +#include "gob/script.h" +#include "gob/resources.h" #include "gob/draw.h" #include "gob/sound/sound.h" #include "gob/videoplayer.h" namespace Gob { -#define OPCODE(x) _OPCODE(Inter_v6, x) - -const int Inter_v6::_goblinFuncLookUp[][2] = { - {0, 0}, -}; +#define OPCODEVER Inter_v6 +#define OPCODEDRAW(i, x) _opcodesDraw[i]._OPCODEDRAW(OPCODEVER, x) +#define OPCODEFUNC(i, x) _opcodesFunc[i]._OPCODEFUNC(OPCODEVER, x) +#define OPCODEGOB(i, x) _opcodesGob[i]._OPCODEGOB(OPCODEVER, x) Inter_v6::Inter_v6(GobEngine *vm) : Inter_v5(vm) { _gotFirstPalette = false; - - setupOpcodes(); -} - -void Inter_v6::setupOpcodes() { - static const OpcodeDrawEntryV6 opcodesDraw[256] = { - /* 00 */ - OPCODE(o1_loadMult), - OPCODE(o2_playMult), - OPCODE(o2_freeMultKeys), - {0, ""}, - /* 04 */ - {0, ""}, - {0, ""}, - {0, ""}, - OPCODE(o1_initCursor), - /* 08 */ - OPCODE(o1_initCursorAnim), - OPCODE(o1_clearCursorAnim), - OPCODE(o2_setRenderFlags), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - OPCODE(o1_loadAnim), - OPCODE(o1_freeAnim), - OPCODE(o1_updateAnim), - OPCODE(o2_multSub), - /* 14 */ - OPCODE(o2_initMult), - OPCODE(o1_freeMult), - OPCODE(o1_animate), - OPCODE(o2_loadMultObject), - /* 18 */ - OPCODE(o1_getAnimLayerInfo), - OPCODE(o1_getObjAnimSize), - OPCODE(o1_loadStatic), - OPCODE(o1_freeStatic), - /* 1C */ - OPCODE(o2_renderStatic), - OPCODE(o2_loadCurLayer), - {0, ""}, - {0, ""}, - /* 20 */ - OPCODE(o2_playCDTrack), - OPCODE(o2_waitCDTrackEnd), - OPCODE(o2_stopCD), - OPCODE(o2_readLIC), - /* 24 */ - OPCODE(o2_freeLIC), - OPCODE(o2_getCDTrackPos), - {0, ""}, - {0, ""}, - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o2_loadFontToSprite), - OPCODE(o1_freeFontToSprite), - {0, ""}, - {0, ""}, - /* 34 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 38 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 3C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 40 */ - OPCODE(o6_totSub), - OPCODE(o2_switchTotSub), - OPCODE(o2_pushVars), - OPCODE(o2_popVars), - /* 44 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 48 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 4C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 50 */ - OPCODE(o2_loadMapObjects), - OPCODE(o2_freeGoblins), - OPCODE(o2_moveGoblin), - OPCODE(o2_writeGoblinPos), - /* 54 */ - OPCODE(o2_stopGoblin), - OPCODE(o2_setGoblinState), - OPCODE(o2_placeGoblin), - {0, ""}, - /* 58 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 5C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 60 */ - {0, ""}, - OPCODE(o5_deleteFile), - {0, ""}, - {0, ""}, - /* 64 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 68 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 6C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 70 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 74 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 78 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 7C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 80 */ - OPCODE(o5_initScreen), - OPCODE(o2_scroll), - OPCODE(o2_setScrollOffset), - OPCODE(o6_playVmdOrMusic), - /* 84 */ - OPCODE(o2_getImdInfo), - OPCODE(o6_openItk), - OPCODE(o2_closeItk), - OPCODE(o2_setImdFrontSurf), - /* 88 */ - OPCODE(o2_resetImdFrontSurf), - {0, ""}, - {0, ""}, - {0, ""}, - /* 8C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 90 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 94 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 98 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 9C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* AC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* BC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* CC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* DC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* EC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* FC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""} - }; - - static const OpcodeFuncEntryV6 opcodesFunc[80] = { - /* 00 */ - OPCODE(o1_callSub), - OPCODE(o1_callSub), - OPCODE(o1_printTotText), - OPCODE(o6_loadCursor), - /* 04 */ - {0, ""}, - OPCODE(o1_switch), - OPCODE(o1_repeatUntil), - OPCODE(o1_whileDo), - /* 08 */ - OPCODE(o1_if), - OPCODE(o6_assign), - OPCODE(o1_loadSpriteToPos), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - {0, ""}, - OPCODE(o2_printText), - OPCODE(o1_loadTot), - OPCODE(o6_palLoad), - /* 14 */ - OPCODE(o1_keyFunc), - OPCODE(o1_capturePush), - OPCODE(o1_capturePop), - OPCODE(o2_animPalInit), - /* 18 */ - OPCODE(o2_addCollision), - OPCODE(o6_freeCollision), - OPCODE(o3_getTotTextItemPart), - {0, ""}, - /* 1C */ - {0, ""}, - {0, ""}, - OPCODE(o1_drawOperations), - OPCODE(o1_setcmdCount), - /* 20 */ - OPCODE(o1_return), - OPCODE(o1_renewTimeInVars), - OPCODE(o1_speakerOn), - OPCODE(o1_speakerOff), - /* 24 */ - OPCODE(o1_putPixel), - OPCODE(o2_goblinFunc), - OPCODE(o1_createSprite), - OPCODE(o1_freeSprite), - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o1_returnTo), - OPCODE(o1_loadSpriteContent), - OPCODE(o1_copySprite), - OPCODE(o6_fillRect), - /* 34 */ - OPCODE(o1_drawLine), - OPCODE(o1_strToLong), - OPCODE(o1_invalidate), - OPCODE(o1_setBackDelta), - /* 38 */ - OPCODE(o1_playSound), - OPCODE(o2_stopSound), - OPCODE(o2_loadSound), - OPCODE(o1_freeSoundSlot), - /* 3C */ - OPCODE(o1_waitEndPlay), - OPCODE(o1_playComposition), - OPCODE(o2_getFreeMem), - OPCODE(o2_checkData), - /* 40 */ - {0, ""}, - OPCODE(o1_prepareStr), - OPCODE(o1_insertStr), - OPCODE(o1_cutStr), - /* 44 */ - OPCODE(o1_strstr), - OPCODE(o5_istrlen), - OPCODE(o1_setMousePos), - OPCODE(o1_setFrameRate), - /* 48 */ - OPCODE(o1_animatePalette), - OPCODE(o1_animateCursor), - OPCODE(o1_blitCursor), - OPCODE(o1_loadFont), - /* 4C */ - OPCODE(o1_freeFont), - OPCODE(o2_readData), - OPCODE(o2_writeData), - OPCODE(o1_manageDataFile), - }; - - static const OpcodeGoblinEntryV6 opcodesGoblin[71] = { - /* 00 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 04 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 08 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 14 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 18 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 1C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 20 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 24 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 34 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 38 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 3C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 40 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 44 */ - {0, ""}, - {0, ""}, - {0, ""}, - }; - - _opcodesDrawV6 = opcodesDraw; - _opcodesFuncV6 = opcodesFunc; - _opcodesGoblinV6 = opcodesGoblin; -} - -void Inter_v6::executeDrawOpcode(byte i) { - debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)", - i, i, getOpcodeDrawDesc(i)); - - OpcodeDrawProcV6 op = _opcodesDrawV6[i].proc; - - if (op == 0) - warning("unimplemented opcodeDraw: %d", i); - else - (this->*op) (); -} - -bool Inter_v6::executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms) { - _vm->_video->_palLUT->buildNext(); - - debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s) - %s, %d, %d", - i, j, i, j, getOpcodeFuncDesc(i, j), _vm->_game->_curTotFile, - (uint) (_vm->_global->_inter_execPtr - _vm->_game->_totFileData), - (uint) (_vm->_global->_inter_execPtr - _vm->_game->_totFileData - params.counter - 4)); - - if ((i > 4) || (j > 15)) { - warning("unimplemented opcodeFunc: %d.%d", i, j); - return false; - } - - OpcodeFuncProcV6 op = _opcodesFuncV6[i*16 + j].proc; - - if (op == 0) - warning("unimplemented opcodeFunc: %d.%d", i, j); - else - return (this->*op) (params); - - return false; } -void Inter_v6::executeGoblinOpcode(int i, OpGobParams ¶ms) { - debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)", - i, i, getOpcodeGoblinDesc(i)); - - OpcodeGoblinProcV6 op = 0; - - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) { - op = _opcodesGoblinV6[_goblinFuncLookUp[j][1]].proc; - break; - } - - _vm->_global->_inter_execPtr -= 2; - - if (op == 0) { - warning("unimplemented opcodeGoblin: %d", i); - - int16 paramCount = load16(); - _vm->_global->_inter_execPtr += paramCount * 2; - } else { - params.extraData = i; +void Inter_v6::setupOpcodesDraw() { + Inter_v5::setupOpcodesDraw(); - (this->*op) (params); - } -} - -const char *Inter_v6::getOpcodeDrawDesc(byte i) { - return _opcodesDrawV6[i].desc; + OPCODEDRAW(0x40, o6_totSub); + OPCODEDRAW(0x83, o6_playVmdOrMusic); + OPCODEDRAW(0x85, o6_openItk); } -const char *Inter_v6::getOpcodeFuncDesc(byte i, byte j) { - if ((i > 4) || (j > 15)) - return ""; +void Inter_v6::setupOpcodesFunc() { + Inter_v5::setupOpcodesFunc(); - return _opcodesFuncV6[i*16 + j].desc; + OPCODEFUNC(0x03, o6_loadCursor); + OPCODEFUNC(0x09, o6_assign); + OPCODEFUNC(0x13, o6_palLoad); + OPCODEFUNC(0x19, o6_freeCollision); + OPCODEFUNC(0x33, o6_fillRect); } -const char *Inter_v6::getOpcodeGoblinDesc(int i) { - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) - return _opcodesGoblinV6[_goblinFuncLookUp[j][1]].desc; - return ""; +void Inter_v6::setupOpcodesGob() { } void Inter_v6::o6_totSub() { @@ -660,20 +77,20 @@ void Inter_v6::o6_totSub() { int flags; int i; - length = *_vm->_global->_inter_execPtr++; + length = _vm->_game->_script->readByte(); if ((length & 0x7F) > 13) error("Length in o2_totSub is greater than 13 (%d)", length); if (length & 0x80) { - evalExpr(0); - strcpy(totFile, _vm->_global->_inter_resStr); + _vm->_game->_script->evalExpr(0); + strcpy(totFile, _vm->_game->_script->getResultStr()); } else { for (i = 0; i < length; i++) - totFile[i] = (char) *_vm->_global->_inter_execPtr++; + totFile[i] = _vm->_game->_script->readChar(); totFile[i] = 0; } - flags = *_vm->_global->_inter_execPtr++; + flags = _vm->_game->_script->readByte(); if (flags & 0x40) warning("Urban Stub: o6_totSub(), flags & 0x40"); @@ -693,17 +110,17 @@ void Inter_v6::o6_playVmdOrMusic() { uint16 palCmd; bool close; - evalExpr(0); - strncpy0(fileName, _vm->_global->_inter_resStr, 127); - - x = _vm->_parse->parseValExpr(); - y = _vm->_parse->parseValExpr(); - startFrame = _vm->_parse->parseValExpr(); - lastFrame = _vm->_parse->parseValExpr(); - breakKey = _vm->_parse->parseValExpr(); - flags = _vm->_parse->parseValExpr(); - palStart = _vm->_parse->parseValExpr(); - palEnd = _vm->_parse->parseValExpr(); + _vm->_game->_script->evalExpr(0); + strncpy0(fileName, _vm->_game->_script->getResultStr(), 127); + + x = _vm->_game->_script->readValExpr(); + y = _vm->_game->_script->readValExpr(); + startFrame = _vm->_game->_script->readValExpr(); + lastFrame = _vm->_game->_script->readValExpr(); + breakKey = _vm->_game->_script->readValExpr(); + flags = _vm->_game->_script->readValExpr(); + palStart = _vm->_game->_script->readValExpr(); + palEnd = _vm->_game->_script->readValExpr(); palCmd = 1 << (flags & 0x3F); debugC(1, kDebugVideo, "Playing video \"%s\" @ %d+%d, frames %d - %d, " @@ -759,8 +176,8 @@ void Inter_v6::o6_playVmdOrMusic() { void Inter_v6::o6_openItk() { char fileName[32]; - evalExpr(0); - strncpy0(fileName, _vm->_global->_inter_resStr, 27); + _vm->_game->_script->evalExpr(0); + strncpy0(fileName, _vm->_game->_script->getResultStr(), 27); if (!strchr(fileName, '.')) strcat(fileName, ".ITK"); @@ -778,21 +195,21 @@ void Inter_v6::o6_openItk() { } bool Inter_v6::o6_loadCursor(OpFuncParams ¶ms) { - int16 id = load16(); + int16 id = _vm->_game->_script->readInt16(); if ((id == -1) || (id == -2)) { char file[10]; if (id == -1) { for (int i = 0; i < 9; i++) - file[i] = *_vm->_global->_inter_execPtr++; + file[i] = _vm->_game->_script->readChar(); } else - strncpy(file, GET_VAR_STR(load16()), 10); + strncpy(file, GET_VAR_STR(_vm->_game->_script->readInt16()), 10); file[9] = '\0'; - uint16 start = load16(); - int8 index = (int8) *_vm->_global->_inter_execPtr++; + uint16 start = _vm->_game->_script->readUint16(); + int8 index = _vm->_game->_script->readInt8(); int vmdSlot = _vm->_vidPlayer->slotOpen(file); @@ -820,101 +237,102 @@ bool Inter_v6::o6_loadCursor(OpFuncParams ¶ms) { return false; } - int8 index = (int8) *_vm->_global->_inter_execPtr++; + int8 index = _vm->_game->_script->readInt8(); if ((index * _vm->_draw->_cursorWidth) >= _vm->_draw->_cursorSprites->getWidth()) return false; - int16 width, height; - byte *dataBuf = _vm->_game->loadTotResource(id, 0, &width, &height); + Resource *resource = _vm->_game->_resources->getResource((uint16) id); + if (!resource) + return false; _vm->_video->fillRect(*_vm->_draw->_cursorSprites, index * _vm->_draw->_cursorWidth, 0, index * _vm->_draw->_cursorWidth + _vm->_draw->_cursorWidth - 1, _vm->_draw->_cursorHeight - 1, 0); - _vm->_video->drawPackedSprite(dataBuf, width, height, + _vm->_video->drawPackedSprite(resource->getData(), + resource->getWidth(), resource->getHeight(), index * _vm->_draw->_cursorWidth, 0, 0, *_vm->_draw->_cursorSprites); _vm->_draw->_cursorAnimLow[index] = 0; + delete resource; return false; } bool Inter_v6::o6_assign(OpFuncParams ¶ms) { - byte *savedPos; - int16 varOff; - int16 token; - int16 result; - byte loopCount; - uint16 var_6, var_A; + uint16 size, destType; + int16 dest = _vm->_game->_script->readVarIndex(&size, &destType); - varOff = _vm->_parse->parseVarIndex(&var_6, &var_A); + if (size != 0) { + int16 src; - if (var_6 != 0) { - int16 var_4; + _vm->_game->_script->push(); - savedPos = _vm->_global->_inter_execPtr; + src = _vm->_game->_script->readVarIndex(&size, 0); - var_4 = _vm->_parse->parseVarIndex(&var_6, 0); + memcpy(_vm->_inter->_variables->getAddressOff8(dest), + _vm->_inter->_variables->getAddressOff8(src), size * 4); - memcpy(_vm->_inter->_variables->getAddressOff8(varOff), - _vm->_inter->_variables->getAddressOff8(var_4), var_6 * 4); + _vm->_game->_script->pop(); - _vm->_global->_inter_execPtr = savedPos; - evalExpr(&var_4); + _vm->_game->_script->evalExpr(&src); return false; } - if (*_vm->_global->_inter_execPtr == 98) { - _vm->_global->_inter_execPtr++; - loopCount = *_vm->_global->_inter_execPtr++; + byte loopCount; + if (_vm->_game->_script->peekByte() == 98) { + _vm->_game->_script->skip(1); + loopCount = _vm->_game->_script->readByte(); for (int i = 0; i < loopCount; i++) { - uint8 c = *_vm->_global->_inter_execPtr++; - uint16 n = load16(); + uint8 c = _vm->_game->_script->readByte(); + uint16 n = _vm->_game->_script->readUint16(); - memset(_vm->_inter->_variables->getAddressOff8(varOff), c, n); + memset(_vm->_inter->_variables->getAddressOff8(dest), c, n); - varOff += n; + dest += n; } return false; - } else if (*_vm->_global->_inter_execPtr == 99) { - _vm->_global->_inter_execPtr++; - loopCount = *_vm->_global->_inter_execPtr++; + } else if (_vm->_game->_script->peekByte() == 99) { + _vm->_game->_script->skip(1); + loopCount = _vm->_game->_script->readByte(); } else loopCount = 1; for (int i = 0; i < loopCount; i++) { - token = evalExpr(&result); - switch (var_A) { - case 16: - case 18: - WRITE_VARO_UINT8(varOff + i, _vm->_global->_inter_resVal); + int16 result; + int16 srcType = _vm->_game->_script->evalExpr(&result); + + switch (destType) { + case TYPE_VAR_INT8: + case TYPE_ARRAY_INT8: + WRITE_VARO_UINT8(dest + i, _vm->_game->_script->getResultInt()); break; - case 17: - case 27: - WRITE_VARO_UINT16(varOff + i * 2, _vm->_global->_inter_resVal); + case TYPE_VAR_INT16: + case TYPE_ARRAY_INT16: + WRITE_VARO_UINT16(dest + i * 2, _vm->_game->_script->getResultInt()); break; - case 23: - case 26: - WRITE_VAR_OFFSET(varOff + i * 4, _vm->_global->_inter_resVal); + case TYPE_VAR_INT32: + case TYPE_ARRAY_INT32: + WRITE_VAR_OFFSET(dest + i * 4, _vm->_game->_script->getResultInt()); break; - case 24: - WRITE_VARO_UINT16(varOff + i * 4, _vm->_global->_inter_resVal); + case TYPE_VAR_INT32_AS_INT16: + WRITE_VARO_UINT16(dest + i * 4, _vm->_game->_script->getResultInt()); break; - case 25: - case 28: - if (token == 20) - WRITE_VARO_UINT8(varOff, result); + case TYPE_VAR_STR: + case TYPE_ARRAY_STR: + if (srcType == TYPE_IMM_INT16) + WRITE_VARO_UINT8(dest, result); else - WRITE_VARO_STR(varOff, _vm->_global->_inter_resStr); + WRITE_VARO_STR(dest, _vm->_game->_script->getResultStr()); break; } } @@ -936,7 +354,7 @@ bool Inter_v6::o6_palLoad(OpFuncParams ¶ms) { bool Inter_v6::o6_freeCollision(OpFuncParams ¶ms) { int16 id; - id = _vm->_parse->parseValExpr(); + id = _vm->_game->_script->readValExpr(); switch (id + 5) { case 0: @@ -972,17 +390,17 @@ bool Inter_v6::o6_freeCollision(OpFuncParams ¶ms) { bool Inter_v6::o6_fillRect(OpFuncParams ¶ms) { int16 destSurf; - _vm->_draw->_destSurface = destSurf = load16(); + _vm->_draw->_destSurface = destSurf = _vm->_game->_script->readInt16(); - _vm->_draw->_destSpriteX = _vm->_parse->parseValExpr(); - _vm->_draw->_destSpriteY = _vm->_parse->parseValExpr(); - _vm->_draw->_spriteRight = _vm->_parse->parseValExpr(); - _vm->_draw->_spriteBottom = _vm->_parse->parseValExpr(); + _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr(); + _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr(); + _vm->_draw->_spriteRight = _vm->_game->_script->readValExpr(); + _vm->_draw->_spriteBottom = _vm->_game->_script->readValExpr(); - evalExpr(0); + _vm->_game->_script->evalExpr(0); - _vm->_draw->_backColor = _vm->_global->_inter_resVal & 0xFFFF; - uint16 extraVar = _vm->_global->_inter_resVal >> 16; + _vm->_draw->_backColor = _vm->_game->_script->getResultInt() & 0xFFFF; + uint16 extraVar = _vm->_game->_script->getResultInt() >> 16; if (extraVar != 0) warning("Urban Stub: o6_fillRect(), extraVar = %d", extraVar); @@ -1019,11 +437,8 @@ void Inter_v6::probe16bitMusic(char *fileName) { fileName[len - 1] = 'V'; - int16 handle; - if ((handle = _vm->_dataIO->openData(fileName)) >= 0) { - _vm->_dataIO->closeData(handle); + if (_vm->_dataIO->existData(fileName)) return; - } fileName[len - 1] = '8'; } diff --git a/engines/gob/map_v1.cpp b/engines/gob/map_v1.cpp index 2c94b3fb24..dacc72d6c7 100644 --- a/engines/gob/map_v1.cpp +++ b/engines/gob/map_v1.cpp @@ -64,7 +64,6 @@ void Map_v1::init(void) { void Map_v1::loadMapObjects(const char *avjFile) { char avoName[128]; byte *dataBuf; - int16 handle; int16 tmp; int32 flag; int16 gobDataCount; @@ -75,15 +74,14 @@ void Map_v1::loadMapObjects(const char *avjFile) { strcpy(avoName, _sourceFile); strcat(avoName, ".avo"); - handle = _vm->_dataIO->openData(avoName); - if (handle >= 0) { + if (_vm->_dataIO->existData(avoName)) { _loadFromAvo = true; - _vm->_dataIO->closeData(handle); dataBuf = _vm->_dataIO->getData(avoName); } else { _loadFromAvo = false; dataBuf = _vm->_dataIO->getData(avjFile); } + Common::MemoryReadStream mapData(dataBuf, 4294967295U); init(); @@ -146,7 +144,6 @@ void Map_v1::loadMapObjects(const char *avjFile) { void Map_v1::loadSounds(Common::SeekableReadStream &data) { int16 count; - int16 handle; char buf[19]; char sndNames[20][14]; @@ -162,11 +159,9 @@ void Map_v1::loadSounds(Common::SeekableReadStream &data) { _vm->_sound->sampleLoad(&_vm->_goblin->_soundData[14], SOUND_SND, "diamant1.snd"); for (int i = 0; i < count; i++) { - handle = _vm->_dataIO->openData(sndNames[i]); - if (handle < 0) + if (!_vm->_dataIO->existData(sndNames[i])) continue; - _vm->_dataIO->closeData(handle); _vm->_sound->sampleLoad(&_vm->_goblin->_soundData[i], SOUND_SND, sndNames[i]); } } diff --git a/engines/gob/map_v2.cpp b/engines/gob/map_v2.cpp index db4f2075e1..6ceda7ab44 100644 --- a/engines/gob/map_v2.cpp +++ b/engines/gob/map_v2.cpp @@ -31,7 +31,8 @@ #include "gob/goblin.h" #include "gob/inter.h" #include "gob/game.h" -#include "gob/parse.h" +#include "gob/script.h" +#include "gob/resources.h" #include "gob/mult.h" namespace Gob { @@ -51,22 +52,24 @@ void Map_v2::loadMapObjects(const char *avjFile) { int16 mapWidth, mapHeight; int16 tmp; byte *variables; - byte *extData; uint32 tmpPos; uint32 passPos; - var = _vm->_parse->parseVarIndex(); + var = _vm->_game->_script->readVarIndex(); variables = _vm->_inter->_variables->getAddressOff8(var); - id = _vm->_inter->load16(); + id = _vm->_game->_script->readInt16(); if (id == -1) { _passMap = (int8 *) _vm->_inter->_variables->getAddressOff8(var); return; } - extData = _vm->_game->loadExtData(id, 0, 0); - Common::MemoryReadStream mapData(extData, 4294967295U); + Resource *resource = _vm->_game->_resources->getResource(id); + if (!resource) + return; + + Common::SeekableReadStream &mapData = *resource->stream(); if (mapData.readByte() == 3) { _screenWidth = 640; @@ -88,7 +91,7 @@ void Map_v2::loadMapObjects(const char *avjFile) { passPos = mapData.pos(); mapData.skip(_mapWidth * _mapHeight); - if (*extData == 1) + if (resource->getData()[0] == 1) wayPointsCount = _wayPointsCount = 40; else wayPointsCount = _wayPointsCount == 0 ? 1 : _wayPointsCount; @@ -130,11 +133,11 @@ void Map_v2::loadMapObjects(const char *avjFile) { for (int i = 0; i < _vm->_goblin->_gobsCount; i++) loadGoblinStates(mapData, i); - _vm->_goblin->_soundSlotsCount = _vm->_inter->load16(); + _vm->_goblin->_soundSlotsCount = _vm->_game->_script->readInt16(); for (int i = 0; i < _vm->_goblin->_soundSlotsCount; i++) _vm->_goblin->_soundSlots[i] = _vm->_inter->loadSound(1); - delete[] extData; + delete resource; } void Map_v2::loadGoblinStates(Common::SeekableReadStream &data, int index) { diff --git a/engines/gob/map_v4.cpp b/engines/gob/map_v4.cpp index 858e7972bc..1db3d6a3f8 100644 --- a/engines/gob/map_v4.cpp +++ b/engines/gob/map_v4.cpp @@ -31,7 +31,8 @@ #include "gob/goblin.h" #include "gob/inter.h" #include "gob/game.h" -#include "gob/parse.h" +#include "gob/script.h" +#include "gob/resources.h" #include "gob/mult.h" namespace Gob { @@ -49,14 +50,13 @@ void Map_v4::loadMapObjects(const char *avjFile) { int16 mapWidth, mapHeight; int16 tmp; byte *variables; - byte *extData; uint32 tmpPos; uint32 passPos; - var = _vm->_parse->parseVarIndex(); + var = _vm->_game->_script->readVarIndex(); variables = _vm->_inter->_variables->getAddressOff8(var); - id = _vm->_inter->load16(); + id = _vm->_game->_script->readInt16(); if (((uint16) id) >= 65520) { warning("Woodruff Stub: loadMapObjects ID >= 65520"); @@ -66,8 +66,11 @@ void Map_v4::loadMapObjects(const char *avjFile) { return; } - extData = _vm->_game->loadExtData(id, 0, 0); - Common::MemoryReadStream mapData(extData, 4294967295U); + Resource *resource = _vm->_game->_resources->getResource(id); + if (!resource) + return; + + Common::SeekableReadStream &mapData = *resource->stream(); _widthByte = mapData.readByte(); if (_widthByte == 4) { @@ -99,7 +102,7 @@ void Map_v4::loadMapObjects(const char *avjFile) { passPos = mapData.pos(); mapData.skip(_mapWidth * _mapHeight); - if (*extData == 1) + if (resource->getData()[0] == 1) wayPointsCount = _wayPointsCount = 40; else wayPointsCount = _wayPointsCount == 0 ? 1 : _wayPointsCount; @@ -146,11 +149,11 @@ void Map_v4::loadMapObjects(const char *avjFile) { for (int i = 0; i < _vm->_goblin->_gobsCount; i++) loadGoblinStates(mapData, i); - _vm->_goblin->_soundSlotsCount = _vm->_inter->load16(); + _vm->_goblin->_soundSlotsCount = _vm->_game->_script->readInt16(); for (int i = 0; i < _vm->_goblin->_soundSlotsCount; i++) _vm->_goblin->_soundSlots[i] = _vm->_inter->loadSound(1); - delete[] extData; + delete resource; } } // End of namespace Gob diff --git a/engines/gob/module.mk b/engines/gob/module.mk index 22a5cd37b9..695976da61 100644 --- a/engines/gob/module.mk +++ b/engines/gob/module.mk @@ -9,6 +9,7 @@ MODULE_OBJS := \ draw_bargon.o \ draw_fascin.o \ driver_vga.o \ + expression.o \ game.o \ game_v1.o \ game_v2.o \ @@ -43,10 +44,12 @@ MODULE_OBJS := \ mult_v1.o \ mult_v2.o \ palanim.o \ - parse.o \ + resources.o \ scenery.o \ scenery_v1.o \ scenery_v2.o \ + script.o \ + totfile.o \ util.o \ variables.o \ video.o \ diff --git a/engines/gob/mult.cpp b/engines/gob/mult.cpp index 1670c26ea5..5aec5ff76e 100644 --- a/engines/gob/mult.cpp +++ b/engines/gob/mult.cpp @@ -31,6 +31,7 @@ #include "gob/util.h" #include "gob/draw.h" #include "gob/game.h" +#include "gob/script.h" #include "gob/palanim.h" #include "gob/scenery.h" #include "gob/video.h" @@ -251,8 +252,6 @@ void Mult::playMult(int16 startFrame, int16 endFrame, char checkEscape, } void Mult::drawText(bool &stop, bool &stopNoClear) { - byte *savedIP; - int16 cmd; for (_index = 0; _index < _multData->textKeysCount; _index++) { if (_multData->textKeys[_index].frame != _frame) @@ -265,9 +264,10 @@ void Mult::drawText(bool &stop, bool &stopNoClear) { stopNoClear = true; _multData->frameStart = 0; } else if (cmd == 3) { + warning("Mult::drawText, cmd == 3"); stop = false; - savedIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr = _multData->textKeys[_index].script; +// uint32 startPos = _vm->_game->_script->pos(); +// _vm->_global->_inter_execPtr = _multData->textKeys[_index].script; } } } diff --git a/engines/gob/mult_v1.cpp b/engines/gob/mult_v1.cpp index e2c16674c9..1bb162c789 100644 --- a/engines/gob/mult_v1.cpp +++ b/engines/gob/mult_v1.cpp @@ -1,4 +1,4 @@ -/* ScummVM - Graphic Adventure Engine +/* 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 @@ -32,6 +32,8 @@ #include "gob/util.h" #include "gob/draw.h" #include "gob/game.h" +#include "gob/script.h" +#include "gob/resources.h" #include "gob/inter.h" #include "gob/scenery.h" @@ -41,9 +43,6 @@ Mult_v1::Mult_v1(GobEngine *vm) : Mult(vm) { } void Mult_v1::loadMult(int16 resId) { - uint32 dataSize; - byte *extData; - debugC(4, kDebugGameFlow, "Loading mult"); _multData = new Mult_Data; @@ -52,8 +51,11 @@ void Mult_v1::loadMult(int16 resId) { _multData->sndSlotsCount = 0; _multData->frameStart = 0; - extData = (byte *) _vm->_game->loadExtData(resId, 0, 0, &dataSize); - Common::MemoryReadStream data(extData, dataSize); + Resource *resource = _vm->_game->_resources->getResource(resId); + if (!resource) + return; + + Common::SeekableReadStream &data = *resource->stream(); _multData->staticCount = data.readSByte() + 1; _multData->animCount = data.readSByte() + 1; @@ -157,15 +159,14 @@ void Mult_v1::loadMult(int16 resId) { switch (_multData->sndKeys[i].cmd) { case 1: case 4: - _multData->sndKeys[i].resId = - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _multData->sndKeys[i].resId = _vm->_game->_script->peekUint16(); for (j = 0; j < i; j++) { if (_multData->sndKeys[i].resId == _multData->sndKeys[j].resId) { _multData->sndKeys[i].soundIndex = _multData->sndKeys[j].soundIndex; - _vm->_global->_inter_execPtr += 2; + _vm->_game->_script->skip(2); break; } } @@ -178,16 +179,16 @@ void Mult_v1::loadMult(int16 resId) { break; case 3: - _vm->_global->_inter_execPtr += 6; + _vm->_game->_script->skip(6); break; case 5: - _vm->_global->_inter_execPtr += _multData->sndKeys[i].freq * 2; + _vm->_game->_script->skip(_multData->sndKeys[i].freq * 2); break; } } - delete[] extData; + delete resource; } void Mult_v1::freeMultKeys() { diff --git a/engines/gob/mult_v2.cpp b/engines/gob/mult_v2.cpp index d9b5be0847..135c50c92c 100644 --- a/engines/gob/mult_v2.cpp +++ b/engines/gob/mult_v2.cpp @@ -32,9 +32,10 @@ #include "gob/util.h" #include "gob/draw.h" #include "gob/game.h" +#include "gob/script.h" +#include "gob/resources.h" #include "gob/goblin.h" #include "gob/inter.h" -#include "gob/parse.h" #include "gob/scenery.h" #include "gob/video.h" #include "gob/videoplayer.h" @@ -60,11 +61,9 @@ void Mult_v2::loadMult(int16 resId) { int8 index; uint8 staticCount; uint8 animCount; - uint32 dataSize; - byte *extData; bool hasImds; - index = (resId & 0x8000) ? *_vm->_global->_inter_execPtr++ : 0; + index = (resId & 0x8000) ? _vm->_game->_script->readByte() : 0; resId &= 0x7FFF; debugC(4, kDebugGameFlow, "Loading mult %d", index); @@ -80,8 +79,11 @@ void Mult_v2::loadMult(int16 resId) { _multData->sndSlotsCount = 0; _multData->frameStart = 0; - extData = (byte *) _vm->_game->loadExtData(resId, 0, 0, &dataSize); - Common::MemoryReadStream data(extData, dataSize); + Resource *resource = _vm->_game->_resources->getResource(resId); + if (!resource) + return; + + Common::SeekableReadStream &data = *resource->stream(); _multData->staticCount = staticCount = data.readSByte(); _multData->animCount = animCount = data.readSByte(); @@ -206,14 +208,13 @@ void Mult_v2::loadMult(int16 resId) { switch (_multData->sndKeys[i].cmd) { case 1: case 4: - _multData->sndKeys[i].resId = - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _multData->sndKeys[i].resId = _vm->_game->_script->peekUint16(); for (j = 0; j < i; j++) { if (_multData->sndKeys[j].resId == _multData->sndKeys[i].resId) { _multData->sndKeys[i].soundIndex = _multData->sndKeys[j].soundIndex; - _vm->_global->_inter_execPtr += 2; + _vm->_game->_script->skip(2); break; } } @@ -226,7 +227,7 @@ void Mult_v2::loadMult(int16 resId) { } break; case 3: - _vm->_global->_inter_execPtr += 4; + _vm->_game->_script->skip(4); break; case -1: @@ -244,17 +245,17 @@ void Mult_v2::loadMult(int16 resId) { if (hasImds) loadImds(data); - delete[] extData; + delete resource; } void Mult_v2::loadImds(Common::SeekableReadStream &data) { int16 size; - size = _vm->_inter->load16(); - _multData->execPtr = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += size * 2; + size = _vm->_game->_script->readInt16(); + _multData->execPtr = _vm->_game->_script->getData() + _vm->_game->_script->pos(); + _vm->_game->_script->skip(size * 2); - if (_vm->_game->_totFileData[0x29] < 51) + if (_vm->_game->_script->getVersionMinor() < 3) return; size = data.readSint16LE(); @@ -263,13 +264,27 @@ void Mult_v2::loadImds(Common::SeekableReadStream &data) { data.read(_multData->somepointer10, size * 20); } - size = _vm->_inter->load16(); + size = _vm->_game->_script->readInt16(); if (size <= 0) return; _multData->imdFiles = new char[size * 14]; - memcpy(_multData->imdFiles, _vm->_global->_inter_execPtr, size * 14); - _vm->_global->_inter_execPtr += size * 14; + memcpy(_multData->imdFiles, + _vm->_game->_script->getData() + _vm->_game->_script->pos(), size * 14); + + // WORKAROUND: The Windows version of Lost in Time has VMD not IMD files, + // but they are still referenced as IMD. + if ((_vm->getGameType() == kGameTypeLostInTime) && + (_vm->getPlatform() == Common::kPlatformWindows)) { + + for (int i = 0; i < size; i++) { + char *dot = strrchr(_multData->imdFiles + (i * 14), '.'); + if (dot) + *dot = '\0'; + } + } + + _vm->_game->_script->skip(size * 14); data.seek(2, SEEK_CUR); for (int i = 0; i < 4; i++) { _multData->imdKeysCount[i] = data.readSint16LE(); @@ -382,14 +397,16 @@ void Mult_v2::multSub(uint16 multIndex) { if (multIndex > 7) error("Multindex out of range"); + _vm->_util->notifyNewAnim(); + debugC(4, kDebugGameFlow, "Sub mult %d", multIndex); _multData = _multDatas[multIndex]; if (!_multData) { - _vm->_parse->parseValExpr(); - _vm->_parse->parseValExpr(); - _vm->_parse->parseValExpr(); - _vm->_parse->parseValExpr(); + _vm->_game->_script->readValExpr(); + _vm->_game->_script->readValExpr(); + _vm->_game->_script->readValExpr(); + _vm->_game->_script->readValExpr(); return; } @@ -412,9 +429,9 @@ void Mult_v2::multSub(uint16 multIndex) { _multData->animObjs[index][0] = flags; for (int i = 1; i < 4; i++) - _multData->animObjs[index][i] = _vm->_parse->parseValExpr(); + _multData->animObjs[index][i] = _vm->_game->_script->readValExpr(); - expr = _vm->_parse->parseValExpr(); + expr = _vm->_game->_script->readValExpr(); _multData->animKeysFrames[index] = expr; _multData->animKeysStartFrames[index] = expr; @@ -856,7 +873,7 @@ void Mult_v2::animate() { animObj.newBottom = MAX(animObj.lastBottom, _vm->_scenery->_toRedrawBottom); - if ((_vm->_game->_totFileData[0x29] > 50) && + if ((_vm->_game->_script->getVersionMinor() > 2) && (animObj.newLeft == animObj.lastLeft) && (animObj.newTop == animObj.lastTop) && (animObj.newRight == animObj.lastRight) && diff --git a/engines/gob/parse.cpp b/engines/gob/parse.cpp deleted file mode 100644 index 0fa46097a3..0000000000 --- a/engines/gob/parse.cpp +++ /dev/null @@ -1,1499 +0,0 @@ -/* 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. - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#include "common/endian.h" - -#include "gob/gob.h" -#include "gob/parse.h" -#include "gob/global.h" -#include "gob/game.h" -#include "gob/inter.h" - -namespace Gob { - -Parse::Parse(GobEngine *vm) : _vm(vm) { -} - -int32 Parse::encodePtr(byte *ptr, int type) { - int32 offset = 0; - - switch (type) { - case kExecPtr: - offset = ptr - _vm->_game->_totFileData; - break; - case kInterVar: - offset = ptr - ((byte *) _vm->_inter->_variables->getAddressOff8(0)); - break; - case kResStr: - offset = ptr - ((byte *) _vm->_global->_inter_resStr); - break; - default: - error("Parse::encodePtr(): Unknown pointer type"); - } - assert((offset & 0xF0000000) == 0); - return (type << 28) | offset; -} - -byte *Parse::decodePtr(int32 n) { - byte *ptr; - - switch (n >> 28) { - case kExecPtr: - ptr = _vm->_game->_totFileData; - break; - case kInterVar: - ptr = (byte *) _vm->_inter->_variables->getAddressOff8(0); - break; - case kResStr: - ptr = (byte *) _vm->_global->_inter_resStr; - break; - default: - error("Parse::decodePtr(): Unknown pointer type"); - } - return ptr + (n & 0x0FFFFFFF); -} - -void Parse::skipExpr(char stopToken) { - int16 dimCount; - byte operation; - int16 num; - int16 dim; - - num = 0; - while (true) { - operation = *_vm->_global->_inter_execPtr++; - - if ((operation >= 14) && (operation <= OP_FUNC)) { - switch (operation) { - case 14: - _vm->_global->_inter_execPtr += 4; - if (*_vm->_global->_inter_execPtr == 97) - _vm->_global->_inter_execPtr++; - break; - - case OP_LOAD_VAR_INT16: - case OP_LOAD_VAR_INT8: - case OP_LOAD_IMM_INT16: - case 23: - case 24: - _vm->_global->_inter_execPtr += 2; - break; - - case OP_LOAD_IMM_INT32: - _vm->_global->_inter_execPtr += 4; - break; - - case OP_LOAD_IMM_INT8: - _vm->_global->_inter_execPtr += 1; - break; - - case OP_LOAD_IMM_STR: - _vm->_global->_inter_execPtr += - strlen((char *) _vm->_global->_inter_execPtr) + 1; - break; - - case OP_LOAD_VAR_STR: - _vm->_global->_inter_execPtr += 2; - if (*_vm->_global->_inter_execPtr == 13) { - _vm->_global->_inter_execPtr++; - skipExpr(OP_END_MARKER); - } - break; - - case 15: - _vm->_global->_inter_execPtr += 2; - - case OP_ARRAY_UINT8: - case OP_ARRAY_UINT32: - case OP_ARRAY_UINT16: - case OP_ARRAY_STR: - dimCount = _vm->_global->_inter_execPtr[2]; - // skip header and dimensions - _vm->_global->_inter_execPtr += 3 + dimCount; - // skip indices - for (dim = 0; dim < dimCount; dim++) - skipExpr(OP_END_MARKER); - - if ((operation == OP_ARRAY_STR) && (*_vm->_global->_inter_execPtr == 13)) { - _vm->_global->_inter_execPtr++; - skipExpr(OP_END_MARKER); - } - break; - - case OP_FUNC: - _vm->_global->_inter_execPtr++; - skipExpr(OP_END_EXPR); - } - continue; - } // if ((operation >= OP_ARRAY_UINT8) && (operation <= OP_FUNC)) - - if (operation == OP_BEGIN_EXPR) { - num++; - continue; - } - - if ((operation == OP_NOT) || ((operation >= OP_NEG) && (operation <= 8))) - continue; - - if ((operation >= OP_OR) && (operation <= OP_NEQ)) - continue; - - if (operation == OP_END_EXPR) - num--; - - if (operation != stopToken) - continue; - - if ((stopToken != OP_END_EXPR) || (num < 0)) - return; - } -} - -void Parse::printExpr(char stopToken) { - // Expression printing disabled by default - return; - - byte *savedPos = _vm->_global->_inter_execPtr; - printExpr_internal(stopToken); - - // restore IP to start of expression - _vm->_global->_inter_execPtr = savedPos; -} - -void Parse::printExpr_internal(char stopToken) { - int16 dimCount; - byte operation; - int16 num; - int16 dim; - byte *arrDesc; - byte func; - - num = 0; - while (true) { - operation = *_vm->_global->_inter_execPtr++; - - if ((operation >= OP_ARRAY_UINT8) && (operation <= OP_FUNC)) { - // operands - - switch (operation) { - case OP_LOAD_VAR_INT16: // int16 variable load - debugN(5, "var16_%d", _vm->_inter->load16()); - break; - - case OP_LOAD_VAR_INT8: // int8 variable load: - debugN(5, "var8_%d", _vm->_inter->load16()); - break; - - case OP_LOAD_IMM_INT32: // int32/uint32 immediate - debugN(5, "%d", READ_LE_UINT32(_vm->_global->_inter_execPtr)); - _vm->_global->_inter_execPtr += 4; - break; - - case OP_LOAD_IMM_INT16: // int16 immediate - debugN(5, "%d", _vm->_inter->load16()); - break; - - case OP_LOAD_IMM_INT8: // int8 immediate - debugN(5, "%d", (int8) *_vm->_global->_inter_execPtr++); - break; - - case OP_LOAD_IMM_STR: // string immediate - debugN(5, "\42%s\42", _vm->_global->_inter_execPtr); - _vm->_global->_inter_execPtr += - strlen((char *) _vm->_global->_inter_execPtr) + 1; - break; - - case 23: // uint32 variable load - case 24: // uint32 variable load as uint16 - debugN(5, "var_%d", _vm->_inter->load16()); - break; - - case OP_LOAD_VAR_STR: // string variable load - debugN(5, "(&var_%d)", _vm->_inter->load16()); - if (*_vm->_global->_inter_execPtr == 13) { - _vm->_global->_inter_execPtr++; - debugN(5, "{"); - printExpr_internal(OP_END_MARKER); // this also prints the closing } - } - break; - - case OP_ARRAY_UINT8: // uint8 array access - case OP_ARRAY_UINT32: // uint32 array access - case OP_ARRAY_UINT16: // uint16 array access - case OP_ARRAY_STR: // string array access - debugN(5, "\n"); - if (operation == OP_ARRAY_STR) - debugN(5, "(&"); - - debugN(5, "var_%d[", _vm->_inter->load16()); - dimCount = *_vm->_global->_inter_execPtr++; - arrDesc = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += dimCount; - for (dim = 0; dim < dimCount; dim++) { - printExpr_internal(OP_END_MARKER); - debugN(5, " of %d", (int16) arrDesc[dim]); - if (dim != dimCount - 1) - debugN(5, ","); - } - debugN(5, "]"); - if (operation == OP_ARRAY_STR) - debugN(5, ")"); - - if ((operation == OP_ARRAY_STR) && (*_vm->_global->_inter_execPtr == 13)) { - _vm->_global->_inter_execPtr++; - debugN(5, "{"); - printExpr_internal(OP_END_MARKER); // this also prints the closing } - } - break; - - case OP_FUNC: // function - func = *_vm->_global->_inter_execPtr++; - if (func == FUNC_SQR) - debugN(5, "sqr("); - else if (func == FUNC_RAND) - debugN(5, "rand("); - else if (func == FUNC_ABS) - debugN(5, "abs("); - else if ((func == FUNC_SQRT1) || (func == FUNC_SQRT2) || (func == FUNC_SQRT3)) - debugN(5, "sqrt("); - else - debugN(5, "id("); - printExpr_internal(OP_END_EXPR); - break; - } - continue; - } // if ((operation >= OP_ARRAY_UINT8) && (operation <= OP_FUNC)) - - // operators - switch (operation) { - case OP_BEGIN_EXPR: - debugN(5, "("); - break; - - case OP_NOT: - debugN(5, "!"); - break; - - case OP_END_EXPR: - debugN(5, ")"); - break; - - case OP_NEG: - debugN(5, "-"); - break; - - case OP_ADD: - debugN(5, "+"); - break; - - case OP_SUB: - debugN(5, "-"); - break; - - case OP_BITOR: - debugN(5, "|"); - break; - - case OP_MUL: - debugN(5, "*"); - break; - - case OP_DIV: - debugN(5, "/"); - break; - - case OP_MOD: - debugN(5, "%%"); - break; - - case OP_BITAND: - debugN(5, "&"); - break; - - case OP_OR: - debugN(5, "||"); - break; - - case 31: - debugN(5, "&&"); - break; - - case OP_LESS: - debugN(5, "<"); - break; - - case OP_LEQ: - debugN(5, "<="); - break; - - case OP_GREATER: - debugN(5, ">"); - break; - - case OP_GEQ: - debugN(5, ">="); - break; - - case OP_EQ: - debugN(5, "=="); - break; - - case OP_NEQ: - debugN(5, "!="); - break; - - case 99: - debugN(5, "\n"); - break; - - case OP_END_MARKER: - debugN(5, "}"); - if (stopToken != OP_END_MARKER) { - debugN(5, "Closing paren without opening?"); - } - break; - - default: - debugN(5, "<%d>", (int16) operation); - error("Parse::printExpr(): invalid operator in expression"); - break; - } - - if (operation == OP_BEGIN_EXPR) { - num++; - continue; - } - - if ((operation == OP_NOT) || ((operation >= OP_NEG) && (operation <= 8))) - continue; - - if ((operation >= OP_OR) && (operation <= OP_NEQ)) - continue; - - if (operation == OP_END_EXPR) - num--; - - if (operation == stopToken) { - if ((stopToken != OP_END_EXPR) || (num < 0)) { - return; - } - } - } -} - - -void Parse::printVarIndex() { - byte *arrDesc; - int16 dim; - int16 dimCount; - int16 operation; - int16 temp; - - byte *pos = _vm->_global->_inter_execPtr; - - operation = *_vm->_global->_inter_execPtr++; - switch (operation) { - case 23: - case OP_LOAD_VAR_STR: - temp = _vm->_inter->load16() * 4; - debugN(5, "&var_%d", temp); - if ((operation == OP_LOAD_VAR_STR) && (*_vm->_global->_inter_execPtr == 13)) { - _vm->_global->_inter_execPtr++; - debugN(5, "+"); - printExpr(OP_END_MARKER); - } - break; - - case OP_ARRAY_UINT32: - case OP_ARRAY_STR: - debugN(5, "&var_%d[", _vm->_inter->load16()); - dimCount = *_vm->_global->_inter_execPtr++; - arrDesc = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += dimCount; - for (dim = 0; dim < dimCount; dim++) { - printExpr(OP_END_MARKER); - debugN(5, " of %d", (int16) arrDesc[dim]); - if (dim != dimCount - 1) - debugN(5, ","); - } - debugN(5, "]"); - - if ((operation == OP_ARRAY_STR) && (*_vm->_global->_inter_execPtr == 13)) { - _vm->_global->_inter_execPtr++; - debugN(5, "+"); - printExpr(OP_END_MARKER); - } - break; - - default: - debugN(5, "var_0"); - break; - } - debugN(5, "\n"); - _vm->_global->_inter_execPtr = pos; - return; -} - -int16 Parse::getOffset(int16 arg_0, byte arg_2, uint32 arg_3, uint16 arg_7, uint16 arg_9) { - if (arg_0 < 0) - return 0; - - if (arg_2 > arg_0) - return arg_0; - - return arg_2 - 1; -} - -int Parse::cmpHelper(byte *operPtr, int32 *valPtr) { - byte var_C = operPtr[-3]; - int cmpTemp = 0; - if (var_C == OP_LOAD_IMM_INT16) { - cmpTemp = (int)valPtr[-3] - (int)valPtr[-1]; - } else if (var_C == OP_LOAD_IMM_STR) { - if ((char *)decodePtr(valPtr[-3]) != _vm->_global->_inter_resStr) { - strcpy(_vm->_global->_inter_resStr, (char *)decodePtr(valPtr[-3])); - valPtr[-3] = encodePtr((byte *) _vm->_global->_inter_resStr, kResStr); - } - cmpTemp = strcmp(_vm->_global->_inter_resStr, (char *)decodePtr(valPtr[-1])); - } - - return cmpTemp; -} - -int16 Parse::parseVarIndex(uint16 *arg_0, uint16 *arg_4) { - int16 temp2; - byte *arrDesc; - int16 dim; - int16 dimCount; - int16 operation; - int16 temp; - int16 offset; - int16 val; - uint32 varPos = 0; - - operation = *_vm->_global->_inter_execPtr++; - - while ((operation == 14) || (operation == 15)) { - if (operation == 14) { - uint16 n = _vm->_inter->load16(); - varPos += n * 4; - - if (arg_0) - *arg_0 = READ_LE_UINT16(_vm->_global->_inter_execPtr); - if (arg_4) - *arg_4 = 14; - - _vm->_global->_inter_execPtr += 2; - - debugC(2, kDebugParser, "parseVarIndex: Prefix %d (%d)", varPos, operation); - - if (*_vm->_global->_inter_execPtr != 97) - return varPos; - - _vm->_global->_inter_execPtr++; - - } else if (operation == 15) { - uint16 n = _vm->_inter->load16(); - varPos += n * 4; - - uint16 var_0C = _vm->_inter->load16(); - if (arg_0) - *arg_0 = var_0C; - if (arg_4) - *arg_4 = 15; - - uint8 var_A = *_vm->_global->_inter_execPtr++; - - byte *var_12 = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += var_A; - - uint16 var_6 = 0; - - for (int i = 0; i < var_A; i++) { - temp2 = parseValExpr(OP_END_MARKER); - - int16 ax = getOffset(temp2, var_12[i], varPos, 0, 0); - - var_6 = var_6 * var_12[i] + ax; - } - - varPos += var_6 * var_0C * 4; - - debugC(2, kDebugParser, "parseVarIndex: Prefix %d (%d)", varPos, operation); - - if (*_vm->_global->_inter_execPtr != 97) - return varPos; - - _vm->_global->_inter_execPtr++; - } - - operation = *_vm->_global->_inter_execPtr++; - } - - if (arg_0) - *arg_0 = 0; - if (arg_4) - *arg_4 = operation; - - debugC(5, kDebugParser, "var parse = %d", operation); - switch (operation) { - case OP_ARRAY_UINT8: - case OP_ARRAY_UINT32: - case OP_ARRAY_UINT16: - case OP_ARRAY_STR: - temp = _vm->_inter->load16(); - dimCount = *_vm->_global->_inter_execPtr++; - arrDesc = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += dimCount; - offset = 0; - for (dim = 0; dim < dimCount; dim++) { - temp2 = parseValExpr(OP_END_MARKER); - offset = arrDesc[dim] * offset + temp2; - } - if (operation == OP_ARRAY_UINT8) - return varPos + temp + offset; - if (operation == OP_ARRAY_UINT32) - return varPos + (temp + offset) * 4; - if (operation == OP_ARRAY_UINT16) - return varPos + (temp + offset) * 2; - temp *= 4; - offset *= 4; - if (*_vm->_global->_inter_execPtr == 13) { - _vm->_global->_inter_execPtr++; - temp += parseValExpr(OP_END_MARKER); - } - return varPos + offset * _vm->_global->_inter_animDataSize + temp; - - case OP_LOAD_VAR_INT16: - return varPos + _vm->_inter->load16() * 2; - - case OP_LOAD_VAR_INT8: - return varPos + _vm->_inter->load16(); - - case 23: - case 24: - case OP_LOAD_VAR_STR: - temp = _vm->_inter->load16() * 4; - debugC(5, kDebugParser, "oper = %d", - (int16) *_vm->_global->_inter_execPtr); - if ((operation == OP_LOAD_VAR_STR) && (*_vm->_global->_inter_execPtr == 13)) { - _vm->_global->_inter_execPtr++; - val = parseValExpr(OP_END_MARKER); - temp += val; - debugC(5, kDebugParser, "parse subscript = %d", val); - } - return varPos + temp; - - default: - return 0; - } -} - -int16 Parse::parseValExpr(byte stopToken) { - int16 values[20]; - byte operStack[20]; - int16 *valPtr; - byte *operPtr; - byte *arrDesc; - byte operation; - int16 temp2; - int16 dim; - int16 dimCount; - int16 temp; - int16 offset; - int16 stkPos; - int16 brackPos; - static int16 flag = 0; - int16 oldflag; - uint32 varPos = 0; - - memset(values, 0, 20 * sizeof(int16)); - - oldflag = flag; - if (flag == 0) { - flag = 1; - printExpr(stopToken); - } - - stkPos = -1; - operPtr = operStack - 1; - valPtr = values - 1; - - while (1) { - operation = *_vm->_global->_inter_execPtr++; - - while ((operation == 14) || (operation == 15)) { - if (operation == 14) { - uint16 n = _vm->_inter->load16(); - varPos += n * 4; - - _vm->_global->_inter_execPtr += 3; - } else if (operation == 15) { - uint16 n = _vm->_inter->load16(); - varPos += n * 4; - - uint16 var_0C = _vm->_inter->load16(); - uint8 var_A = *_vm->_global->_inter_execPtr++; - - byte *var_12 = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += var_A; - - uint16 var_6 = 0; - - for (int i = 0; i < var_A; i++) { - temp2 = parseValExpr(OP_END_MARKER); - - int16 ax = getOffset(temp2, var_12[i], varPos, 0, 0); - - var_6 = var_6 * var_12[i] + ax; - } - - varPos += var_6 * var_0C * 4; - - _vm->_global->_inter_execPtr++; - } - - debugC(2, kDebugParser, "parseValExpr: Prefix %d (%d)", varPos, operation); - - operation = *_vm->_global->_inter_execPtr++; - } - - stkPos++; - operPtr++; - valPtr++; - - if ((operation >= OP_ARRAY_UINT8) && (operation <= OP_FUNC)) { - *operPtr = OP_LOAD_IMM_INT16; - switch (operation) { - case OP_ARRAY_UINT8: - case OP_ARRAY_UINT32: - case OP_ARRAY_UINT16: - case OP_ARRAY_STR: - temp = _vm->_inter->load16(); - dimCount = *_vm->_global->_inter_execPtr++; - arrDesc = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += dimCount; - offset = 0; - for (dim = 0; dim < dimCount; dim++) { - temp2 = parseValExpr(OP_END_MARKER); - offset = arrDesc[dim] * offset + temp2; - } - if (operation == OP_ARRAY_UINT8) - *valPtr = (int8) READ_VARO_UINT8(varPos + temp + offset); - else if (operation == OP_ARRAY_UINT32) - *valPtr = (uint16) READ_VARO_UINT32(varPos + temp * 4 + offset * 4); - else if (operation == OP_ARRAY_UINT16) - *valPtr = READ_VARO_UINT16(varPos + temp * 2 + offset * 2); - else if (operation == OP_ARRAY_STR) { - _vm->_global->_inter_execPtr++; - temp2 = parseValExpr(OP_END_MARKER); - *valPtr = READ_VARO_UINT8(varPos + temp * 4 + - offset * 4 * _vm->_global->_inter_animDataSize + temp2); - } - break; - - case OP_LOAD_VAR_INT16: - *valPtr = READ_VARO_UINT16(varPos + _vm->_inter->load16() * 2); - break; - - case OP_LOAD_VAR_INT8: - *valPtr = (int8) READ_VARO_UINT8(varPos + _vm->_inter->load16()); - break; - - case OP_LOAD_IMM_INT32: - *valPtr = (uint16) READ_LE_UINT32(varPos + _vm->_global->_inter_execPtr); - _vm->_global->_inter_execPtr += 4; - break; - - case OP_LOAD_IMM_INT16: - *valPtr = _vm->_inter->load16(); - break; - - case OP_LOAD_IMM_INT8: - *valPtr = (int8) *_vm->_global->_inter_execPtr++; - break; - - case 23: - *valPtr = (uint16) READ_VARO_UINT32(varPos + _vm->_inter->load16() * 4); - break; - - case 24: - *valPtr = READ_VARO_UINT16(varPos + _vm->_inter->load16() * 4); - break; - - case OP_LOAD_VAR_STR: - temp = _vm->_inter->load16() * 4; - _vm->_global->_inter_execPtr++; - temp += parseValExpr(OP_END_MARKER); - *valPtr = READ_VARO_UINT8(varPos + temp); - break; - - case OP_FUNC: - operation = *_vm->_global->_inter_execPtr++; - parseExpr(OP_END_EXPR, 0); - - if (operation == FUNC_SQR) { - _vm->_global->_inter_resVal = - _vm->_global->_inter_resVal * _vm->_global->_inter_resVal; - } else if (operation == FUNC_ABS) { - if (_vm->_global->_inter_resVal < 0) - _vm->_global->_inter_resVal = -_vm->_global->_inter_resVal; - } else if (operation == FUNC_RAND) { - _vm->_global->_inter_resVal = - _vm->_util->getRandom(_vm->_global->_inter_resVal); - } - *valPtr = _vm->_global->_inter_resVal; - break; - - } // switch - if ((stkPos > 0) && (operPtr[-1] == OP_NEG)) { - stkPos--; - operPtr--; - valPtr--; - operPtr[0] = OP_LOAD_IMM_INT16; - valPtr[0] = -valPtr[1]; - } - - if ((stkPos > 0) && (operPtr[-1] >= OP_MUL) && (operPtr[-1] <= OP_BITAND)) { - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - - switch (operPtr[1]) { - case OP_MUL: - valPtr[0] *= valPtr[2]; - break; - - case OP_DIV: - valPtr[0] /= valPtr[2]; - break; - - case OP_MOD: - valPtr[0] %= valPtr[2]; - break; - - case OP_BITAND: - valPtr[0] &= valPtr[2]; - break; - } - } // if ((stkPos > 0) && (cmdPtr[-1] >= OP_MUL) && (cmdPtr[-1] <= OP_BITAND)) - varPos = 0; - continue; - } - - if ((operation >= OP_NEG) && (operation <= OP_BEGIN_EXPR)) { - *operPtr = operation; - continue; - } - - while (stkPos >= 2) { - if (operPtr[-2] == OP_BEGIN_EXPR) { - stkPos--; - operPtr--; - valPtr--; - - operPtr[-1] = operPtr[0]; - valPtr[-1] = valPtr[0]; - if ((stkPos > 1) && (operPtr[-2] == OP_NEG)) { - operPtr[-2] = OP_LOAD_IMM_INT16; - valPtr[-2] = -valPtr[-1]; - - stkPos--; - operPtr--; - valPtr--; - } - - if ((stkPos > 2) && (operPtr[-2] >= OP_MUL) && (operPtr[-2] <= OP_BITAND)) { - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - switch (operPtr[0]) { - case OP_MUL: - valPtr[-1] *= valPtr[1]; - break; - - case OP_DIV: - valPtr[-1] /= valPtr[1]; - break; - - case OP_MOD: - valPtr[-1] %= valPtr[1]; - break; - - case OP_BITAND: - valPtr[-1] &= valPtr[1]; - break; - } - } - if (operation == OP_END_EXPR) - break; - } // operPtr[-2] == OP_BEGIN_EXPR - - for (brackPos = (stkPos - 2); (brackPos > 0) && - (operStack[brackPos] < OP_OR) && (operStack[brackPos] != OP_BEGIN_EXPR); - brackPos--) - ; - - if ((operStack[brackPos] >= OP_OR) || (operStack[brackPos] == OP_BEGIN_EXPR)) - brackPos++; - - if ((operPtr[-2] < 2) || (operPtr[-2] > 8)) - break; - - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - switch (operPtr[0]) { - case OP_ADD: - values[brackPos] += valPtr[1]; - continue; - case OP_SUB: - values[brackPos] -= valPtr[1]; - continue; - case OP_BITOR: - values[brackPos] |= valPtr[1]; - continue; - case OP_MUL: - valPtr[-1] *= valPtr[1]; - continue; - case OP_DIV: - valPtr[-1] /= valPtr[1]; - continue; - case OP_MOD: - valPtr[-1] %= valPtr[1]; - continue; - case OP_BITAND: - valPtr[-1] &= valPtr[1]; - continue; - } - } - - if (operation != OP_END_EXPR) { - if (operation != stopToken) { - debugC(5, kDebugParser, "stoptoken error: %d != %d", - operation, stopToken); - } - flag = oldflag; - return values[0]; - } - - stkPos--; - operPtr--; - valPtr--; - } -} - -int16 Parse::parseExpr(byte stopToken, byte *arg_2) { - int32 values[20]; - byte operStack[20]; - int32 prevPrevVal; - int32 prevVal; - int32 curVal; - int32 *valPtr; - byte *operPtr; - byte *arrDescPtr; - byte operation; - int16 dimCount; - int16 temp; - int16 temp2; - int16 offset; - int16 dim; - bool var_1A; - int16 stkPos; - int16 brackStart; - uint32 varPos = 0; - - memset(operStack, 0, 20); - - stkPos = -1; - operPtr = operStack - 1; - valPtr = values - 1; - - while (true) { - operation = *_vm->_global->_inter_execPtr++; - - while ((operation == 14) || (operation == 15)) { - if (operation == 14) { - uint16 n = _vm->_inter->load16(); - varPos += n * 4; - - _vm->_global->_inter_execPtr += 2; - if (*_vm->_global->_inter_execPtr == 97) - _vm->_global->_inter_execPtr++; - } else if (operation == 15) { - uint16 n = _vm->_inter->load16(); - varPos += n * 4; - - uint16 var_0C = _vm->_inter->load16(); - uint8 var_A = *_vm->_global->_inter_execPtr++; - - byte *var_12 = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += var_A; - - uint16 var_6 = 0; - - for (int i = 0; i < var_A; i++) { - temp2 = parseValExpr(OP_END_MARKER); - - int16 ax = getOffset(temp2, var_12[i], varPos, 0, 0); - - var_6 = var_6 * var_12[i] + ax; - } - - varPos += var_6 * var_0C * 4; - - if (*_vm->_global->_inter_execPtr == 97) - _vm->_global->_inter_execPtr++; - } - - debugC(2, kDebugParser, "parseExpr: Prefix %d (%d)", varPos, operation); - - operation = *_vm->_global->_inter_execPtr++; - } - - stkPos++; - operPtr++; - valPtr++; - - if ((operation >= OP_ARRAY_UINT8) && (operation <= OP_FUNC)) { - switch (operation) { - case OP_ARRAY_UINT8: - case OP_ARRAY_UINT32: - case OP_ARRAY_UINT16: - case OP_ARRAY_STR: - *operPtr = (operation == OP_ARRAY_STR) ? OP_LOAD_IMM_STR : OP_LOAD_IMM_INT16; - temp = _vm->_inter->load16(); - dimCount = *_vm->_global->_inter_execPtr++; - arrDescPtr = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += dimCount; - offset = 0; - for (dim = 0; dim < dimCount; dim++) { - temp2 = parseValExpr(OP_END_MARKER); - offset = offset * arrDescPtr[dim] + temp2; - } - if (operation == OP_ARRAY_UINT8) - *valPtr = (int8) READ_VARO_UINT8(varPos + temp + offset); - else if (operation == OP_ARRAY_UINT32) - *valPtr = READ_VARO_UINT32(varPos + temp * 4 + offset * 4); - else if (operation == OP_ARRAY_UINT16) - *valPtr = (int16) READ_VARO_UINT16(varPos + temp * 2 + offset * 2); - else if (operation == OP_ARRAY_STR) { - *valPtr = encodePtr(_vm->_inter->_variables->getAddressOff8( - varPos + temp * 4 + offset * _vm->_global->_inter_animDataSize * 4), - kInterVar); - if (*_vm->_global->_inter_execPtr == 13) { - _vm->_global->_inter_execPtr++; - temp2 = parseValExpr(OP_END_MARKER); - *operPtr = OP_LOAD_IMM_INT16; - *valPtr = READ_VARO_UINT8(varPos + temp * 4 + - offset * 4 * _vm->_global->_inter_animDataSize + temp2); - } - } - break; - - case OP_LOAD_VAR_INT16: - *operPtr = OP_LOAD_IMM_INT16; - *valPtr = (int16) READ_VARO_UINT16(varPos + _vm->_inter->load16() * 2); - break; - - case OP_LOAD_VAR_INT8: - *operPtr = OP_LOAD_IMM_INT16; - *valPtr = (int8) READ_VARO_UINT8(varPos + _vm->_inter->load16()); - break; - - case OP_LOAD_IMM_INT32: - *operPtr = OP_LOAD_IMM_INT16; - *valPtr = READ_LE_UINT32(varPos + _vm->_global->_inter_execPtr); - _vm->_global->_inter_execPtr += 4; - break; - - case OP_LOAD_IMM_INT16: - *operPtr = OP_LOAD_IMM_INT16; - *valPtr = _vm->_inter->load16(); - break; - - case OP_LOAD_IMM_INT8: - *operPtr = OP_LOAD_IMM_INT16; - *valPtr = (int8) *_vm->_global->_inter_execPtr++; - break; - - case OP_LOAD_IMM_STR: - *operPtr = OP_LOAD_IMM_STR; - *valPtr = encodePtr(_vm->_global->_inter_execPtr, kExecPtr); - _vm->_global->_inter_execPtr += - strlen((char *) _vm->_global->_inter_execPtr) + 1; - break; - - case 23: - *operPtr = OP_LOAD_IMM_INT16; - *valPtr = READ_VARO_UINT32(varPos + _vm->_inter->load16() * 4); - break; - - case 24: - *operPtr = OP_LOAD_IMM_INT16; - *valPtr = (int16) READ_VARO_UINT16(varPos + _vm->_inter->load16() * 4); - break; - - case OP_LOAD_VAR_STR: - *operPtr = OP_LOAD_IMM_STR; - temp = _vm->_inter->load16() * 4; - *valPtr = encodePtr(_vm->_inter->_variables->getAddressOff8(varPos + temp), kInterVar); - if (*_vm->_global->_inter_execPtr == 13) { - _vm->_global->_inter_execPtr++; - temp += parseValExpr(OP_END_MARKER); - *operPtr = OP_LOAD_IMM_INT16; - *valPtr = READ_VARO_UINT8(varPos + temp); - } - break; - - case OP_FUNC: - operation = *_vm->_global->_inter_execPtr++; - parseExpr(OP_END_EXPR, 0); - - switch (operation) { - case FUNC_SQRT1: - case FUNC_SQRT2: - case FUNC_SQRT3: - curVal = 1; - prevVal = 1; - - do { - prevPrevVal = prevVal; - prevVal = curVal; - curVal = (curVal + _vm->_global->_inter_resVal / curVal) / 2; - } while ((curVal != prevVal) && (curVal != prevPrevVal)); - _vm->_global->_inter_resVal = curVal; - break; - - case FUNC_SQR: - _vm->_global->_inter_resVal = - _vm->_global->_inter_resVal * _vm->_global->_inter_resVal; - break; - - case FUNC_ABS: - if (_vm->_global->_inter_resVal < 0) - _vm->_global->_inter_resVal = -_vm->_global->_inter_resVal; - break; - - case FUNC_RAND: - _vm->_global->_inter_resVal = - _vm->_util->getRandom(_vm->_global->_inter_resVal); - break; - } - - *operPtr = OP_LOAD_IMM_INT16; - *valPtr = _vm->_global->_inter_resVal; - break; - } - - if ((stkPos > 0) && ((operPtr[-1] == OP_NEG) || (operPtr[-1] == OP_NOT))) { - stkPos--; - operPtr--; - valPtr--; - - if (*operPtr == OP_NEG) { - *operPtr = OP_LOAD_IMM_INT16; - valPtr[0] = -valPtr[1]; - } else - *operPtr = (operPtr[1] == GOB_FALSE) ? GOB_TRUE : GOB_FALSE; - } - - if (stkPos <= 0) { - varPos = 0; - continue; - } - - switch (operPtr[-1]) { - case OP_ADD: - if (operPtr[-2] == OP_LOAD_IMM_STR) { - if ((char *) decodePtr(valPtr[-2]) != _vm->_global->_inter_resStr) { - strcpy(_vm->_global->_inter_resStr, (char *) decodePtr(valPtr[-2])); - valPtr[-2] = encodePtr((byte *) _vm->_global->_inter_resStr, kResStr); - } - strcat(_vm->_global->_inter_resStr, (char *) decodePtr(valPtr[0])); - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - } - break; - - case OP_MUL: - valPtr[-2] *= valPtr[0]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_DIV: - valPtr[-2] /= valPtr[0]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_MOD: - valPtr[-2] %= valPtr[0]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_BITAND: - valPtr[-2] &= valPtr[0]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - } - varPos = 0; - continue; - } // (op >= OP_ARRAY_UINT8) && (op <= OP_FUNC) - - if ((operation == stopToken) || (operation == OP_OR) || - (operation == OP_AND) || (operation == OP_END_EXPR)) { - while (stkPos >= 2) { - var_1A = false; - if ((operPtr[-2] == OP_BEGIN_EXPR) && - ((operation == OP_END_EXPR) || (operation == stopToken))) { - operPtr[-2] = operPtr[-1]; - if ((operPtr[-2] == OP_LOAD_IMM_INT16) || (operPtr[-2] == OP_LOAD_IMM_STR)) - valPtr[-2] = valPtr[-1]; - - stkPos--; - operPtr--; - valPtr--; - - if (stkPos > 1) { - if (operPtr[-2] == OP_NEG) { - operPtr[-2] = OP_LOAD_IMM_INT16; - valPtr[-2] = -valPtr[-1]; - stkPos--; - operPtr--; - valPtr--; - } else if (operPtr[-2] == OP_NOT) { - operPtr[-2] = (operPtr[-1] == GOB_FALSE) ? GOB_TRUE : GOB_FALSE; - stkPos--; - operPtr--; - valPtr--; - } - } // stkPos > 1 - - if (stkPos > 2) { - switch (operPtr[-2]) { - case OP_MUL: - valPtr[-3] *= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_DIV: - valPtr[-3] /= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_MOD: - valPtr[-3] %= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_BITAND: - valPtr[-3] &= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - } // switch - } // stkPos > 2 - - if (operation != stopToken) - break; - } // if ((operPtr[-2] == OP_BEGIN_EXPR) && ...) - - for (brackStart = (stkPos - 2); (brackStart > 0) && - (operStack[brackStart] < OP_OR) && (operStack[brackStart] != OP_BEGIN_EXPR); - brackStart--) - ; - - if ((operStack[brackStart] >= OP_OR) || (operStack[brackStart] == OP_BEGIN_EXPR)) - brackStart++; - - switch (operPtr[-2]) { - case OP_ADD: - if (operStack[brackStart] == OP_LOAD_IMM_INT16) { - values[brackStart] += valPtr[-1]; - } else if (operStack[brackStart] == OP_LOAD_IMM_STR) { - if ((char *) decodePtr(values[brackStart]) != _vm->_global->_inter_resStr) { - strcpy(_vm->_global->_inter_resStr, (char *) decodePtr(values[brackStart])); - values[brackStart] = - encodePtr((byte *) _vm->_global->_inter_resStr, kResStr); - } - strcat(_vm->_global->_inter_resStr, (char *) decodePtr(valPtr[-1])); - } - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - continue; - - case OP_SUB: - values[brackStart] -= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - continue; - - case OP_BITOR: - values[brackStart] |= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - continue; - - case OP_MUL: - valPtr[-3] *= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_DIV: - valPtr[-3] /= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_MOD: - valPtr[-3] %= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_BITAND: - valPtr[-3] &= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_OR: - // (x OR false) == x - // (x OR true) == true - if (operPtr[-3] == GOB_FALSE) - operPtr[-3] = operPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_AND: - // (x AND false) == false - // (x AND true) == x - if (operPtr[-3] == GOB_TRUE) - operPtr[-3] = operPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_LESS: - operPtr[-3] = (cmpHelper(operPtr, valPtr) < 0) ? GOB_TRUE : GOB_FALSE; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_LEQ: - operPtr[-3] = (cmpHelper(operPtr, valPtr) <= 0) ? GOB_TRUE : GOB_FALSE; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_GREATER: - operPtr[-3] = (cmpHelper(operPtr, valPtr) > 0) ? GOB_TRUE : GOB_FALSE; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_GEQ: - operPtr[-3] = (cmpHelper(operPtr, valPtr) >= 0) ? GOB_TRUE : GOB_FALSE; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_EQ: - operPtr[-3] = (cmpHelper(operPtr, valPtr) == 0) ? GOB_TRUE : GOB_FALSE; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_NEQ: { - int cmpTemp = 0; - - if (operPtr[-3] == OP_LOAD_IMM_INT16) { - cmpTemp = valPtr[-3] - valPtr[-1]; - } else if (operPtr[-3] == OP_LOAD_IMM_STR) { - if ((char *) decodePtr(valPtr[-3]) != _vm->_global->_inter_resStr) { - strcpy(_vm->_global->_inter_resStr, (char *) decodePtr(valPtr[-3])); - valPtr[-3] = encodePtr((byte *) _vm->_global->_inter_resStr, kResStr); - } - // FIXME: Why scumm_stricmp here and strcmp everywhere else? - cmpTemp = scumm_stricmp(_vm->_global->_inter_resStr, (char *) decodePtr(valPtr[-1])); - } - operPtr[-3] = (cmpTemp != 0) ? GOB_TRUE : GOB_FALSE; - //operPtr[-3] = (cmpHelper(operPtr, valPtr) != 0) ? GOB_TRUE : GOB_FALSE; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - } - - default: - var_1A = true; - break; - } // switch - - if (var_1A) - break; - } // while (stkPos >= 2) - - if ((operation == OP_OR) || (operation == OP_AND)) { - if (operPtr[-1] == OP_LOAD_IMM_INT16) { - if (valPtr[-1] != 0) - operPtr[-1] = GOB_TRUE; - else - operPtr[-1] = GOB_FALSE; - } - - if (((operation == OP_OR) && (operPtr[-1] == GOB_TRUE)) || - ((operation == OP_AND) && (operPtr[-1] == GOB_FALSE))) { - if ((stkPos > 1) && (operPtr[-2] == OP_BEGIN_EXPR)) { - skipExpr(OP_END_EXPR); - operPtr[-2] = operPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - } else { - skipExpr(stopToken); - } - operation = _vm->_global->_inter_execPtr[-1]; - if ((stkPos > 0) && (operPtr[-1] == OP_NOT)) { - if (operPtr[0] == GOB_FALSE) - operPtr[-1] = GOB_TRUE; - else - operPtr[-1] = GOB_FALSE; - - stkPos--; - operPtr--; - valPtr--; - } - } else - operPtr[0] = operation; - } else { - stkPos--; - operPtr--; - valPtr--; - } - - if (operation != stopToken) - continue; - - if (arg_2 != 0) - *arg_2 = operStack[0]; - - switch (operStack[0]) { - case OP_NOT: - if (arg_2 != 0) - *arg_2 ^= 1; - break; - - case OP_LOAD_IMM_INT16: - _vm->_global->_inter_resVal = values[0]; - break; - - case OP_LOAD_IMM_STR: - if ((char *) decodePtr(values[0]) != _vm->_global->_inter_resStr) - strcpy(_vm->_global->_inter_resStr, (char *) decodePtr(values[0])); - break; - - case 23: - case 24: - break; - - default: - _vm->_global->_inter_resVal = 0; - if (arg_2 != 0) - *arg_2 = OP_LOAD_IMM_INT16; - break; - } - return 0; - } // (operation == stopToken) || (operation == OP_OR) || (operation == OP_AND) || (operation == OP_END_EXPR) - - if ((operation < OP_NEG) || (operation > OP_NOT)) { - if ((operation < OP_LESS) || (operation > OP_NEQ)) - continue; - - if (stkPos > 2) { - if (operPtr[-2] == OP_ADD) { - if (operPtr[-3] == OP_LOAD_IMM_INT16) { - valPtr[-3] += valPtr[-1]; - } else if (operPtr[-3] == OP_LOAD_IMM_STR) { - if ((char *) decodePtr(valPtr[-3]) != _vm->_global->_inter_resStr) { - strcpy(_vm->_global->_inter_resStr, (char *) decodePtr(valPtr[-3])); - valPtr[-3] = encodePtr((byte *) _vm->_global->_inter_resStr, kResStr); - } - strcat(_vm->_global->_inter_resStr, (char *) decodePtr(valPtr[-1])); - } - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - - } else if (operPtr[-2] == OP_SUB) { - valPtr[-3] -= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - } else if (operPtr[-2] == OP_BITOR) { - valPtr[-3] |= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - } - } - } - *operPtr = operation; - } -} - -} // End of namespace Gob diff --git a/engines/gob/parse.h b/engines/gob/parse.h deleted file mode 100644 index 01f5762b6d..0000000000 --- a/engines/gob/parse.h +++ /dev/null @@ -1,128 +0,0 @@ -/* 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. - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#ifndef GOB_PARSE_H -#define GOB_PARSE_H - -namespace Gob { - -enum { - OP_NEG = 1, - OP_ADD = 2, - OP_SUB = 3, - OP_BITOR = 4, - OP_MUL = 5, - OP_DIV = 6, - OP_MOD = 7, - OP_BITAND = 8, - OP_BEGIN_EXPR = 9, - OP_END_EXPR = 10, - OP_NOT = 11, - - OP_END_MARKER = 12, // Marks end of an array or string - - - OP_ARRAY_UINT8 = 16, - - OP_LOAD_VAR_INT16 = 17, - OP_LOAD_VAR_INT8 = 18, - OP_LOAD_IMM_INT32 = 19, - OP_LOAD_IMM_INT16 = 20, - OP_LOAD_IMM_INT8 = 21, - OP_LOAD_IMM_STR = 22, - - OP_LOAD_VAR_UINT32 = 23, // ??? - OP_LOAD_VAR_UINT32_AS_UINT16 = 24, // ??? - OP_LOAD_VAR_STR = 25, - - OP_ARRAY_UINT32 = 26, - OP_ARRAY_UINT16 = 27, - OP_ARRAY_STR = 28, - - OP_FUNC = 29, - - OP_OR = 30, // Logical OR - OP_AND = 31, // Logical AND - OP_LESS = 32, - OP_LEQ = 33, - OP_GREATER = 34, - OP_GEQ = 35, - OP_EQ = 36, - OP_NEQ = 37 -}; - -enum { - FUNC_SQRT1 = 0, - FUNC_SQRT2 = 1, - FUNC_SQRT3 = 6, - - FUNC_SQR = 5, - FUNC_ABS = 7, - FUNC_RAND = 10 -}; - -enum { - // FIXME: The following two 'truth values' are stored inside the list - // of "operators". So they somehow coincide with OP_LOAD_VAR_UINT32 - // and OP_LOAD_VAR_UINT32_AS_UINT16. I haven't yet quite understood - // how, resp. what that means. You have been warned. - GOB_TRUE = 24, - GOB_FALSE = 23 -}; - -class Parse { -public: - void skipExpr(char stopToken); - void printExpr(char stopToken); - void printVarIndex(void); - - int16 parseVarIndex(uint16 *arg_0 = 0, uint16 *arg_4 = 0); - int16 parseValExpr(byte stopToken = 99); - int16 parseExpr(byte stopToken, byte *resultPtr); - - Parse(GobEngine *vm); - virtual ~Parse() {} - -private: - enum PointerType { - kExecPtr = 0, - kInterVar = 1, - kResStr = 2 - }; - - GobEngine *_vm; - - int32 encodePtr(byte *ptr, int type); - byte *decodePtr(int32 n); - - void printExpr_internal(char stopToken); - - int16 getOffset(int16 arg_0, byte arg_2, uint32 arg_3, uint16 arg_7, uint16 arg_9); - int cmpHelper(byte *operPtr, int32 *valPtr); -}; - -} // End of namespace Gob - -#endif // GOB_PARSE_H diff --git a/engines/gob/resources.cpp b/engines/gob/resources.cpp new file mode 100644 index 0000000000..20427e547b --- /dev/null +++ b/engines/gob/resources.cpp @@ -0,0 +1,706 @@ +/* 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. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "common/util.h" +#include "common/endian.h" +#include "common/stream.h" + +#include "gob/gob.h" +#include "gob/resources.h" +#include "gob/totfile.h" +#include "gob/dataio.h" +#include "gob/game.h" +#include "gob/global.h" + +namespace Gob { + +Resource::Resource(byte *data, int32 size, bool needFree, + int16 width, int16 height) { + + _data = data; + _size = size; + _width = width; + _height = height; + _needFree = needFree; + + _stream = new Common::MemoryReadStream(data, size); +} + +Resource::~Resource() { + delete _stream; + + if (_needFree) + delete[] _data; +} + +byte *Resource::getData() const { + return _data; +} + +int32 Resource::getSize() const { + return _size; +} + +int16 Resource::getWidth() const { + return _width; +} + +int16 Resource::getHeight() const { + return _height; +} + +Common::MemoryReadStream *Resource::stream() const { + return _stream; +} + + +TextItem::TextItem(byte *data, int32 size) { + _data = data; + _size = size; + + _stream = new Common::MemoryReadStream(data, size); +} + +TextItem::~TextItem() { + delete _stream; +} + +byte *TextItem::getData() const { + return _data; +} + +int32 TextItem::getSize() const { + return _size; +} + +Common::MemoryReadStream *TextItem::stream() const { + return _stream; +} + + +Resources::TOTResourceTable::TOTResourceTable() { + items = 0; +} + +Resources::TOTResourceTable::~TOTResourceTable() { + delete[] items; +} + + +Resources::EXTResourceTable::EXTResourceTable() { + itemsCount = 0; + unknown = 0; + items = 0; +} + +Resources::EXTResourceTable::~EXTResourceTable() { + delete[] items; +} + + +Resources::TOTTextTable::TOTTextTable() { + items = 0; + data = 0; + needFree = false; +} + +Resources::TOTTextTable::~TOTTextTable() { + delete[] items; + if (needFree) + delete[] data; +} + + +Resources::Resources(GobEngine *vm) : _vm(vm) { + unload(false); +} + +Resources::~Resources() { + unload(); +} + +bool Resources::load(const Common::String &fileName) { + unload(); + + Common::String fileBase; + + _totFile = TOTFile::createFileName(fileName, _hasLOM); + + if (_hasLOM) { + warning("Stub: Resources::load(%s)", fileName.c_str()); + unload(); + return false; + } + + fileBase = TOTFile::getFileBase(fileName); + + _extFile = fileBase + ".ext"; + + if (!loadTOTResourceTable()) { + unload(); + return false; + } + + if (!loadEXTResourceTable()) { + unload(); + return false; + } + + if (!loadTOTTextTable(fileBase)) { + unload(); + return false; + } + + if (!loadIMFile()) { + unload(); + return false; + } + + if (!loadEXFile()) { + unload(); + return false; + } + + return true; +} + +void Resources::unload(bool del) { + if (del) { + delete _totResourceTable; + delete _extResourceTable; + delete _totTextTable; + + delete[] _totData; + delete[] _imData; + + _totFile.clear(); + _extFile.clear(); + _exFile.clear(); + } + + _totResourceTable = 0; + _extResourceTable = 0; + _totTextTable = 0; + _totData = 0; + _totSize = 0; + _imData = 0; + _imSize = 0; +} + +bool Resources::isLoaded() const { + return (_totResourceTable != 0); +} + +bool Resources::loadTOTResourceTable() { + TOTFile totFile(_vm); + + if (!totFile.load(_totFile)) + return false; + + TOTFile::Properties totProps; + if (!totFile.getProperties(totProps)) + return false; + + Common::SeekableReadStream *stream = totFile.getStream(); + if (!stream) + return false; + + if ((totProps.resourcesOffset == 0xFFFFFFFF) || + (totProps.resourcesOffset == 0)) + // No resources here + return false; + + _totResourceTable = new TOTResourceTable; + + stream->seek(totProps.resourcesOffset); + _totResourceTable->itemsCount = stream->readSint16LE(); + + _totResourceTable->dataOffset = totProps.resourcesOffset + kTOTResTableSize + + _totResourceTable->itemsCount * kTOTResItemSize; + + + uint32 resSize = _totResourceTable->itemsCount * kTOTResItemSize + + kTOTResTableSize; + + // Would the table actually fit into the TOT? + if ((totProps.resourcesOffset + resSize) > ((uint32) stream->size())) + return false; + + _totResourceTable->unknown = stream->readByte(); + _totResourceTable->items = new TOTResourceItem[_totResourceTable->itemsCount]; + + for (int i = 0; i < _totResourceTable->itemsCount; ++i) { + TOTResourceItem &item = _totResourceTable->items[i]; + + item.offset = stream->readSint32LE(); + item.size = stream->readSint16LE(); + item.width = stream->readSint16LE(); + item.height = stream->readSint16LE(); + + if (item.offset < 0) { + item.type = kResourceIM; + item.index = -item.offset - 1; + } else + item.type = kResourceTOT; + } + + _totResStart = totProps.scriptEnd; + _totSize = stream->size() - _totResStart; + if (_totSize <= 0) + return false; + + if (!stream->seek(totProps.scriptEnd)) + return false; + + _totData = new byte[_totSize]; + if (stream->read(_totData, _totSize) != _totSize) + return false; + + return !stream->err(); +} + +bool Resources::loadEXTResourceTable() { + _extResourceTable = new EXTResourceTable; + + DataStream *stream = _vm->_dataIO->getDataStream(_extFile.c_str()); + if (!stream) + return true; + + _extResourceTable->itemsCount = stream->readSint16LE(); + _extResourceTable->unknown = stream->readByte(); + + if (_extResourceTable->itemsCount > 0) + _extResourceTable->items = new EXTResourceItem[_extResourceTable->itemsCount]; + + for (int i = 0; i < _extResourceTable->itemsCount; i++) { + EXTResourceItem &item = _extResourceTable->items[i]; + + item.offset = stream->readUint32LE(); + item.size = stream->readUint16LE(); + item.width = stream->readUint16LE(); + item.height = stream->readUint16LE(); + + if (item.offset < 0) { + item.type = kResourceEX; + item.offset = -item.offset - 1; + } else { + item.type = kResourceEXT; + item.offset += kEXTResTableSize + + kEXTResItemSize * _extResourceTable->itemsCount; + } + + item.packed = (item.width & 0x8000) != 0; + + item.width &= 0x7FFF; + } + + delete stream; + return true; +} + +bool Resources::loadTOTTextTable(const Common::String &fileBase) { + TOTFile totFile(_vm); + + if (!totFile.load(_totFile)) + return false; + + TOTFile::Properties totProps; + if (!totFile.getProperties(totProps)) + return false; + + Common::SeekableReadStream *stream = totFile.getStream(); + if (!stream) + return false; + + if (totProps.textsOffset == ((uint32) -1)) + // No texts + return true; + + _totTextTable = new TOTTextTable; + + bool fromTOT; + if (totProps.textsOffset == 0) { + fromTOT = false; + _totTextTable->data = loadTOTLocTexts(fileBase, _totTextTable->size); + _totTextTable->needFree = true; + } else { + fromTOT = true; + _totTextTable->data = _totData + totProps.textsOffset - _totResStart; + _totTextTable->needFree = false; + _totTextTable->size = _totSize - totProps.textsOffset; + } + + if (_totTextTable->data) { + Common::MemoryReadStream totTextTable(_totTextTable->data, _totTextTable->size); + _totTextTable->itemsCount = totTextTable.readSint16LE() & 0x3FFF; + + _totTextTable->items = new TOTTextItem[_totTextTable->itemsCount]; + for (int i = 0; i < _totTextTable->itemsCount; ++i) { + TOTTextItem &item = _totTextTable->items[i]; + + item.offset = totTextTable.readSint16LE(); + item.size = totTextTable.readSint16LE(); + + if (fromTOT) + item.offset -= (totProps.textsOffset - _totResStart); + } + } + + return true; +} + +bool Resources::loadIMFile() { + TOTFile totFile(_vm); + + if (!totFile.load(_totFile)) + return false; + + TOTFile::Properties totProps; + if (!totFile.getProperties(totProps)) + return false; + + if ((totProps.communHandling != 0) && (totProps.imFileNumber == 0)) + // No IM file + return true; + + Common::String imFile = "commun.im"; + + char num = totProps.imFileNumber + '0'; + if (num == '0') + num = '1'; + + imFile += num; + + DataStream *stream = _vm->_dataIO->getDataStream(imFile.c_str()); + if (!stream) + return true; + + _imSize = stream->size(); + if (_imSize <= 0) { + _imSize = 0; + delete stream; + return true; + } + + _imData = new byte[_imSize]; + if (stream->read(_imData, _imSize) != _imSize) { + delete[] _imData; + _imData = 0; + _imSize = 0; + } + + delete stream; + return true; +} + +bool Resources::loadEXFile() { + TOTFile totFile(_vm); + + if (!totFile.load(_totFile)) + return false; + + TOTFile::Properties totProps; + if (!totFile.getProperties(totProps)) + return false; + + _exFile = "commun.ex"; + _exFile += totProps.exFileNumber + '0'; + + if (!_vm->_dataIO->existData(_exFile.c_str())) { + _exFile.clear(); + return true; + } + + return true; +} + +Common::String Resources::getLocTextFile(const Common::String &fileBase, + int language) { + + Common::String locTextFile = fileBase + "."; + switch (language) { + case kLanguageFrench: + locTextFile += "dat"; + break; + case kLanguageGerman: + locTextFile += "all"; + break; + case kLanguageSpanish: + locTextFile += "esp"; + break; + case kLanguageItalian: + locTextFile += "ita"; + break; + case kLanguageAmerican: + locTextFile += "usa"; + break; + case kLanguageDutch: + locTextFile += "ndl"; + break; + case kLanguageKorean: + locTextFile += "kor"; + break; + case kLanguageHebrew: + locTextFile += "isr"; + break; + default: + locTextFile += "ang"; + break; + } + + if (!_vm->_dataIO->existData(locTextFile.c_str())) + locTextFile.clear(); + + return locTextFile; +} + +byte *Resources::loadTOTLocTexts(const Common::String &fileBase, int32 &size) { + Common::String locTextFile; + + locTextFile = getLocTextFile(fileBase, _vm->_global->_languageWanted); + + if (!locTextFile.empty()) { + + _vm->_global->_foundLanguage = true; + _vm->_global->_language = _vm->_global->_languageWanted; + + } else if (!_vm->_global->_foundLanguage) { + + // Trying US for GB and vice versa + if (_vm->_global->_languageWanted == kLanguageBritish) { + + locTextFile = getLocTextFile(fileBase, kLanguageAmerican); + if (!locTextFile.empty()) + _vm->_global->_language = kLanguageAmerican; + + } else if (_vm->_global->_languageWanted == kLanguageAmerican) { + + locTextFile = getLocTextFile(fileBase, kLanguageBritish); + if (!locTextFile.empty()) + _vm->_global->_language = kLanguageBritish; + + } + + if (locTextFile.empty()) { + // Looking for the first existing language + for (int i = 0; i < 10; i++) { + locTextFile = getLocTextFile(fileBase, i); + if (!locTextFile.empty()) { + _vm->_global->_language = i; + break; + } + } + } + + } + + debugC(1, kDebugFileIO, "Using language %d for %s", + _vm->_global->_language, _totFile.c_str()); + + if (locTextFile.empty()) + return 0; + + size = _vm->_dataIO->getDataSize(locTextFile.c_str()); + return _vm->_dataIO->getData(locTextFile.c_str()); +} + +Resource *Resources::getResource(uint16 id, int16 *width, int16 *height) const { + if (_hasLOM) { + warning("Stub: Resources::getResource(): Has LOM"); + return 0; + } + + Resource *resource = 0; + if (id >= 30000) + resource = getEXTResource(id - 30000); + else + resource = getTOTResource(id); + + if (!resource) + return 0; + + if (width) + *width = resource->getWidth(); + if (height) + *height = resource->getHeight(); + + return resource; +} + +TextItem *Resources::getTextItem(uint16 id) const { + if (!_totTextTable || !_totTextTable->data) + return 0; + + if (id >= _totTextTable->itemsCount) + return 0; + + TOTTextItem &totItem = _totTextTable->items[id]; + + if ((totItem.offset == 0xFFFF) || (totItem.size == 0)) + return 0; + if ((totItem.offset + totItem.size) > (_totTextTable->size)) + return 0; + + return new TextItem(_totTextTable->data + totItem.offset, totItem.size); +} + +byte *Resources::getTexts() const { + if (!_totTextTable) + return 0; + + return _totTextTable->data; +} + +Resource *Resources::getTOTResource(uint16 id) const { + if (id >= _totResourceTable->itemsCount) { + warning("Trying to load non-existent TOT resource (%s, %d/%d)", + _totFile.c_str(), id, _totResourceTable->itemsCount - 1); + return 0; + } + + TOTResourceItem &totItem = _totResourceTable->items[id]; + + byte *data = 0; + if (totItem.type == kResourceIM) + data = getIMData(totItem); + if (totItem.type == kResourceTOT) + data = getTOTData(totItem); + + if (!data) + return 0; + + return new Resource(data, totItem.size, false, totItem.width, totItem.height); +} + +Resource *Resources::getEXTResource(uint16 id) const { + if (!_extResourceTable || (id > _extResourceTable->itemsCount)) + return 0; + + EXTResourceItem &extItem = _extResourceTable->items[id]; + + uint32 size = extItem.size; + + if (extItem.width & 0x4000) + size += 1 << 16; + if (extItem.width & 0x2000) + size += 2 << 16; + if (extItem.width & 0x1000) + size += 4 << 16; + if (extItem.height == 0) + size += extItem.width << 16; + + byte *data = 0; + if (extItem.type == kResourceEXT) + data = getEXTData(extItem, size); + if (extItem.type == kResourceEX) + data = getEXData(extItem, size); + + if (!data) + return 0; + + if (extItem.packed) { + byte *packedData = data; + + size = READ_LE_UINT32(packedData); + data = new byte[size]; + + _vm->_dataIO->unpackData(packedData, data); + + delete[] packedData; + } + + return new Resource(data, size, true, extItem.width & 0xFFF, extItem.height); +} + +byte *Resources::getTOTData(TOTResourceItem &totItem) const { + if (totItem.size < 0) + return 0; + + int32 offset = _totResourceTable->dataOffset + totItem.offset - _totResStart; + + if ((offset < 0) || (((uint32) (offset + totItem.size)) > _totSize)) + return 0; + + return _totData + offset; +} + +byte *Resources::getIMData(TOTResourceItem &totItem) const { + if (totItem.size < 0) + return 0; + + int32 indexOffset = totItem.index * 4; + if ((indexOffset < 0) || (((uint32) indexOffset) >= _imSize)) + return 0; + + uint32 offset = READ_LE_UINT32(_imData + indexOffset); + if ((offset + totItem.size) > _imSize) + return 0; + + return _imData + offset; +} + +byte *Resources::getEXTData(EXTResourceItem &extItem, uint32 size) const { + DataStream *stream = _vm->_dataIO->getDataStream(_extFile.c_str()); + if (!stream) + return 0; + + if (!stream->seek(extItem.offset)) { + delete stream; + return 0; + } + + byte *data = new byte[extItem.packed ? (size + 2) : size]; + if (stream->read(data, size) != size) { + delete[] data; + delete stream; + return 0; + } + + delete stream; + return data; +} + +byte *Resources::getEXData(EXTResourceItem &extItem, uint32 size) const { + DataStream *stream = _vm->_dataIO->getDataStream(_exFile.c_str()); + if (!stream) + return 0; + + if (!stream->seek(extItem.offset)) { + delete stream; + return 0; + } + + byte *data = new byte[extItem.packed ? (size + 2) : size]; + if (stream->read(data, size) != size) { + delete[] data; + delete stream; + return 0; + } + + delete stream; + return data; +} + +} // End of namespace Gob diff --git a/engines/gob/resources.h b/engines/gob/resources.h new file mode 100644 index 0000000000..80acef645c --- /dev/null +++ b/engines/gob/resources.h @@ -0,0 +1,207 @@ +/* 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. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef GOB_RESOURCES_H +#define GOB_RESOURCES_H + +#include "common/str.h" + +namespace Common { + class MemoryReadStream; +} + +namespace Gob { + +class GobEngine; + +class Resource { +public: + Resource(byte *data, int32 size, bool needFree = true, + int16 width = 0, int16 height = 0); + ~Resource(); + + byte *getData () const; + int32 getSize () const; + int16 getWidth () const; + int16 getHeight() const; + + Common::MemoryReadStream *stream() const; + +private: + byte *_data; + int32 _size; + int16 _width; + int16 _height; + bool _needFree; + + Common::MemoryReadStream *_stream; +}; + +class TextItem { +public: + TextItem(byte *data, int32 size); + ~TextItem(); + + byte *getData() const; + int32 getSize() const; + + Common::MemoryReadStream *stream() const; + +private: + byte *_data; + int32 _size; + + Common::MemoryReadStream *_stream; +}; + +class Resources { +public: + Resources(GobEngine *vm); + ~Resources(); + + bool load(const Common::String &fileName); + void unload(bool del = true); + + bool isLoaded() const; + + Resource *getResource(uint16 id, int16 *width = 0, int16 *height = 0) const; + TextItem *getTextItem(uint16 id) const; + + byte *getTexts() const; + +private: + // Structure sizes in the files + static const int kTOTResItemSize = 4 + 2 + 2 + 2; + static const int kTOTResTableSize = 2 + 1; + static const int kEXTResItemSize = 4 + 2 + 2 + 2; + static const int kEXTResTableSize = 2 + 1; + static const int kTOTTextTableSize = 2; + static const int kTOTTextItemSize = 2 + 2; + + enum ResourceType { + kResourceTOT, + kResourceIM, + kResourceEXT, + kResourceEX + }; + + struct TOTResourceItem { + ResourceType type; + int16 size; + int16 width; + int16 height; + union { + int32 offset; + int32 index; + }; + }; + + struct TOTResourceTable { + int16 itemsCount; + byte unknown; + TOTResourceItem *items; + uint32 dataOffset; + + TOTResourceTable(); + ~TOTResourceTable(); + }; + + struct EXTResourceItem { + ResourceType type; + int32 offset; + uint16 size; + int16 width; + int16 height; + bool packed; + }; + + struct EXTResourceTable { + int16 itemsCount; + byte unknown; + EXTResourceItem *items; + + EXTResourceTable(); + ~EXTResourceTable(); + }; + + struct TOTTextItem { + uint16 offset; + int16 size; + }; + + struct TOTTextTable { + bool needFree; + int16 itemsCount; + + byte *data; + int32 size; + + TOTTextItem *items; + + TOTTextTable(); + ~TOTTextTable(); + }; + + GobEngine *_vm; + + Common::String _totFile; + Common::String _extFile; + Common::String _exFile; + + byte *_totData; + uint32 _totSize; + + byte *_imData; + uint32 _imSize; + + bool _hasLOM; + int32 _totResStart; + + TOTResourceTable *_totResourceTable; + EXTResourceTable *_extResourceTable; + TOTTextTable *_totTextTable; + + bool loadTOTResourceTable(); + bool loadEXTResourceTable(); + bool loadTOTTextTable(const Common::String &fileBase); + bool loadIMFile(); + bool loadEXFile(); + + byte *loadTOTLocTexts(const Common::String &fileBase, int32 &size); + bool getLocTextFile(char *locTextFile, int language); + Common::String getLocTextFile(const Common::String &fileBase, int language); + + Resource *getTOTResource(uint16 id) const; + Resource *getEXTResource(uint16 id) const; + + byte *getTOTData(TOTResourceItem &totItem) const; + byte *getIMData(TOTResourceItem &totItem) const; + byte *getEXTData(EXTResourceItem &extItem, uint32 size) const; + byte *getEXData(EXTResourceItem &extItem, uint32 size) const; +}; + +} // End of namespace Gob + +#endif // GOB_RESOURCES_H diff --git a/engines/gob/save/savefile.h b/engines/gob/save/savefile.h index 989a37277e..615be8e0f2 100644 --- a/engines/gob/save/savefile.h +++ b/engines/gob/save/savefile.h @@ -163,7 +163,7 @@ public: bool readPalette(const byte *palette); /** Read a sprite into the part. */ bool readSprite(const SurfaceDesc &sprite); - + /** Read size bytes of raw data into the sprite. */ bool readSpriteRaw(const byte *data, uint32 size); diff --git a/engines/gob/save/saveload.cpp b/engines/gob/save/saveload.cpp index abda2f8a65..81239f07dc 100644 --- a/engines/gob/save/saveload.cpp +++ b/engines/gob/save/saveload.cpp @@ -61,7 +61,7 @@ int32 SaveLoad::getSize(const char *fileName) { int32 size = handler->getSize(); debugC(4, kDebugSaveLoad, "Size is %d", size); - + return size; } diff --git a/engines/gob/save/saveload_v3.cpp b/engines/gob/save/saveload_v3.cpp index 2f89644ee0..58232e6991 100644 --- a/engines/gob/save/saveload_v3.cpp +++ b/engines/gob/save/saveload_v3.cpp @@ -302,7 +302,7 @@ bool SaveLoad_v3::GameHandler::createReader(int slot) { if (!_reader || (_reader->getSlot() != ((uint32) slot))) { Common::String slotFile = _slotFile->build(slot); - + if (slotFile.empty()) return false; @@ -319,7 +319,7 @@ bool SaveLoad_v3::GameHandler::createReader(int slot) { } else _reader = new SaveReader(_usesScreenshots ? 3 : 2, slot, slotFile); - + if (!_reader->load()) { delete _reader; _reader = 0; @@ -337,7 +337,7 @@ bool SaveLoad_v3::GameHandler::createWriter(int slot) { if (!_writer || (_writer->getSlot() != ((uint32) slot))) { Common::String slotFile = _slotFile->build(slot); - + if (slotFile.empty()) return false; @@ -495,7 +495,7 @@ SaveLoad_v3::SaveLoad_v3(GobEngine *vm, const char *targetName, ScreenshotType s _gameHandler = new GameHandler(vm, targetName, true); _screenshotHandler = new ScreenshotHandler(vm, _gameHandler, sShotType); } - + _tempSpriteHandler = new TempSpriteHandler(vm); _notesHandler = new NotesHandler(2560, vm, targetName); diff --git a/engines/gob/save/saveload_v4.cpp b/engines/gob/save/saveload_v4.cpp index 6e1d5208ff..06280af2a6 100644 --- a/engines/gob/save/saveload_v4.cpp +++ b/engines/gob/save/saveload_v4.cpp @@ -317,7 +317,7 @@ bool SaveLoad_v4::GameHandler::createReader(int slot) { if (!_reader || (_reader->getSlot() != ((uint32) slot))) { Common::String slotFile = _slotFile->build(slot); - + if (slotFile.empty()) return false; @@ -334,7 +334,7 @@ bool SaveLoad_v4::GameHandler::createReader(int slot) { } else _reader = new SaveReader(3, slot, slotFile); - + if (!_reader->load()) { delete _reader; _reader = 0; @@ -352,7 +352,7 @@ bool SaveLoad_v4::GameHandler::createWriter(int slot) { if (!_writer || (_writer->getSlot() != ((uint32) slot))) { Common::String slotFile = _slotFile->build(slot); - + if (slotFile.empty()) return false; diff --git a/engines/gob/scenery.cpp b/engines/gob/scenery.cpp index 71750509b4..7a4b8ad868 100644 --- a/engines/gob/scenery.cpp +++ b/engines/gob/scenery.cpp @@ -31,6 +31,8 @@ #include "gob/global.h" #include "gob/draw.h" #include "gob/game.h" +#include "gob/script.h" +#include "gob/resources.h" #include "gob/inter.h" #include "gob/map.h" #include "gob/videoplayer.h" @@ -39,33 +41,33 @@ namespace Gob { Scenery::Scenery(GobEngine *vm) : _vm(vm) { for (int i = 0; i < 20; i++) { - _spriteRefs[i] = 0; + _spriteRefs[i] = 0; _spriteResId[i] = 0; } for (int i = 0; i < 10; i++) { _staticPictCount[i] = 0; - _staticResId[i] = 0; - _animPictCount[i] = 0; - _animResId[i] = 0; + _staticResId[i] = 0; + _animPictCount[i] = 0; + _animResId[i] = 0; } - _curStatic = 0; + _curStatic = 0; _curStaticLayer = 0; - _toRedrawLeft = 0; - _toRedrawRight = 0; - _toRedrawTop = 0; + _toRedrawLeft = 0; + _toRedrawRight = 0; + _toRedrawTop = 0; _toRedrawBottom = 0; - _animTop = 0; + _animTop = 0; _animLeft = 0; _pCaptureCounter = 0; for (int i = 0; i < 70; i++ ) { _staticPictToSprite[i] = 0; - _animPictToSprite[i] = 0; + _animPictToSprite[i] = 0; } } @@ -78,17 +80,17 @@ Scenery::~Scenery() { void Scenery::init() { for (int i = 0; i < 10; i++) { - _animPictCount[i] = 0; + _animPictCount[i] = 0; _staticPictCount[i] = -1; } for (int i = 0; i < 20; i++) { - _spriteRefs[i] = 0; + _spriteRefs[i] = 0; _spriteResId[i] = -1; } _curStaticLayer = -1; - _curStatic = -1; + _curStatic = -1; } int16 Scenery::loadStatic(char search) { @@ -97,28 +99,26 @@ int16 Scenery::loadStatic(char search) { int16 picsCount; int16 resId; int16 sceneryIndex; - byte *extData = 0; - byte *dataPtr; Static *ptr; int16 width; int16 height; int16 sprResId; int16 sprIndex; - _vm->_inter->evalExpr(&sceneryIndex); + _vm->_game->_script->evalExpr(&sceneryIndex); - size = _vm->_inter->load16(); - backsPtr = (int16 *) _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += size * 2; - picsCount = _vm->_inter->load16(); - resId = _vm->_inter->load16(); + size = _vm->_game->_script->readInt16(); + backsPtr = (int16 *) (_vm->_game->_script->getData() + _vm->_game->_script->pos()); + _vm->_game->_script->skip(size * 2); + picsCount = _vm->_game->_script->readInt16(); + resId = _vm->_game->_script->readInt16(); if (search) { int i; for (i = 0; i < 10; i++) { if ((_staticPictCount[i] != -1) && (_staticResId[i] == resId)) { - _vm->_global->_inter_execPtr += 8 * _staticPictCount[i]; + _vm->_game->_script->skip(8 * _staticPictCount[i]); return i; } @@ -128,52 +128,54 @@ int16 Scenery::loadStatic(char search) { } _staticPictCount[sceneryIndex] = picsCount; - _staticResId[sceneryIndex] = resId; + _staticResId[sceneryIndex] = resId; - if (resId >= 30000) { - extData = _vm->_game->loadExtData(resId, 0, 0); - dataPtr = extData; - } else - dataPtr = _vm->_game->loadTotResource(resId); + Resource *resource = _vm->_game->_resources->getResource((uint16) resId); + if (!resource) + return 0; ptr = &_statics[sceneryIndex]; - ptr->layersCount = (int16) READ_LE_UINT16(dataPtr); - dataPtr += 2; + ptr->layersCount = resource->stream()->readSint16LE(); ptr->layers = new StaticLayer[ptr->layersCount]; for (int i = 0; i < ptr->layersCount; i++) { - int16 offset = READ_LE_UINT16(dataPtr + i * 2); - Common::MemoryReadStream layerData(dataPtr + offset, 4294967295U); + Common::SeekableReadStream &layerData = *resource->stream(); - ptr->layers[i].planeCount = layerData.readSint16LE(); + layerData.seek(2 + i * 2); + layerData.seek(layerData.readUint16LE()); - ptr->layers[i].planes = new StaticPlane[ptr->layers[i].planeCount]; - for (int j = 0; j < ptr->layers[i].planeCount; ++j) { - ptr->layers[i].planes[j].pictIndex = layerData.readByte(); - ptr->layers[i].planes[j].pieceIndex = layerData.readByte(); - ptr->layers[i].planes[j].drawOrder = layerData.readByte(); - ptr->layers[i].planes[j].destX = layerData.readSint16LE(); - ptr->layers[i].planes[j].destY = layerData.readSint16LE(); - ptr->layers[i].planes[j].transp = layerData.readSByte(); - } + ptr->layers[i].backResId = layerData.readSint16LE(); + ptr->layers[i].planeCount = layerData.readSint16LE(); + if (ptr->layers[i].planeCount > 0) { + ptr->layers[i].planes = new StaticPlane[ptr->layers[i].planeCount]; + for (int j = 0; j < ptr->layers[i].planeCount; j++) { + ptr->layers[i].planes[j].pictIndex = layerData.readByte(); + ptr->layers[i].planes[j].pieceIndex = layerData.readByte(); + ptr->layers[i].planes[j].drawOrder = layerData.readByte(); + ptr->layers[i].planes[j].destX = layerData.readSint16LE(); + ptr->layers[i].planes[j].destY = layerData.readSint16LE(); + ptr->layers[i].planes[j].transp = layerData.readSByte(); + } + } else + ptr->layers[i].planes = 0; ptr->layers[i].backResId = (int16) READ_LE_UINT16(backsPtr); backsPtr++; } - ptr->pieces = new PieceDesc*[picsCount]; + ptr->pieces = new PieceDesc*[picsCount]; ptr->piecesCount = new uint32[picsCount]; for (int i = 0; i < picsCount; i++) { - int16 pictDescId = _vm->_inter->load16(); + int16 pictDescId = _vm->_game->_script->readInt16(); loadPieces(pictDescId, ptr->pieces[i], ptr->piecesCount[i]); - width = _vm->_inter->load16(); - height = _vm->_inter->load16(); - sprResId = _vm->_inter->load16(); + width = _vm->_game->_script->readInt16(); + height = _vm->_game->_script->readInt16(); + sprResId = _vm->_game->_script->readInt16(); for (sprIndex = 0; sprIndex < 20; sprIndex++) { if (_spriteResId[sprIndex] == sprResId) break; @@ -183,9 +185,7 @@ int16 Scenery::loadStatic(char search) { _staticPictToSprite[7 * sceneryIndex + i] = sprIndex; _spriteRefs[sprIndex]++; } else { - for (sprIndex = 19; _vm->_draw->_spritesArray[sprIndex] != 0; - sprIndex--) - ; + for (sprIndex = 19; _vm->_draw->_spritesArray[sprIndex] != 0; sprIndex--); _staticPictToSprite[7 * sceneryIndex + i] = sprIndex; _spriteRefs[sprIndex] = 1; @@ -193,17 +193,16 @@ int16 Scenery::loadStatic(char search) { _vm->_draw->initSpriteSurf(sprIndex, width, height, 2); _vm->_video->clearSurf(*_vm->_draw->_spritesArray[sprIndex]); - _vm->_draw->_destSurface = sprIndex; - _vm->_draw->_spriteLeft = sprResId; + _vm->_draw->_destSurface = sprIndex; + _vm->_draw->_spriteLeft = sprResId; _vm->_draw->_transparency = 0; - _vm->_draw->_destSpriteX = 0; - _vm->_draw->_destSpriteY = 0; + _vm->_draw->_destSpriteX = 0; + _vm->_draw->_destSpriteY = 0; _vm->_draw->spriteOperation(DRAW_LOADSPRITE); } } - delete[] extData; - + delete resource; return sceneryIndex + 100; } @@ -211,7 +210,7 @@ void Scenery::freeStatic(int16 index) { int16 spr; if (index == -1) - _vm->_inter->evalExpr(&index); + _vm->_game->_script->evalExpr(&index); if (_staticPictCount[index] == -1) return; @@ -229,12 +228,13 @@ void Scenery::freeStatic(int16 index) { for (int i = 0; i < _statics[index].layersCount; i++) delete[] _statics[index].layers[i].planes; + delete[] _statics[index].layers; delete[] _statics[index].pieces; delete[] _statics[index].piecesCount; _statics[index].layersCount = 0; - _staticPictCount[index] = -1; + _staticPictCount[index] = -1; } void Scenery::renderStatic(int16 scenery, int16 layer) { @@ -261,22 +261,21 @@ void Scenery::renderStatic(int16 scenery, int16 layer) { _vm->_draw->_spriteLeft = layerPtr->backResId; if (_vm->_draw->_spriteLeft != -1) { - _vm->_draw->_destSpriteX = 0; - _vm->_draw->_destSpriteY = 0; - _vm->_draw->_destSurface = 21; - _vm->_draw->_transparency = 0; + _vm->_draw->_destSpriteX = 0; + _vm->_draw->_destSpriteY = 0; + _vm->_draw->_destSurface = 21; + _vm->_draw->_transparency = 0; _vm->_draw->spriteOperation(DRAW_LOADSPRITE); } planeCount = layerPtr->planeCount; for (order = 0; order < 100; order++) { - for (plane = 0, planePtr = layerPtr->planes; - plane < planeCount; plane++, planePtr++) { + for (plane = 0, planePtr = layerPtr->planes; plane < planeCount; plane++, planePtr++) { if (planePtr->drawOrder != order) continue; pieceIndex = planePtr->pieceIndex; - pictIndex = planePtr->pictIndex - 1; + pictIndex = planePtr->pictIndex - 1; if (pictIndex >= _staticPictCount[scenery]) continue; @@ -289,19 +288,19 @@ void Scenery::renderStatic(int16 scenery, int16 layer) { _vm->_draw->_destSpriteX = planePtr->destX; _vm->_draw->_destSpriteY = planePtr->destY; - left = ptr->pieces[pictIndex][pieceIndex].left; - right = ptr->pieces[pictIndex][pieceIndex].right; - top = ptr->pieces[pictIndex][pieceIndex].top; + left = ptr->pieces[pictIndex][pieceIndex].left; + right = ptr->pieces[pictIndex][pieceIndex].right; + top = ptr->pieces[pictIndex][pieceIndex].top; bottom = ptr->pieces[pictIndex][pieceIndex].bottom; _vm->_draw->_sourceSurface = _staticPictToSprite[scenery * 7 + pictIndex]; - _vm->_draw->_destSurface = 21; - _vm->_draw->_spriteLeft = left; - _vm->_draw->_spriteTop = top; - _vm->_draw->_spriteRight = right - left + 1; - _vm->_draw->_spriteBottom = bottom - top + 1; - _vm->_draw->_transparency = planePtr->transp ? 3 : 0; + _vm->_draw->_destSurface = 21; + _vm->_draw->_spriteLeft = left; + _vm->_draw->_spriteTop = top; + _vm->_draw->_spriteRight = right - left + 1; + _vm->_draw->_spriteBottom = bottom - top + 1; + _vm->_draw->_transparency = planePtr->transp ? 3 : 0; _vm->_draw->spriteOperation(DRAW_BLITSURF); } } @@ -337,7 +336,7 @@ void Scenery::updateStatic(int16 orderFrom, byte index, byte layer) { continue; pieceIndex = planePtr->pieceIndex; - pictIndex = planePtr->pictIndex - 1; + pictIndex = planePtr->pictIndex - 1; if (pictIndex >= _staticPictCount[index]) continue; @@ -351,9 +350,9 @@ void Scenery::updateStatic(int16 orderFrom, byte index, byte layer) { _vm->_draw->_destSpriteX = planePtr->destX; _vm->_draw->_destSpriteY = planePtr->destY; - left = pictPtr[pictIndex][pieceIndex].left; - right = pictPtr[pictIndex][pieceIndex].right; - top = pictPtr[pictIndex][pieceIndex].top; + left = pictPtr[pictIndex][pieceIndex].left; + right = pictPtr[pictIndex][pieceIndex].right; + top = pictPtr[pictIndex][pieceIndex].top; bottom = pictPtr[pictIndex][pieceIndex].bottom; if (_vm->_draw->_destSpriteX > _toRedrawRight) @@ -372,10 +371,10 @@ void Scenery::updateStatic(int16 orderFrom, byte index, byte layer) { _vm->_draw->_destSpriteY = _toRedrawTop; } - _vm->_draw->_spriteLeft = left; - _vm->_draw->_spriteTop = top; - _vm->_draw->_spriteRight = right - left + 1; - _vm->_draw->_spriteBottom = bottom - top + 1; + _vm->_draw->_spriteLeft = left; + _vm->_draw->_spriteTop = top; + _vm->_draw->_spriteRight = right - left + 1; + _vm->_draw->_spriteBottom = bottom - top + 1; if ((_vm->_draw->_spriteRight <= 0) || (_vm->_draw->_spriteBottom <= 0)) @@ -393,8 +392,8 @@ void Scenery::updateStatic(int16 orderFrom, byte index, byte layer) { _vm->_draw->_sourceSurface = _staticPictToSprite[index * 7 + pictIndex]; - _vm->_draw->_destSurface = 21; - _vm->_draw->_transparency = planePtr->transp ? 3 : 0; + _vm->_draw->_destSurface = 21; + _vm->_draw->_transparency = planePtr->transp ? 3 : 0; _vm->_draw->spriteOperation(DRAW_BLITSURF); } } @@ -422,8 +421,6 @@ int16 Scenery::loadAnim(char search) { int16 j; int16 sceneryIndex; int16 framesCount; - byte *extData; - byte *dataPtr; Animation *ptr; int16 width; int16 height; @@ -431,15 +428,14 @@ int16 Scenery::loadAnim(char search) { int16 sprIndex; uint32 layerPos; - extData = 0; - _vm->_inter->evalExpr(&sceneryIndex); - picsCount = _vm->_inter->load16(); - resId = _vm->_inter->load16(); + _vm->_game->_script->evalExpr(&sceneryIndex); + picsCount = _vm->_game->_script->readInt16(); + resId = _vm->_game->_script->readInt16(); if (search) { for (i = 0; i < 10; i++) { if ((_animPictCount[i] != 0) && (_animResId[i] == resId)) { - _vm->_global->_inter_execPtr += 8 * _animPictCount[i]; + _vm->_game->_script->skip(8 * _animPictCount[i]); return i; } @@ -451,50 +447,50 @@ int16 Scenery::loadAnim(char search) { _animPictCount[sceneryIndex] = picsCount; _animResId[sceneryIndex] = resId; - if (resId >= 30000) { - extData = _vm->_game->loadExtData(resId, 0, 0); - dataPtr = extData; - } else - dataPtr = _vm->_game->loadTotResource(resId); + Resource *resource = _vm->_game->_resources->getResource((uint16) resId); + if (!resource) + return 0; ptr = &_animations[sceneryIndex]; - ptr->layersCount = READ_LE_UINT16(dataPtr); - dataPtr += 2; + ptr->layersCount = resource->stream()->readSint16LE(); ptr->layers = new AnimLayer[ptr->layersCount]; for (i = 0; i < ptr->layersCount; i++) { - int16 offset = READ_LE_UINT16(dataPtr + i * 2); - Common::MemoryReadStream layerData(dataPtr + offset - 2, 4294967295U); - - ptr->layers[i].unknown0 = layerData.readSint16LE(); - ptr->layers[i].posX = layerData.readSint16LE(); - ptr->layers[i].posY = layerData.readSint16LE(); - ptr->layers[i].animDeltaX = layerData.readSint16LE(); - ptr->layers[i].animDeltaY = layerData.readSint16LE(); - ptr->layers[i].transp = layerData.readSByte(); + Common::SeekableReadStream &layerData = *resource->stream(); + + layerData.seek(2 + i * 2); + layerData.seek(layerData.readUint16LE()); + + ptr->layers[i].unknown0 = layerData.readSint16LE(); + ptr->layers[i].posX = layerData.readSint16LE(); + ptr->layers[i].posY = layerData.readSint16LE(); + ptr->layers[i].animDeltaX = layerData.readSint16LE(); + ptr->layers[i].animDeltaY = layerData.readSint16LE(); + ptr->layers[i].transp = layerData.readSByte(); ptr->layers[i].framesCount = layerData.readSint16LE(); + // Going through the AnimFramePiece, finding the end for each layerPos = layerData.pos(); framesCount = 0; - layerData.seek(4, SEEK_CUR); - for (j = 0; j < ptr->layers[i].framesCount; - j++, framesCount++, layerData.seek(4, SEEK_CUR)) { + for (j = 0; j < ptr->layers[i].framesCount; j++) { + layerData.skip(4); // pictIndex, pieceIndex, destX, destY while (layerData.readByte() == 1) { framesCount++; - layerData.seek(4, SEEK_CUR); + layerData.skip(4); // pictIndex, pieceIndex, destX, destY } + framesCount++; } layerData.seek(layerPos); ptr->layers[i].frames = new AnimFramePiece[framesCount]; for (j = 0; j < framesCount; j++) { - ptr->layers[i].frames[j].pictIndex = layerData.readByte(); + ptr->layers[i].frames[j].pictIndex = layerData.readByte(); ptr->layers[i].frames[j].pieceIndex = layerData.readByte(); - ptr->layers[i].frames[j].destX = layerData.readSByte(); - ptr->layers[i].frames[j].destY = layerData.readSByte(); - ptr->layers[i].frames[j].notFinal = layerData.readSByte(); + ptr->layers[i].frames[j].destX = layerData.readSByte(); + ptr->layers[i].frames[j].destY = layerData.readSByte(); + ptr->layers[i].frames[j].notFinal = layerData.readSByte(); } } @@ -502,13 +498,13 @@ int16 Scenery::loadAnim(char search) { ptr->piecesCount = new uint32[picsCount]; for (i = 0; i < picsCount; i++) { - int16 pictDescId = _vm->_inter->load16(); + int16 pictDescId = _vm->_game->_script->readInt16(); loadPieces(pictDescId, ptr->pieces[i], ptr->piecesCount[i]); - width = _vm->_inter->load16(); - height = _vm->_inter->load16(); - sprResId = _vm->_inter->load16(); + width = _vm->_game->_script->readInt16(); + height = _vm->_game->_script->readInt16(); + sprResId = _vm->_game->_script->readInt16(); for (sprIndex = 0; sprIndex < 20; sprIndex++) if (_spriteResId[sprIndex] == sprResId) break; @@ -522,22 +518,21 @@ int16 Scenery::loadAnim(char search) { ; _animPictToSprite[7 * sceneryIndex + i] = sprIndex; - _spriteRefs[sprIndex] = 1; + _spriteRefs[sprIndex] = 1; _spriteResId[sprIndex] = sprResId; _vm->_draw->initSpriteSurf(sprIndex, width, height, 2); _vm->_video->clearSurf(*_vm->_draw->_spritesArray[sprIndex]); - _vm->_draw->_destSurface = sprIndex; - _vm->_draw->_spriteLeft = sprResId; + _vm->_draw->_destSurface = sprIndex; + _vm->_draw->_spriteLeft = sprResId; _vm->_draw->_transparency = 0; - _vm->_draw->_destSpriteX = 0; - _vm->_draw->_destSpriteY = 0; + _vm->_draw->_destSpriteX = 0; + _vm->_draw->_destSpriteY = 0; _vm->_draw->spriteOperation(DRAW_LOADSPRITE); } } - delete[] extData; - + delete resource; return sceneryIndex + 100; } @@ -545,7 +540,7 @@ void Scenery::freeAnim(int16 index) { int16 spr; if (index == -1) - _vm->_inter->evalExpr(&index); + _vm->_game->_script->evalExpr(&index); if (_animPictCount[index] == 0) return; @@ -563,6 +558,7 @@ void Scenery::freeAnim(int16 index) { for (int i = 0; i < _animations[index].layersCount; i++) delete[] _animations[index].layers[i].frames; + delete[] _animations[index].layers; delete[] _animations[index].pieces; delete[] _animations[index].piecesCount; @@ -607,8 +603,8 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, return; _vm->_game->capturePush(_toRedrawLeft, _toRedrawTop, - _toRedrawRight - _toRedrawLeft + 1, - _toRedrawBottom - _toRedrawTop + 1); + _toRedrawRight - _toRedrawLeft + 1, + _toRedrawBottom - _toRedrawTop + 1); *_pCaptureCounter = *_pCaptureCounter + 1; } @@ -628,7 +624,7 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, while (_vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) <= frame) _vm->_vidPlayer->slotPlay(obj.videoSlot - 1); } else { - int16 curFrame = _vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1); + int16 curFrame = _vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1); uint8 frameWrap = curFrame / 256; frame = (frame + 1) % 256; @@ -636,17 +632,17 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, _vm->_vidPlayer->slotPlay(obj.videoSlot - 1); } - destX = 0; - destY = 0; - left = *(obj.pPosX); - top = *(obj.pPosY); - right = left + _vm->_vidPlayer->getWidth(obj.videoSlot - 1) - 1; - bottom = top + _vm->_vidPlayer->getHeight(obj.videoSlot - 1) - 1; + destX = 0; + destY = 0; + left = *(obj.pPosX); + top = *(obj.pPosY); + right = left + _vm->_vidPlayer->getWidth(obj.videoSlot - 1) - 1; + bottom = top + _vm->_vidPlayer->getHeight(obj.videoSlot - 1) - 1; if (flags & 2) { if (left < _vm->_mult->_animLeft) { destX += _vm->_mult->_animLeft - left; - left = _vm->_mult->_animLeft; + left = _vm->_mult->_animLeft; } if ((_vm->_mult->_animLeft + _vm->_mult->_animWidth) <= right) @@ -654,7 +650,7 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, if (top < _vm->_mult->_animTop) { destY += _vm->_mult->_animTop - top; - top = _vm->_mult->_animTop; + top = _vm->_mult->_animTop; } if ((_vm->_mult->_animTop + _vm->_mult->_animHeight) <= bottom) @@ -663,7 +659,7 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, } else if (flags & 4) { if (left < _toRedrawLeft) { destX += _toRedrawLeft - left; - left = _toRedrawLeft; + left = _toRedrawLeft; } if (right > _toRedrawRight) @@ -671,16 +667,16 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, if (top < _toRedrawTop) { destY += _toRedrawTop - top; - top = _toRedrawTop; + top = _toRedrawTop; } if (bottom > _toRedrawBottom) bottom = _toRedrawBottom; } else { - _toRedrawTop = top; - _toRedrawLeft = left; - _toRedrawRight = right; + _toRedrawTop = top; + _toRedrawLeft = left; + _toRedrawRight = right; _toRedrawBottom = bottom; } @@ -690,7 +686,7 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, if (left < _vm->_mult->_animLeft) { destX += _vm->_mult->_animLeft - left; - left = _vm->_mult->_animLeft; + left = _vm->_mult->_animLeft; } if ((_vm->_mult->_animLeft + _vm->_mult->_animWidth) <= right) @@ -698,40 +694,40 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, if (top < _vm->_mult->_animTop) { destY += _vm->_mult->_animTop - top; - top = _vm->_mult->_animTop; + top = _vm->_mult->_animTop; } if ((_vm->_mult->_animTop + _vm->_mult->_animHeight) <= bottom) bottom = _vm->_mult->_animTop + _vm->_mult->_animHeight - 1; - _vm->_draw->_spriteLeft = destX; - _vm->_draw->_spriteTop = destY; - _vm->_draw->_spriteRight = right - left + 1; - _vm->_draw->_spriteBottom = bottom - top + 1; - _vm->_draw->_destSpriteX = left; - _vm->_draw->_destSpriteY = top; + _vm->_draw->_spriteLeft = destX; + _vm->_draw->_spriteTop = destY; + _vm->_draw->_spriteRight = right - left + 1; + _vm->_draw->_spriteBottom = bottom - top + 1; + _vm->_draw->_destSpriteX = left; + _vm->_draw->_destSpriteY = top; _vm->_draw->_transparency = layer; if (layer & 0x80) _vm->_draw->_spriteLeft = _vm->_vidPlayer->getWidth(obj.videoSlot - 1) - (destX + _vm->_draw->_spriteRight); _vm->_vidPlayer->slotCopyFrame(obj.videoSlot - 1, _vm->_draw->_backSurface->getVidMem(), - _vm->_draw->_spriteLeft, _vm->_draw->_spriteTop, + _vm->_draw->_spriteLeft, _vm->_draw->_spriteTop, _vm->_draw->_spriteRight, _vm->_draw->_spriteBottom, _vm->_draw->_destSpriteX, _vm->_draw->_destSpriteY, _vm->_draw->_backSurface->getWidth(), (_vm->_draw->_transparency != 0) ? 0 : -1); _vm->_draw->invalidateRect(_vm->_draw->_destSpriteX, _vm->_draw->_destSpriteY, - _vm->_draw->_destSpriteX + _vm->_draw->_spriteRight - 1, + _vm->_draw->_destSpriteX + _vm->_draw->_spriteRight - 1, _vm->_draw->_destSpriteY + _vm->_draw->_spriteBottom - 1); } if (!(flags & 4)) { - _animLeft = _toRedrawLeft = left; - _animTop = _toRedrawTop = top; - _animRight = _toRedrawRight = right; + _animLeft = _toRedrawLeft = left; + _animTop = _toRedrawTop = top; + _animRight = _toRedrawRight = right; _animBottom = _toRedrawBottom = bottom; } @@ -757,13 +753,13 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, return; _vm->_game->capturePush(_toRedrawLeft, _toRedrawTop, - _toRedrawRight - _toRedrawLeft + 1, - _toRedrawBottom - _toRedrawTop + 1); + _toRedrawRight - _toRedrawLeft + 1, + _toRedrawBottom - _toRedrawTop + 1); *_pCaptureCounter = *_pCaptureCounter + 1; } - pictPtr = _animations[animation].pieces; + pictPtr = _animations[animation].pieces; framePtr = layerPtr->frames; for (i = 0; i < frame; i++, framePtr++) @@ -771,9 +767,9 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, framePtr++; if (flags & 4) { - _toRedrawLeft = MAX(_toRedrawLeft, _vm->_mult->_animLeft); - _toRedrawTop = MAX(_toRedrawTop, _vm->_mult->_animTop); - _toRedrawRight = MIN(_toRedrawRight, + _toRedrawLeft = MAX(_toRedrawLeft, _vm->_mult->_animLeft); + _toRedrawTop = MAX(_toRedrawTop, _vm->_mult->_animTop); + _toRedrawRight = MIN(_toRedrawRight, (int16)(_vm->_mult->_animLeft + _vm->_mult->_animWidth - 1)); _toRedrawBottom = MIN(_toRedrawBottom, (int16)(_vm->_mult->_animTop + _vm->_mult->_animHeight - 1)); @@ -844,7 +840,7 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, (_vm->_mult->_animLeft + _vm->_mult->_animWidth) + 1; if (destY < _vm->_mult->_animTop) { - top += _vm->_mult->_animTop - destY; + top += _vm->_mult->_animTop - destY; destY = _vm->_mult->_animTop; } @@ -863,7 +859,7 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, right -= destX + right - left - _toRedrawRight; if (destY < _toRedrawTop) { - top += _toRedrawTop - destY; + top += _toRedrawTop - destY; destY = _toRedrawTop; } @@ -877,33 +873,33 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, if (doDraw) { _vm->_draw->_sourceSurface = _animPictToSprite[animation * 7 + pictIndex]; - _vm->_draw->_destSurface = 21; + _vm->_draw->_destSurface = 21; - _vm->_draw->_spriteLeft = left; - _vm->_draw->_spriteTop = top; - _vm->_draw->_spriteRight = right - left + 1; + _vm->_draw->_spriteLeft = left; + _vm->_draw->_spriteTop = top; + _vm->_draw->_spriteRight = right - left + 1; _vm->_draw->_spriteBottom = bottom - top + 1; - _vm->_draw->_destSpriteX = destX; - _vm->_draw->_destSpriteY = destY; + _vm->_draw->_destSpriteX = destX; + _vm->_draw->_destSpriteY = destY; _vm->_draw->_transparency = transp; _vm->_draw->spriteOperation(DRAW_BLITSURF); } if (!(flags & 4)) { if (_toRedrawLeft == -12345) { - _toRedrawLeft = destX; - _animLeft = destX; - _toRedrawTop = destY; - _animTop = destY; - _toRedrawRight = destX + right - left; - _animRight = destX + right - left; + _toRedrawLeft = destX; + _animLeft = destX; + _toRedrawTop = destY; + _animTop = destY; + _toRedrawRight = destX + right - left; + _animRight = destX + right - left; _toRedrawBottom = destY + bottom - top; - _animBottom = destY + bottom - top; + _animBottom = destY + bottom - top; } else { - _toRedrawLeft = MIN(_toRedrawLeft, destX); - _toRedrawTop = MIN(_toRedrawTop, destY); - _toRedrawRight = - MAX(_toRedrawRight, (int16)(destX + right - left)); + _toRedrawLeft = MIN(_toRedrawLeft, destX); + _toRedrawTop = MIN(_toRedrawTop, destY); + _toRedrawRight = + MAX(_toRedrawRight, (int16)(destX + right - left)); _toRedrawBottom = MAX(_toRedrawBottom, (int16)(destY + bottom - top)); } @@ -952,41 +948,23 @@ Scenery::AnimLayer *Scenery::getAnimLayer(uint16 index, uint16 layer) { } void Scenery::loadPieces(int16 pictDescId, PieceDesc *&pieceDesc, uint32 &piecesCount) { - byte *data; - uint32 size; - bool fromExt = false; - - if (pictDescId >= 30000) { - fromExt = true; - - uint32 eSize; - - data = _vm->_game->loadExtData(pictDescId, 0, 0, &eSize); - size = eSize; - } else { - int16 tSize; - - data = _vm->_game->loadTotResource(pictDescId, &tSize); - size = tSize; + Resource *resource = _vm->_game->_resources->getResource(pictDescId); + if (!resource) { + warning("Scenery::loadPieces(): Can't load %d", pictDescId); + return; } - if (!data) - error("Scenery::loadPieces(): Can't load pictDescId %d", pictDescId); - - piecesCount = size / 8; + piecesCount = resource->getSize() / 8; pieceDesc = new PieceDesc[piecesCount]; - Common::MemoryReadStream pieceData(data, size); - for (uint32 i = 0; i < piecesCount; i++) { - pieceDesc[i].left = (int16) pieceData.readUint16LE(); - pieceDesc[i].right = (int16) pieceData.readUint16LE(); - pieceDesc[i].top = (int16) pieceData.readUint16LE(); - pieceDesc[i].bottom = (int16) pieceData.readUint16LE(); + pieceDesc[i].left = resource->stream()->readSint16LE(); + pieceDesc[i].right = resource->stream()->readSint16LE(); + pieceDesc[i].top = resource->stream()->readSint16LE(); + pieceDesc[i].bottom = resource->stream()->readSint16LE(); } - if (fromExt) - delete[] data; + delete resource; } } // End of namespace Gob diff --git a/engines/gob/script.cpp b/engines/gob/script.cpp new file mode 100644 index 0000000000..6162e943bf --- /dev/null +++ b/engines/gob/script.cpp @@ -0,0 +1,522 @@ +/* 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. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "common/util.h" +#include "common/endian.h" + +#include "gob/gob.h" +#include "gob/script.h" +#include "gob/dataio.h" +#include "gob/expression.h" +#include "gob/videoplayer.h" + +namespace Gob { + +Script::Script(GobEngine *vm) : _vm(vm) { + _expression = new Expression(vm); + + _finished = true; + + _totData = 0; + _totPtr = 0; + _totSize = 0; + + _lomHandle = -1; + + memset(&_totProperties, 0, sizeof(TOTFile::Properties)); +} + +Script::~Script() { + unload(); + + delete _expression; +} + +uint32 Script::read(byte *data, int32 size) { + int32 toRead = MIN<int32>(size, _totSize - (_totPtr - _totData)); + + if (toRead < 1) + return 0; + + memcpy(data, _totPtr, toRead); + _totPtr += toRead; + + return toRead; +} + +uint32 Script::peek(byte *data, int32 size, int32 offset) const { + int32 totOffset = ((_totPtr + offset) - _totData); + + if (totOffset < 1) + return 0; + if (((uint32) totOffset) >= _totSize) + return 0; + + int32 toPeek = MIN<int32>(size, _totSize - totOffset); + if (toPeek < 1) + return 0; + + memcpy(data, _totPtr + offset, toPeek); + + return toPeek; +} + +int32 Script::pos() const { + if (!_totData) + return -1; + + return _totPtr - _totData; +} + +int32 Script::getSize() const { + if (!_totData) + return -1; + + return _totSize; +} + +bool Script::seek(int32 offset, int whence) { + if (!_totData) + return false; + + if (whence == SEEK_CUR) + offset += pos(); + else if (whence == SEEK_END) + offset += _totSize; + + if ((offset < 0) || (((uint32) offset) >= _totSize)) + return false; + + // Cannot seek into the header + if (offset < 128) { + _finished = true; + return false; + } + + // A successful seek means the script file continues to be executed + _finished = false; + + _totPtr = _totData + offset; + + return true; +} + +bool Script::skip(int32 offset) { + return seek(offset, SEEK_CUR); +} + +int32 Script::getOffset(byte *ptr) const { + if (!_totData) + return -1; + + if ((ptr < _totData) || (ptr >= (_totData + _totSize))) + return -1; + + return ptr - _totData; +} + +byte *Script::getData(int32 offset) const { + if (!_totData) + return 0; + if ((offset < 0) || (((uint32) offset) >= _totSize)) + return 0; + + return _totData + offset; +} + +byte *Script::getData() { + return _totData; +} + +byte Script::readByte() { + byte v; + + read(&v, 1); + + return v; +} + +char Script::readChar() { + return (char) readByte(); +} + +uint8 Script::readUint8() { + return (uint8) readByte(); +} + +uint16 Script::readUint16() { + byte v[2]; + + read(v, 2); + + return READ_LE_UINT16(v); +} + +uint32 Script::readUint32() { + byte v[4]; + + read(v, 4); + + return READ_LE_UINT32(v); +} + +int8 Script::readInt8() { + return (int8) readByte(); +} + +int16 Script::readInt16() { + return (int16) readUint16(); +} + +int32 Script::readInt32() { + return (int32) readUint32(); +} + +char *Script::readString(int32 length) { + if (length < 0) { + length = 0; + while (_totPtr[length++] != '\0'); + } + + char *string = (char *) _totPtr; + + _totPtr += length; + + return string; +} + +byte Script::peekByte(int32 offset) { + byte v; + + peek(&v, 1, offset); + + return v; +} + +char Script::peekChar(int32 offset) { + return (char) peekByte(offset); +} + +uint8 Script::peekUint8(int32 offset) { + return (uint8) peekByte(offset); +} + +uint16 Script::peekUint16(int32 offset) { + byte v[2]; + + peek(v, 2, offset); + + return READ_LE_UINT16(v); +} + +uint32 Script::peekUint32(int32 offset) { + byte v[4]; + + peek(v, 4, offset); + + return READ_LE_UINT32(v); +} + +int8 Script::peekInt8(int32 offset) { + return (int8) peekByte(offset); +} + +int16 Script::peekInt16(int32 offset) { + return (int16) peekUint16(offset); +} + +int32 Script::peekInt32(int32 offset) { + return (int32) peekUint32(offset); +} + +char *Script::peekString(int32 offset) { + return (char *) (_totPtr + offset); +} + +int16 Script::readVarIndex(uint16 *size, uint16 *type) { + return _expression->parseVarIndex(size, type); +} + +int16 Script::readValExpr(byte stopToken) { + return _expression->parseValExpr(stopToken); +} + +int16 Script::readExpr(byte stopToken, byte *type) { + return _expression->parseExpr(stopToken, type); +} + +void Script::skipExpr(char stopToken) { + _expression->skipExpr(stopToken); +} + +char Script::evalExpr(int16 *pRes) { + byte type; + + _expression->printExpr(99); + + _expression->parseExpr(99, &type); + if (!pRes) + return type; + + switch (type) { + case TYPE_IMM_INT16: + *pRes = _expression->getResultInt(); + break; + + case TYPE_IMM_STR: + case GOB_FALSE: + *pRes = 0; + break; + + case GOB_TRUE: + *pRes = 1; + break; + } + + return type; +} + +bool Script::evalBoolResult() { + byte type; + + _expression->printExpr(99); + + _expression->parseExpr(99, &type); + if ( (type == GOB_TRUE) || + ((type == TYPE_IMM_INT16) && _expression->getResultInt())) + return true; + else + return false; +} + +int32 Script::getResultInt() const { + return _expression->getResultInt(); +} + +char *Script::getResultStr() const { + return _expression->getResultStr(); +} + +bool Script::load(const Common::String &fileName) { + unload(); + + _finished = false; + + bool isLOM; + + _totFile = TOTFile::createFileName(fileName, isLOM); + + if (isLOM) { + if (!loadLOM(_totFile)) { + unload(); + return false; + } + } else { + if (!loadTOT(_totFile)) { + unload(); + return false; + } + } + + return true; +} + +bool Script::loadTOT(const Common::String &fileName) { + TOTFile totFile(_vm); + + if (!totFile.load(fileName)) + return false; + + Common::SeekableReadStream *stream = totFile.getStream(); + if (!stream) + return false; + + if (!totFile.getProperties(_totProperties)) + return false; + + _totSize = _totProperties.scriptEnd; + if (_totSize <= 0) + return false; + + _totData = new byte[_totSize]; + if (stream->read(_totData, _totSize) != _totSize) + return false; + + return true; +} + +bool Script::loadLOM(const Common::String &fileName) { + warning("Stub: Script::loadLOM(%s)", _totFile.c_str()); + + _lomHandle = _vm->_dataIO->openData(_totFile.c_str()); + if (_lomHandle < 0) + return false; + + DataStream *stream = _vm->_dataIO->openAsStream(_lomHandle); + + stream->seek(48); + _totSize = stream->readUint32LE(); + stream->seek(0); + + _totData = new byte[_totSize]; + stream->read(_totData, _totSize); + + delete stream; + + return false; +} + +void Script::unload() { + unloadTOT(); +} + +void Script::unloadTOT() { + if (_lomHandle >= 0) + _vm->_dataIO->closeData(_lomHandle); + + // Unwind the call stack + while (!_callStack.empty()) + pop(); + + delete[] _totData; + + _totData = 0; + _totSize = 0; + _totPtr = 0; + _lomHandle = -1; + _totFile.clear(); + + _finished = true; +} + +bool Script::isLoaded() const { + return _totData != 0; +} + +void Script::setFinished(bool finished) { + _finished = finished; +} + +bool Script::isFinished() const { + return _finished; +} + +void Script::push() { + if (!isLoaded()) + // Nothing to do + return; + + CallEntry currentCall; + + currentCall.totPtr = _totPtr; + currentCall.finished = _finished; + + _callStack.push(currentCall); +} + +void Script::pop(bool ret) { + if (!isLoaded()) + // Nothing to do + return; + + // Unmatched pop? + assert(!_callStack.empty()); + + CallEntry lastCall = _callStack.pop(); + + if (ret) { + _totPtr = lastCall.totPtr; + _finished = lastCall.finished; + } +} + +void Script::call(uint32 offset) { + if (!isLoaded()) + // Nothing to do + return; + + push(); + seek(offset); +} + +uint8 Script::getVersionMajor() const { + return _totProperties.versionMajor; +} + +uint8 Script::getVersionMinor() const { + return _totProperties.versionMinor; +} + +uint32 Script::getVariablesCount() const { + return _totProperties.variablesCount; +} + +uint32 Script::getTextsOffset() const { + return _totProperties.textsOffset; +} + +uint32 Script::getResourcesOffset() const { + return _totProperties.resourcesOffset; +} + +uint16 Script::getAnimDataSize() const { + return _totProperties.animDataSize; +} + +uint8 Script::getImFileNumber() const { + return _totProperties.imFileNumber; +} + +uint8 Script::getExFileNumber() const { + return _totProperties.exFileNumber; +} + +uint8 Script::getCommunHandling() const { + return _totProperties.communHandling; +} + +uint16 Script::getFunctionOffset(uint8 function) const { + if (!_totData) + return 0; + + // Offsets 100-128, 2 bytes per function + assert(function <= 13); + + return _totProperties.functions[function]; +} + +uint32 Script::getVariablesCount(const char *fileName, GobEngine *vm) { + DataStream *stream = vm->_dataIO->getDataStream(fileName); + if (!stream) + return 0; + + stream->seek(0x2C); + uint32 variablesCount = stream->readUint32LE(); + delete stream; + + return variablesCount; +} + +} // End of namespace Gob diff --git a/engines/gob/script.h b/engines/gob/script.h new file mode 100644 index 0000000000..64a04503b1 --- /dev/null +++ b/engines/gob/script.h @@ -0,0 +1,169 @@ +/* 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. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef GOB_SCRIPT_H +#define GOB_SCRIPT_H + +#include "common/str.h" +#include "common/stack.h" + +#include "gob/totfile.h" + +namespace Gob { + +class GobEngine; +class Expression; + +class Script { +public: + Script(GobEngine *vm); + ~Script(); + + /** Read data and move the pointer accordingly. */ + uint32 read(byte *data, int32 size); + /** Read data (from an optional offset) without moving the pointer. */ + uint32 peek(byte *data, int32 size, int32 offset = 0) const; + + // Stream properties + int32 pos() const; + int32 getSize() const; + + // Stream seeking + bool seek(int32 offset, int whence = SEEK_SET); + bool skip(int32 offset); + + // Reading data + byte readByte (); + char readChar (); + uint8 readUint8 (); + uint16 readUint16(); + uint32 readUint32(); + int8 readInt8 (); + int16 readInt16 (); + int32 readInt32 (); + char *readString(int32 length = -1); + + // Peeking data + byte peekByte (int32 offset = 0); + char peekChar (int32 offset = 0); + uint8 peekUint8 (int32 offset = 0); + uint16 peekUint16(int32 offset = 0); + uint32 peekUint32(int32 offset = 0); + int8 peekInt8 (int32 offset = 0); + int16 peekInt16 (int32 offset = 0); + int32 peekInt32 (int32 offset = 0); + char *peekString(int32 offset = 0); + + // Expression parsing functions + int16 readVarIndex(uint16 *size = 0, uint16 *type = 0); + int16 readValExpr(byte stopToken = 99); + int16 readExpr(byte stopToken, byte *type); + void skipExpr(char stopToken); + + // Higher-level expression parsing functions + char evalExpr(int16 *pRes); + bool evalBoolResult(); + + // Accessing the result of expressions + int32 getResultInt() const; + char *getResultStr() const; + + /** Returns the offset the specified pointer is within the script data. */ + int32 getOffset(byte *ptr) const; + /** Returns the data pointer to the offset. */ + byte *getData(int32 offset) const; + + /** Returns the raw data pointer. */ + byte *getData(); + + /** Load a script file. */ + bool load(const Common::String &fileName); + /** Unload the script. */ + void unload(); + /** Was a script loaded? */ + bool isLoaded() const; + + /** Setting the 'finished' property. */ + void setFinished(bool finished); + /** Querying the 'finished' property. */ + bool isFinished() const; + + // Call stack operations + /** Push the current script position onto the call stack. */ + void push(); + /** Pop a script position from the call stack (and return there). */ + void pop(bool ret = true); + /** Push the current script position and branch to the specified offset. */ + void call(uint32 offset); + + // Fixed properties + uint8 getVersionMajor () const; + uint8 getVersionMinor () const; + uint32 getVariablesCount () const; + uint32 getTextsOffset () const; + uint32 getResourcesOffset() const; + uint16 getAnimDataSize () const; + uint8 getImFileNumber () const; + uint8 getExFileNumber () const; + uint8 getCommunHandling () const; + + uint16 getFunctionOffset (uint8 function) const; + + static uint32 getVariablesCount(const char *fileName, GobEngine *vm); + +private: + struct CallEntry { + byte *totPtr; + bool finished; + }; + + GobEngine *_vm; + Expression *_expression; + + bool _finished; + + Common::String _totFile; + byte *_totData; + byte *_totPtr; + uint32 _totSize; + + int16 _lomHandle; + + TOTFile::Properties _totProperties; + + Common::Stack<CallEntry> _callStack; + + /** Loading a TOT file. */ + bool loadTOT(const Common::String &fileName); + /** Loading a LOM file. */ + bool loadLOM(const Common::String &fileName); + + /** Unloading a TOT file. */ + void unloadTOT(); +}; + +} // End of namespace Gob + +#endif // GOB_SCRIPT_H diff --git a/engines/gob/sound/adlib.cpp b/engines/gob/sound/adlib.cpp index 07481431b6..7ab8e1f8dd 100644 --- a/engines/gob/sound/adlib.cpp +++ b/engines/gob/sound/adlib.cpp @@ -39,18 +39,33 @@ const unsigned char AdLib::_volRegNums[] = { }; AdLib::AdLib(Audio::Mixer &mixer) : _mixer(&mixer) { + init(); +} + +AdLib::~AdLib() { + Common::StackLock slock(_mutex); + + _mixer->stopHandle(_handle); + OPLDestroy(_opl); + if (_data && _freeData) + delete[] _data; +} + +void AdLib::init() { _index = -1; _data = 0; _playPos = 0; _dataSize = 0; _rate = _mixer->getOutputRate(); + _opl = makeAdlibOPL(_rate); _first = true; _ended = false; _playing = false; - _needFree = false; + + _freeData = false; _repCount = -1; _samplesTillPoll = 0; @@ -63,15 +78,6 @@ AdLib::AdLib(Audio::Mixer &mixer) : _mixer(&mixer) { this, -1, 255, 0, false, true); } -AdLib::~AdLib() { - Common::StackLock slock(_mutex); - - _mixer->stopHandle(_handle); - OPLDestroy(_opl); - if (_data && _needFree) - delete[] _data; -} - int AdLib::readBuffer(int16 *buffer, const int numSamples) { Common::StackLock slock(_mutex); int samples; @@ -107,7 +113,9 @@ int AdLib::readBuffer(int16 *buffer, const int numSamples) { if (_ended) { _first = true; _ended = false; - _playPos = _data + 3 + (_data[1] + 1) * 0x38; + + rewind(); + _samplesTillPoll = 0; if (_repCount == -1) { reset(); @@ -120,7 +128,6 @@ int AdLib::readBuffer(int16 *buffer, const int numSamples) { else _playing = false; } - return numSamples; } @@ -173,48 +180,6 @@ void AdLib::reset() { writeOPL(0x01, 0x20); } -void AdLib::setVoices() { - // Definitions of the 9 instruments - for (int i = 0; i < 9; i++) - setVoice(i, i, true); -} - -void AdLib::setVoice(byte voice, byte instr, bool set) { - int i; - int j; - uint16 strct[27]; - byte channel; - byte *dataPtr; - - // i = 0 : 0 1 2 3 4 5 6 7 8 9 10 11 12 26 - // i = 1 : 13 14 15 16 17 18 19 20 21 22 23 24 25 27 - for (i = 0; i < 2; i++) { - dataPtr = _data + 3 + instr * 0x38 + i * 0x1A; - for (j = 0; j < 27; j++) { - strct[j] = READ_LE_UINT16(dataPtr); - dataPtr += 2; - } - channel = _operators[voice] + i * 3; - writeOPL(0xBD, 0x00); - writeOPL(0x08, 0x00); - writeOPL(0x40 | channel, ((strct[0] & 3) << 6) | (strct[8] & 0x3F)); - if (!i) - writeOPL(0xC0 | voice, - ((strct[2] & 7) << 1) | (1 - (strct[12] & 1))); - writeOPL(0x60 | channel, ((strct[3] & 0xF) << 4) | (strct[6] & 0xF)); - writeOPL(0x80 | channel, ((strct[4] & 0xF) << 4) | (strct[7] & 0xF)); - writeOPL(0x20 | channel, ((strct[9] & 1) << 7) | - ((strct[10] & 1) << 6) | ((strct[5] & 1) << 5) | - ((strct[11] & 1) << 4) | (strct[1] & 0xF)); - if (!i) - writeOPL(0xE0 | channel, (strct[26] & 3)); - else - writeOPL(0xE0 | channel, (strct[14] & 3)); - if (i && set) - writeOPL(0x40 | channel, 0); - } -} - void AdLib::setKey(byte voice, byte note, bool on, bool spec) { short freq = 0; short octa = 0; @@ -278,7 +243,7 @@ void AdLib::setKey(byte voice, byte note, bool on, bool spec) { writeOPL(0xB0 + voice, (freq >> 8) | (octa << 2) | 0x20 * on); if (!freq) - warning("Voice %d, note %02X unknown", voice, note); + warning("AdLib: Voice %d, note %02X unknown", voice, note); } void AdLib::setVolume(byte voice, byte volume) { @@ -287,17 +252,102 @@ void AdLib::setVolume(byte voice, byte volume) { } void AdLib::pollMusic() { + if ((_playPos > (_data + _dataSize)) && (_dataSize != 0xFFFFFFFF)) { + _ended = true; + return; + } + + interpret(); +} + +void AdLib::unload() { + _playing = false; + _index = -1; + + if (_data && _freeData) + delete[] _data; + + _freeData = false; +} + +bool AdLib::isPlaying() const { + return _playing; +} + +bool AdLib::getRepeating() const { + return _repCount != 0; +} + +void AdLib::setRepeating(int32 repCount) { + _repCount = repCount; +} + +int AdLib::getIndex() const { + return _index; +} + +void AdLib::startPlay() { + if (_data) _playing = true; +} + +void AdLib::stopPlay() { + Common::StackLock slock(_mutex); + _playing = false; +} + +ADLPlayer::ADLPlayer(Audio::Mixer &mixer) : AdLib(mixer) { +} + +ADLPlayer::~ADLPlayer() { +} + +bool ADLPlayer::load(const char *fileName) { + Common::File song; + + unload(); + song.open(fileName); + if (!song.isOpen()) + return false; + + _freeData = true; + _dataSize = song.size(); + _data = new byte[_dataSize]; + song.read(_data, _dataSize); + song.close(); + + reset(); + setVoices(); + _playPos = _data + 3 + (_data[1] + 1) * 0x38; + + return true; +} + +bool ADLPlayer::load(byte *data, uint32 size, int index) { + unload(); + _repCount = 0; + + _dataSize = size; + _data = data; + _index = index; + + reset(); + setVoices(); + _playPos = _data + 3 + (_data[1] + 1) * 0x38; + + return true; +} + +void ADLPlayer::unload() { + AdLib::unload(); +} + +void ADLPlayer::interpret() { unsigned char instr; byte channel; byte note; byte volume; uint16 tempo; - if ((_playPos > (_data + _dataSize)) && (_dataSize != 0xFFFFFFFF)) { - _ended = true; - return; - } - // First tempo, we'll ignore it... if (_first) { tempo = *(_playPos++); @@ -352,7 +402,7 @@ void AdLib::pollMusic() { _samplesTillPoll = 0; return; default: - warning("Unknown special command in ADL, stopping playback: %X", + warning("ADLPlayer: Unknown special command %X, stopping playback", instr & 0x0F); _repCount = 0; _ended = true; @@ -360,7 +410,7 @@ void AdLib::pollMusic() { } break; default: - warning("Unknown command in ADL, stopping playback: %X", + warning("ADLPlayer: Unknown command %X, stopping playback", instr & 0xF0); _repCount = 0; _ended = true; @@ -383,75 +433,349 @@ void AdLib::pollMusic() { _samplesTillPoll = tempo * (_rate / 1000); } -bool AdLib::load(const char *fileName) { +void ADLPlayer::reset() { + AdLib::reset(); +} + +void ADLPlayer::rewind() { + _playPos = _data + 3 + (_data[1] + 1) * 0x38; +} + +void ADLPlayer::setVoices() { + // Definitions of the 9 instruments + for (int i = 0; i < 9; i++) + setVoice(i, i, true); +} + +void ADLPlayer::setVoice(byte voice, byte instr, bool set) { + uint16 strct[27]; + byte channel; + byte *dataPtr; + + // i = 0 : 0 1 2 3 4 5 6 7 8 9 10 11 12 26 + // i = 1 : 13 14 15 16 17 18 19 20 21 22 23 24 25 27 + for (int i = 0; i < 2; i++) { + dataPtr = _data + 3 + instr * 0x38 + i * 0x1A; + for (int j = 0; j < 27; j++) { + strct[j] = READ_LE_UINT16(dataPtr); + dataPtr += 2; + } + channel = _operators[voice] + i * 3; + writeOPL(0xBD, 0x00); + writeOPL(0x08, 0x00); + writeOPL(0x40 | channel, ((strct[0] & 3) << 6) | (strct[8] & 0x3F)); + if (!i) + writeOPL(0xC0 | voice, + ((strct[2] & 7) << 1) | (1 - (strct[12] & 1))); + writeOPL(0x60 | channel, ((strct[3] & 0xF) << 4) | (strct[6] & 0xF)); + writeOPL(0x80 | channel, ((strct[4] & 0xF) << 4) | (strct[7] & 0xF)); + writeOPL(0x20 | channel, ((strct[9] & 1) << 7) | + ((strct[10] & 1) << 6) | ((strct[5] & 1) << 5) | + ((strct[11] & 1) << 4) | (strct[1] & 0xF)); + if (!i) + writeOPL(0xE0 | channel, (strct[26] & 3)); + else + writeOPL(0xE0 | channel, (strct[14] & 3)); + if (i && set) + writeOPL(0x40 | channel, 0); + } +} + + +MDYPlayer::MDYPlayer(Audio::Mixer &mixer) : AdLib(mixer) { + init(); +} + +MDYPlayer::~MDYPlayer() { +} + +void MDYPlayer::init() { + _soundMode = 0; + + _timbres = 0; + _tbrCount = 0; + _tbrStart = 0; + _timbresSize = 0; +} + +bool MDYPlayer::loadMDY(Common::SeekableReadStream &stream) { + unloadMDY(); + + _freeData = true; + + byte mdyHeader[70]; + stream.read(mdyHeader, 70); + + _tickBeat = mdyHeader[36]; + _beatMeasure = mdyHeader[37]; + _totalTick = mdyHeader[38] + (mdyHeader[39] << 8) + (mdyHeader[40] << 16) + (mdyHeader[41] << 24); + _dataSize = mdyHeader[42] + (mdyHeader[43] << 8) + (mdyHeader[44] << 16) + (mdyHeader[45] << 24); + _nrCommand = mdyHeader[46] + (mdyHeader[47] << 8) + (mdyHeader[48] << 16) + (mdyHeader[49] << 24); +// _soundMode is either 0 (melodic) or 1 (percussive) + _soundMode = mdyHeader[58]; + _pitchBendRangeStep = 25*mdyHeader[59]; + _basicTempo = mdyHeader[60] + (mdyHeader[61] << 8); + + if (_pitchBendRangeStep < 25) + _pitchBendRangeStep = 25; + else if (_pitchBendRangeStep > 300) + _pitchBendRangeStep = 300; + + _data = new byte[_dataSize]; + stream.read(_data, _dataSize); + + reset(); + _playPos = _data; + + return true; +} + +bool MDYPlayer::loadMDY(const char *fileName) { Common::File song; - unload(); song.open(fileName); if (!song.isOpen()) return false; - _needFree = true; - _dataSize = song.size(); - _data = new byte[_dataSize]; - song.read(_data, _dataSize); - song.close(); + bool loaded = loadMDY(song); - reset(); - setVoices(); - _playPos = _data + 3 + (_data[1] + 1) * 0x38; + song.close(); - return true; + return loaded; } -bool AdLib::load(byte *data, uint32 size, int index) { - unload(); - _repCount = 0; +bool MDYPlayer::loadTBR(Common::SeekableReadStream &stream) { + unloadTBR(); - _dataSize = size; - _data = data; - _index = index; + _timbresSize = stream.size(); + + _timbres = new byte[_timbresSize]; + stream.read(_timbres, _timbresSize); reset(); setVoices(); - _playPos = _data + 3 + (_data[1] + 1) * 0x38; return true; } -void AdLib::unload() { - _playing = false; - _index = -1; +bool MDYPlayer::loadTBR(const char *fileName) { + Common::File timbres; - if (_data && _needFree) - delete[] _data; + timbres.open(fileName); + if (!timbres.isOpen()) + return false; + + bool loaded = loadTBR(timbres); - _needFree = false; + timbres.close(); + + return loaded; } -bool AdLib::isPlaying() const { - return _playing; +void MDYPlayer::unload() { + unloadTBR(); + unloadMDY(); } -bool AdLib::getRepeating() const { - return _repCount != 0; +void MDYPlayer::unloadMDY() { + AdLib::unload(); } -void AdLib::setRepeating(int32 repCount) { - _repCount = repCount; +void MDYPlayer::unloadTBR() { + delete[] _timbres; + + _timbres = 0; + _timbresSize = 0; } -int AdLib::getIndex() const { - return _index; +void MDYPlayer::interpret() { + unsigned char instr; + byte channel; + byte note; + byte volume; + uint8 tempoMult, tempoFrac; + uint8 ctrlByte1, ctrlByte2; + uint8 timbre; + + if (_first) { + for (int i = 0; i < 11; i ++) + setVolume(i, 0); + +// TODO : Set pitch range + + _tempo = _basicTempo; + _wait = *(_playPos++); + _first = false; + } + do { + instr = *_playPos; +// printf("instr 0x%X\n", instr); + switch(instr) { + case 0xF8: + _wait = *(_playPos++); + break; + case 0xFC: + _ended = true; + _samplesTillPoll = 0; + return; + case 0xF0: + _playPos++; + ctrlByte1 = *(_playPos++); + ctrlByte2 = *(_playPos++); + if (ctrlByte1 != 0x7F || ctrlByte2 != 0) { + _playPos -= 2; + while (*(_playPos++) != 0xF7); + } else { + tempoMult = *(_playPos++); + tempoFrac = *(_playPos++); + _tempo = _basicTempo * tempoMult + (unsigned)(((long)_basicTempo * tempoFrac) >> 7); + _playPos++; + } + _wait = *(_playPos++); + break; + default: + if (instr >= 0x80) { + _playPos++; + } + channel = (int)(instr & 0x0f); + + switch(instr & 0xf0) { + case 0x90: + note = *(_playPos++); + volume = *(_playPos++); + _pollNotes[channel] = note; + setVolume(channel, volume); + setKey(channel, note, true, false); + break; + case 0x80: + _playPos += 2; + note = _pollNotes[channel]; + setKey(channel, note, false, false); + break; + case 0xA0: + setVolume(channel, *(_playPos++)); + break; + case 0xC0: + timbre = *(_playPos++); + setVoice(channel, timbre, false); + break; + case 0xE0: + warning("MDYPlayer: Pitch bend not yet implemented"); + + note = *(_playPos)++; + note += (unsigned)(*(_playPos++)) << 7; + + setKey(channel, note, _notOn[channel], true); + + break; + case 0xB0: + _playPos += 2; + break; + case 0xD0: + _playPos++; + break; + default: + warning("MDYPlayer: Bad MIDI instr byte: 0%X", instr); + while ((*_playPos) < 0x80) + _playPos++; + if (*_playPos != 0xF8) + _playPos--; + break; + } //switch instr & 0xF0 + _wait = *(_playPos++); + break; + } //switch instr + } while (_wait == 0); + + if (_wait == 0xF8) { + _wait = 0xF0; + if (*_playPos != 0xF8) + _wait += *(_playPos++); + } +// _playPos++; + _samplesTillPoll = _wait * (_rate / 1000); } -void AdLib::startPlay() { - if (_data) _playing = true; +void MDYPlayer::reset() { + AdLib::reset(); + +// _soundMode 1 : Percussive mode. + if (_soundMode == 1) { + writeOPL(0xA6, 0); + writeOPL(0xB6, 0); + writeOPL(0xA7, 0); + writeOPL(0xB7, 0); + writeOPL(0xA8, 0); + writeOPL(0xB8, 0); + +// TODO set the correct frequency for the last 4 percussive voices + } } -void AdLib::stopPlay() { - Common::StackLock slock(_mutex); - _playing = false; +void MDYPlayer::rewind() { + _playPos = _data; +} + +void MDYPlayer::setVoices() { + byte *timbrePtr; + + timbrePtr = _timbres; + debugC(6, kDebugSound, "TBR version: %X.%X", timbrePtr[0], timbrePtr[1]); + timbrePtr += 2; + + _tbrCount = READ_LE_UINT16(timbrePtr); + debugC(6, kDebugSound, "Timbres counter: %d", _tbrCount); + timbrePtr += 2; + _tbrStart = READ_LE_UINT16(timbrePtr); + + timbrePtr += 2; + for (int i = 0; i < _tbrCount ; i++) + setVoice(i, i, true); +} + +void MDYPlayer::setVoice(byte voice, byte instr, bool set) { + uint16 strct[27]; + byte channel; + byte *timbrePtr; + char timbreName[10]; + + timbreName[9] = '\0'; + for (int j = 0; j < 9; j++) + timbreName[j] = _timbres[6 + j + (instr * 9)]; + debugC(6, kDebugSound, "Loading timbre %s", timbreName); + + // i = 0 : 0 1 2 3 4 5 6 7 8 9 10 11 12 26 + // i = 1 : 13 14 15 16 17 18 19 20 21 22 23 24 25 27 + for (int i = 0; i < 2; i++) { + timbrePtr = _timbres + _tbrStart + instr * 0x38 + i * 0x1A; + for (int j = 0; j < 27; j++) { + if (timbrePtr >= (_timbres + _timbresSize)) { + warning("MDYPlayer: Instrument %d out of range (%d, %d)", instr, + (uint32) (timbrePtr - _timbres), _timbresSize); + strct[j] = 0; + } else + strct[j] = READ_LE_UINT16(timbrePtr); + timbrePtr += 2; + } + channel = _operators[voice] + i * 3; + writeOPL(0xBD, 0x00); + writeOPL(0x08, 0x00); + writeOPL(0x40 | channel, ((strct[0] & 3) << 6) | (strct[8] & 0x3F)); + if (!i) + writeOPL(0xC0 | voice, + ((strct[2] & 7) << 1) | (1 - (strct[12] & 1))); + writeOPL(0x60 | channel, ((strct[3] & 0xF) << 4) | (strct[6] & 0xF)); + writeOPL(0x80 | channel, ((strct[4] & 0xF) << 4) | (strct[7] & 0xF)); + writeOPL(0x20 | channel, ((strct[9] & 1) << 7) | + ((strct[10] & 1) << 6) | ((strct[5] & 1) << 5) | + ((strct[11] & 1) << 4) | (strct[1] & 0xF)); + if (!i) + writeOPL(0xE0 | channel, (strct[26] & 3)); + else { + writeOPL(0xE0 | channel, (strct[14] & 3)); + writeOPL(0x40 | channel, 0); + } + } } } // End of namespace Gob diff --git a/engines/gob/sound/adlib.h b/engines/gob/sound/adlib.h index 4cd83d5883..3f7b46643f 100644 --- a/engines/gob/sound/adlib.h +++ b/engines/gob/sound/adlib.h @@ -38,7 +38,7 @@ class GobEngine; class AdLib : public Audio::AudioStream { public: AdLib(Audio::Mixer &mixer); - ~AdLib(); + virtual ~AdLib(); bool isPlaying() const; int getIndex() const; @@ -49,9 +49,7 @@ public: void startPlay(); void stopPlay(); - bool load(const char *fileName); - bool load(byte *data, uint32 size, int index = -1); - void unload(); + virtual void unload(); // AudioStream API int readBuffer(int16 *buffer, const int numSamples); @@ -89,18 +87,88 @@ protected: bool _playing; bool _first; bool _ended; - bool _needFree; + + bool _freeData; int _index; + unsigned char _wait; + uint8 _tickBeat; + uint8 _beatMeasure; + uint32 _totalTick; + uint32 _nrCommand; + uint16 _pitchBendRangeStep; + uint16 _basicTempo, _tempo; + void writeOPL(byte reg, byte val); void setFreqs(); - void reset(); - void setVoices(); - void setVoice(byte voice, byte instr, bool set); void setKey(byte voice, byte note, bool on, bool spec); void setVolume(byte voice, byte volume); void pollMusic(); + + virtual void interpret() = 0; + + virtual void reset(); + virtual void rewind() = 0; + virtual void setVoices() = 0; + +private: + void init(); +}; + +class ADLPlayer : public AdLib { +public: + ADLPlayer(Audio::Mixer &mixer); + ~ADLPlayer(); + + bool load(const char *fileName); + bool load(byte *data, uint32 size, int index = -1); + + void unload(); + +protected: + void interpret(); + + void reset(); + void rewind(); + + void setVoices(); + void setVoice(byte voice, byte instr, bool set); +}; + +class MDYPlayer : public AdLib { +public: + MDYPlayer(Audio::Mixer &mixer); + ~MDYPlayer(); + + bool loadMDY(const char *fileName); + bool loadMDY(Common::SeekableReadStream &stream); + bool loadTBR(const char *fileName); + bool loadTBR(Common::SeekableReadStream &stream); + + void unload(); + +protected: + byte _soundMode; + + byte *_timbres; + uint16 _tbrCount; + uint16 _tbrStart; + uint32 _timbresSize; + + void interpret(); + + void reset(); + void rewind(); + + void setVoices(); + void setVoice(byte voice, byte instr, bool set); + + void unloadTBR(); + void unloadMDY(); + +private: + void init(); }; } // End of namespace Gob diff --git a/engines/gob/sound/bgatmosphere.cpp b/engines/gob/sound/bgatmosphere.cpp index 12ceb031b7..6ce184155e 100644 --- a/engines/gob/sound/bgatmosphere.cpp +++ b/engines/gob/sound/bgatmosphere.cpp @@ -27,6 +27,7 @@ #include "common/events.h" #include "gob/sound/bgatmosphere.h" +#include "gob/sound/sounddesc.h" namespace Gob { diff --git a/engines/gob/sound/bgatmosphere.h b/engines/gob/sound/bgatmosphere.h index 3fa648b94d..aa8cf58e10 100644 --- a/engines/gob/sound/bgatmosphere.h +++ b/engines/gob/sound/bgatmosphere.h @@ -29,11 +29,12 @@ #include "sound/mixer.h" #include "common/mutex.h" -#include "gob/sound/sounddesc.h" #include "gob/sound/soundmixer.h" namespace Gob { +class SoundDesc; + class BackgroundAtmosphere : private SoundMixer { public: enum PlayMode { diff --git a/engines/gob/sound/cdrom.cpp b/engines/gob/sound/cdrom.cpp index ec9b2aaccb..4d6a7ec966 100644 --- a/engines/gob/sound/cdrom.cpp +++ b/engines/gob/sound/cdrom.cpp @@ -30,6 +30,7 @@ #include "gob/gob.h" #include "gob/sound/cdrom.h" #include "gob/helper.h" +#include "gob/dataio.h" namespace Gob { @@ -86,7 +87,7 @@ void CDROM::startTrack(const char *trackName) { byte *matchPtr = getTrackBuffer(trackName); if (!matchPtr) { - warning("Track \"%s\" not found", trackName); + warning("CDROM: Track \"%s\" not found", trackName); return; } diff --git a/engines/gob/sound/cdrom.h b/engines/gob/sound/cdrom.h index 201f7adb75..6f01e6f90a 100644 --- a/engines/gob/sound/cdrom.h +++ b/engines/gob/sound/cdrom.h @@ -26,10 +26,10 @@ #ifndef GOB_SOUND_CDROM_H #define GOB_SOUND_CDROM_H -#include "gob/dataio.h" - namespace Gob { +class DataStream; + class CDROM { public: CDROM(); diff --git a/engines/gob/sound/infogrames.cpp b/engines/gob/sound/infogrames.cpp index 0b46f3485c..c955dba43f 100644 --- a/engines/gob/sound/infogrames.cpp +++ b/engines/gob/sound/infogrames.cpp @@ -55,7 +55,7 @@ bool Infogrames::loadSong(const char *fileName) { _mixer->getOutputRate(), _mixer->getOutputRate() / 75); if (!_song->load(fileName)) { - warning("Couldn't load infogrames music"); + warning("Infogrames: Couldn't load music \"%s\"", fileName); clearSong(); return false; } @@ -92,7 +92,7 @@ void Infogrames::clearSong() { bool Infogrames::loadInst(const char *fileName) { _instruments = new Audio::Infogrames::Instruments; if (!_instruments->load(fileName)) { - warning("Couldn't load instruments file"); + warning("Infogrames: Couldn't load instruments \"%s\"", fileName); clearInstruments(); return false; } diff --git a/engines/gob/sound/protracker.cpp b/engines/gob/sound/protracker.cpp index 891580ef40..3e33cfd494 100644 --- a/engines/gob/sound/protracker.cpp +++ b/engines/gob/sound/protracker.cpp @@ -25,6 +25,8 @@ #include "common/file.h" +#include "sound/mods/protracker.h" + #include "gob/sound/protracker.h" namespace Gob { diff --git a/engines/gob/sound/protracker.h b/engines/gob/sound/protracker.h index 6270530427..73cae0d510 100644 --- a/engines/gob/sound/protracker.h +++ b/engines/gob/sound/protracker.h @@ -28,7 +28,6 @@ #include "sound/mixer.h" #include "sound/audiostream.h" -#include "sound/mods/protracker.h" namespace Gob { diff --git a/engines/gob/sound/sound.cpp b/engines/gob/sound/sound.cpp index f0cf17b989..d3afc9baa3 100644 --- a/engines/gob/sound/sound.cpp +++ b/engines/gob/sound/sound.cpp @@ -31,20 +31,28 @@ #include "gob/game.h" #include "gob/inter.h" +#include "gob/sound/pcspeaker.h" +#include "gob/sound/soundblaster.h" +#include "gob/sound/adlib.h" +#include "gob/sound/infogrames.h" +#include "gob/sound/protracker.h" +#include "gob/sound/cdrom.h" + namespace Gob { Sound::Sound(GobEngine *vm) : _vm(vm) { _pcspeaker = new PCSpeaker(*_vm->_mixer); _blaster = new SoundBlaster(*_vm->_mixer); - _adlib = 0; + _adlPlayer = 0; + _mdyPlayer = 0; _infogrames = 0; _protracker = 0; _cdrom = 0; _bgatmos = 0; - if (!_vm->_noMusic && _vm->hasAdlib()) - _adlib = new AdLib(*_vm->_mixer); + _hasAdLib = (!_vm->_noMusic && _vm->hasAdlib()); + if (!_vm->_noMusic && (_vm->getPlatform() == Common::kPlatformAmiga)) { _infogrames = new Infogrames(*_vm->_mixer); _protracker = new Protracker(*_vm->_mixer); @@ -62,7 +70,8 @@ Sound::Sound(GobEngine *vm) : _vm(vm) { Sound::~Sound() { delete _pcspeaker; delete _blaster; - delete _adlib; + delete _adlPlayer; + delete _mdyPlayer; delete _infogrames; delete _protracker; delete _cdrom; @@ -105,14 +114,11 @@ bool Sound::sampleLoad(SoundDesc *sndDesc, SoundType type, const char *fileName, debugC(2, kDebugSound, "Loading sample \"%s\"", fileName); - int16 handle = _vm->_dataIO->openData(fileName); - if (handle < 0) { + if (!_vm->_dataIO->existData(fileName)) { warning("Can't open sample file \"%s\"", fileName); return false; } - _vm->_dataIO->closeData(handle); - byte *data; uint32 size; @@ -121,7 +127,7 @@ bool Sound::sampleLoad(SoundDesc *sndDesc, SoundType type, const char *fileName, return false; size = _vm->_dataIO->getDataSize(fileName); - return sndDesc->load(type, SOUND_FILE, data, size); + return sndDesc->load(type, data, size); } void Sound::sampleFree(SoundDesc *sndDesc, bool noteAdlib, int index) { @@ -130,9 +136,14 @@ void Sound::sampleFree(SoundDesc *sndDesc, bool noteAdlib, int index) { if (sndDesc->getType() == SOUND_ADL) { - if (_adlib && noteAdlib) - if ((index == -1) || (_adlib->getIndex() == index)) - _adlib->stopPlay(); + if (noteAdlib) { + if (_adlPlayer) + if ((index == -1) || (_adlPlayer->getIndex() == index)) + _adlPlayer->stopPlay(); + if (_mdyPlayer) + if ((index == -1) || (_mdyPlayer->getIndex() == index)) + _mdyPlayer->stopPlay(); + } } else { @@ -223,50 +234,112 @@ void Sound::infogramesStop() { _infogrames->stop(); } -bool Sound::adlibLoad(const char *fileName) { - if (!_adlib) +bool Sound::adlibLoadADL(const char *fileName) { + if (!_hasAdLib) return false; - debugC(1, kDebugSound, "Adlib: Loading data (\"%s\")", fileName); + if (!_adlPlayer) + _adlPlayer = new ADLPlayer(*_vm->_mixer); + + debugC(1, kDebugSound, "Adlib: Loading ADL data (\"%s\")", fileName); - return _adlib->load(fileName); + return _adlPlayer->load(fileName); } -bool Sound::adlibLoad(byte *data, uint32 size, int index) { - if (!_adlib) +bool Sound::adlibLoadADL(byte *data, uint32 size, int index) { + if (!_hasAdLib) return false; - debugC(1, kDebugSound, "Adlib: Loading data (%d)", index); + if (!_adlPlayer) + _adlPlayer = new ADLPlayer(*_vm->_mixer); + + debugC(1, kDebugSound, "Adlib: Loading ADL data (%d)", index); - return _adlib->load(data, size, index); + return _adlPlayer->load(data, size, index); } void Sound::adlibUnload() { - if (!_adlib) + if (!_hasAdLib) return; debugC(1, kDebugSound, "Adlib: Unloading data"); - _adlib->unload(); + if (_adlPlayer) + _adlPlayer->unload(); + if (_mdyPlayer) + _mdyPlayer->unload(); +} + +bool Sound::adlibLoadMDY(const char *fileName) { + if (!_hasAdLib) + return false; + + if (!_mdyPlayer) + _mdyPlayer = new MDYPlayer(*_vm->_mixer); + + debugC(1, kDebugSound, "Adlib: Loading MDY data (\"%s\")", fileName); + + if (!_vm->_dataIO->existData(fileName)) { + warning("Can't open MDY file \"%s\"", fileName); + return false; + } + + DataStream *stream = _vm->_dataIO->getDataStream(fileName); + + bool loaded = _mdyPlayer->loadMDY(*stream); + + delete stream; + + return loaded; +} + +bool Sound::adlibLoadTBR(const char *fileName) { + if (!_hasAdLib) + return false; + + if (!_mdyPlayer) + _mdyPlayer = new MDYPlayer(*_vm->_mixer); + + if (!_vm->_dataIO->existData(fileName)) { + warning("Can't open TBR file \"%s\"", fileName); + return false; + } + + debugC(1, kDebugSound, "Adlib: Loading MDY instruments (\"%s\")", fileName); + + DataStream *stream = _vm->_dataIO->getDataStream(fileName); + + bool loaded = _mdyPlayer->loadTBR(*stream); + + delete stream; + + return loaded; } void Sound::adlibPlayTrack(const char *trackname) { - if (!_adlib || _adlib->isPlaying()) + if (!_hasAdLib) return; - debugC(1, kDebugSound, "Adlib: Playing track \"%s\"", trackname); + if (!_adlPlayer) + _adlPlayer = new ADLPlayer(*_vm->_mixer); - _adlib->unload(); - _adlib->load(trackname); - _adlib->startPlay(); + if (_adlPlayer->isPlaying()) + return; + + debugC(1, kDebugSound, "Adlib: Playing ADL track \"%s\"", trackname); + + _adlPlayer->unload(); + _adlPlayer->load(trackname); + _adlPlayer->startPlay(); } void Sound::adlibPlayBgMusic() { - int track; - - if (!_adlib) + if (!_hasAdLib) return; + if (!_adlPlayer) + _adlPlayer = new ADLPlayer(*_vm->_mixer); + static const char *tracksMac[] = { // "musmac1.adl", // TODO: This track isn't played correctly at all yet "musmac2.adl", @@ -285,58 +358,82 @@ void Sound::adlibPlayBgMusic() { }; if (_vm->getPlatform() == Common::kPlatformWindows) { - track = _vm->_util->getRandom(ARRAYSIZE(tracksWin)); + int track = _vm->_util->getRandom(ARRAYSIZE(tracksWin)); adlibPlayTrack(tracksWin[track]); } else { - track = _vm->_util->getRandom(ARRAYSIZE(tracksMac)); + int track = _vm->_util->getRandom(ARRAYSIZE(tracksMac)); adlibPlayTrack(tracksMac[track]); } } void Sound::adlibPlay() { - if (!_adlib) + if (!_hasAdLib) return; debugC(1, kDebugSound, "Adlib: Starting playback"); - _adlib->startPlay(); + if (_adlPlayer) + _adlPlayer->startPlay(); + if (_mdyPlayer) + _mdyPlayer->startPlay(); } void Sound::adlibStop() { - if (!_adlib) + if (!_hasAdLib) return; debugC(1, kDebugSound, "Adlib: Stopping playback"); - _adlib->stopPlay(); + if (_adlPlayer) + _adlPlayer->stopPlay(); + if (_mdyPlayer) + _mdyPlayer->stopPlay(); } bool Sound::adlibIsPlaying() const { - if (!_adlib) + if (!_hasAdLib) return false; - return _adlib->isPlaying(); + if (_adlPlayer && _adlPlayer->isPlaying()) + return true; + if (_mdyPlayer && _mdyPlayer->isPlaying()) + return true; + + return false; } int Sound::adlibGetIndex() const { - if (!_adlib) + if (!_hasAdLib) return -1; - return _adlib->getIndex(); + if (_adlPlayer) + return _adlPlayer->getIndex(); + if (_mdyPlayer) + return _mdyPlayer->getIndex(); + + return -1; } bool Sound::adlibGetRepeating() const { - if (!_adlib) + if (!_hasAdLib) return false; - return _adlib->getRepeating(); + if (_adlPlayer) + return _adlPlayer->getRepeating(); + if (_mdyPlayer) + return _mdyPlayer->getRepeating(); + + return false; } void Sound::adlibSetRepeating(int32 repCount) { - if (!_adlib) + if (!_hasAdLib) return; - _adlib->setRepeating(repCount); + if (_adlPlayer) + _adlPlayer->setRepeating(repCount); + if (_mdyPlayer) + _mdyPlayer->setRepeating(repCount); } void Sound::blasterPlay(SoundDesc *sndDesc, int16 repCount, @@ -425,17 +522,12 @@ void Sound::cdLoadLIC(const char *fname) { debugC(1, kDebugSound, "CDROM: Loading LIC \"%s\"", fname); - int handle = _vm->_dataIO->openData(fname); - - if (handle == -1) + if (!_vm->_dataIO->existData(fname)) return; - _vm->_dataIO->closeData(handle); - _vm->_dataIO->getUnpackedData(fname); - handle = _vm->_dataIO->openData(fname); - DataStream *stream = _vm->_dataIO->openAsStream(handle, true); + DataStream *stream = _vm->_dataIO->getDataStream(fname); _cdrom->readLIC(*stream); diff --git a/engines/gob/sound/sound.h b/engines/gob/sound/sound.h index dbdd580ec7..6f6c1d0469 100644 --- a/engines/gob/sound/sound.h +++ b/engines/gob/sound/sound.h @@ -27,16 +27,19 @@ #define GOB_SOUND_SOUND_H #include "gob/sound/sounddesc.h" -#include "gob/sound/pcspeaker.h" -#include "gob/sound/soundblaster.h" -#include "gob/sound/adlib.h" -#include "gob/sound/infogrames.h" -#include "gob/sound/protracker.h" -#include "gob/sound/cdrom.h" #include "gob/sound/bgatmosphere.h" namespace Gob { +class GobEngine; +class PCSpeaker; +class SoundBlaster; +class ADLPlayer; +class MDYPlayer; +class Infogrames; +class Protracker; +class CDROM; + class Sound { public: static const int kSoundsCount = 60; @@ -77,8 +80,10 @@ public: // AdLib - bool adlibLoad(const char *fileName); - bool adlibLoad(byte *data, uint32 size, int index = -1); + bool adlibLoadADL(const char *fileName); + bool adlibLoadADL(byte *data, uint32 size, int index = -1); + bool adlibLoadMDY(const char *fileName); + bool adlibLoadTBR(const char *fileName); void adlibUnload(); void adlibPlayTrack(const char *trackname); @@ -139,11 +144,14 @@ public: private: GobEngine *_vm; + bool _hasAdLib; + SoundDesc _sounds[kSoundsCount]; PCSpeaker *_pcspeaker; SoundBlaster *_blaster; - AdLib *_adlib; + ADLPlayer *_adlPlayer; + MDYPlayer *_mdyPlayer; Infogrames *_infogrames; Protracker *_protracker; CDROM *_cdrom; diff --git a/engines/gob/sound/soundblaster.cpp b/engines/gob/sound/soundblaster.cpp index 23eea90688..69610dc949 100644 --- a/engines/gob/sound/soundblaster.cpp +++ b/engines/gob/sound/soundblaster.cpp @@ -24,6 +24,7 @@ */ #include "gob/sound/soundblaster.h" +#include "gob/sound/sounddesc.h" namespace Gob { diff --git a/engines/gob/sound/soundblaster.h b/engines/gob/sound/soundblaster.h index c57e4a443e..a2dc87267c 100644 --- a/engines/gob/sound/soundblaster.h +++ b/engines/gob/sound/soundblaster.h @@ -29,11 +29,12 @@ #include "common/mutex.h" #include "sound/mixer.h" -#include "gob/sound/sounddesc.h" #include "gob/sound/soundmixer.h" namespace Gob { +class SoundDesc; + class SoundBlaster : public SoundMixer { public: SoundBlaster(Audio::Mixer &mixer); diff --git a/engines/gob/sound/sounddesc.cpp b/engines/gob/sound/sounddesc.cpp index c4c78eebbd..b9b327d105 100644 --- a/engines/gob/sound/sounddesc.cpp +++ b/engines/gob/sound/sounddesc.cpp @@ -29,15 +29,17 @@ #include "sound/wave.h" #include "gob/sound/sounddesc.h" +#include "gob/resources.h" namespace Gob { SoundDesc::SoundDesc() { + _resource = 0; + _data = _dataPtr = 0; _size = 0; _type = SOUND_SND; - _source = SOUND_FILE; _repCount = 0; _frequency = 0; @@ -50,23 +52,31 @@ SoundDesc::~SoundDesc() { free(); } -void SoundDesc::set(SoundType type, SoundSource src, - byte *data, uint32 dSize) { - +void SoundDesc::set(SoundType type, byte *data, uint32 dSize) { free(); _type = type; - _source = src; _data = _dataPtr = data; _size = dSize; } -bool SoundDesc::load(SoundType type, SoundSource src, - byte *data, uint32 dSize) { +void SoundDesc::set(SoundType type, Resource *resource) { + byte *data = 0; + uint32 dSize = 0; + + if (resource && (resource->getSize() > 0)) { + data = resource->getData(); + dSize = resource->getSize(); + } + + set(type, data, dSize); + _resource = resource; +} + +bool SoundDesc::load(SoundType type, byte *data, uint32 dSize) { free(); - _source = src; switch (type) { case SOUND_ADL: return loadADL(data, dSize); @@ -79,10 +89,28 @@ bool SoundDesc::load(SoundType type, SoundSource src, return false; } +bool SoundDesc::load(SoundType type, Resource *resource) { + if (!resource || (resource->getSize() <= 0)) + return false; + + if (!load(type, resource->getData(), resource->getSize())) + return false; + + _resource = resource; + return true; +} + void SoundDesc::free() { - if (_source != SOUND_TOT) - delete[] _data; - _data = _dataPtr = 0; + if (_resource) { + delete _resource; + _data = 0; + } + + delete[] _data; + + _resource = 0; + _data = 0; + _dataPtr = 0; _id = 0; } diff --git a/engines/gob/sound/sounddesc.h b/engines/gob/sound/sounddesc.h index 83efd61e6d..9e5d20e138 100644 --- a/engines/gob/sound/sounddesc.h +++ b/engines/gob/sound/sounddesc.h @@ -30,18 +30,14 @@ namespace Gob { +class Resource; + enum SoundType { SOUND_SND, SOUND_WAV, SOUND_ADL }; -enum SoundSource { - SOUND_FILE, - SOUND_TOT, - SOUND_EXT -}; - class SoundDesc { public: int16 _repCount; @@ -58,8 +54,11 @@ public: bool isId(int16 id) const { return _dataPtr && (_id == id); } - void set(SoundType type, SoundSource src, byte *data, uint32 dSize); - bool load(SoundType type, SoundSource src, byte *data, uint32 dSize); + void set(SoundType type, byte *data, uint32 dSize); + void set(SoundType type, Resource *resource); + bool load(SoundType type, byte *data, uint32 dSize); + bool load(SoundType type, Resource *resource); + void free(); void convToSigned(); @@ -71,12 +70,12 @@ public: ~SoundDesc(); private: + Resource *_resource; byte *_data; byte *_dataPtr; uint32 _size; SoundType _type; - SoundSource _source; bool loadSND(byte *data, uint32 dSize); bool loadWAV(byte *data, uint32 dSize); diff --git a/engines/gob/sound/soundmixer.cpp b/engines/gob/sound/soundmixer.cpp index ea1dd2ef82..68a96d3b01 100644 --- a/engines/gob/sound/soundmixer.cpp +++ b/engines/gob/sound/soundmixer.cpp @@ -24,6 +24,7 @@ */ #include "gob/sound/soundmixer.h" +#include "gob/sound/sounddesc.h" namespace Gob { diff --git a/engines/gob/sound/soundmixer.h b/engines/gob/sound/soundmixer.h index f32beb149f..20376b5152 100644 --- a/engines/gob/sound/soundmixer.h +++ b/engines/gob/sound/soundmixer.h @@ -31,10 +31,10 @@ #include "sound/audiostream.h" #include "sound/mixer.h" -#include "gob/sound/sounddesc.h" - namespace Gob { +class SoundDesc; + class SoundMixer : public Audio::AudioStream { public: SoundMixer(Audio::Mixer &mixer, Audio::Mixer::SoundType type); diff --git a/engines/gob/totfile.cpp b/engines/gob/totfile.cpp new file mode 100644 index 0000000000..bbf62c143b --- /dev/null +++ b/engines/gob/totfile.cpp @@ -0,0 +1,135 @@ +/* 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. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "common/str.h" +#include "common/stream.h" + +#include "gob/gob.h" +#include "gob/totfile.h" +#include "gob/dataio.h" +#include "gob/videoplayer.h" + +namespace Gob { + +TOTFile::TOTFile(GobEngine *vm) : _vm(vm) { + _stream = 0; + + memset(_header, 0, 128); +} + +TOTFile::~TOTFile() { + unload(); +} + +bool TOTFile::load(const Common::String &fileName) { + // Trying to open normally + _stream = _vm->_dataIO->getDataStream(fileName.c_str()); + + if (!_stream) + // Trying to open from video + _stream = _vm->_vidPlayer->getExtraData(fileName.c_str()); + + if (!_stream) + return false; + + if (_stream->read(_header, 128) != 128) + return false; + + _stream->seek(0); + + return true; +} + +void TOTFile::unload() { + delete _stream; + + _stream = 0; +} + +Common::SeekableReadStream *TOTFile::getStream() const { + return _stream; +} + +bool TOTFile::getProperties(Properties &props) const { + if (!_stream) + return false; + + // Offset 39-41: Version in "Major.Minor" string form + if (_header[40] != '.') + return false; + + props.versionMajor = _header[39] - '0'; + props.versionMinor = _header[41] - '0'; + + props.variablesCount = READ_LE_UINT32(_header + 44); + + props.textsOffset = READ_LE_UINT32(_header + 48); + props.resourcesOffset = READ_LE_UINT32(_header + 52); + + props.animDataSize = READ_LE_UINT16(_header + 56); + + props.imFileNumber = _header[59]; + props.exFileNumber = _header[60]; + props.communHandling = _header[61]; + + for (int i = 0; i < 14; i++) + props.functions[i] = READ_LE_UINT16(_header + 100 + i * 2); + + props.scriptEnd = _stream->size(); + if (props.textsOffset > 0) + props.scriptEnd = MIN(props.scriptEnd, props.textsOffset); + if (props.resourcesOffset > 0) + props.scriptEnd = MIN(props.scriptEnd, props.resourcesOffset); + + return true; +} + +Common::String TOTFile::createFileName(const Common::String &base, bool &isLOM) { + isLOM = false; + + const char *dot; + if ((dot = strrchr(base.c_str(), '.'))) { + // fileName includes an extension + + if (!scumm_stricmp(dot + 1, "LOM")) + isLOM = true; + + return base; + } + + return base + ".tot"; +} + +Common::String TOTFile::getFileBase(const Common::String &fileName) { + const char *dot; + if ((dot = strrchr(fileName.c_str(), '.'))) { + // fileName includes an extension + return Common::String(fileName.c_str(), dot); + } + + return fileName; +} + +} // End of namespace Gob diff --git a/engines/gob/totfile.h b/engines/gob/totfile.h new file mode 100644 index 0000000000..00963d36a2 --- /dev/null +++ b/engines/gob/totfile.h @@ -0,0 +1,80 @@ +/* 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. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef GOB_TOTFILE_H +#define GOB_TOTFILE_H + +#include "common/str.h" + +namespace Common { + class SeekableReadStream; +} + +namespace Gob { + +class TOTFile { +public: + enum Function { + kFunctionStart = 0, + kFunctionCenter = 13 + }; + + struct Properties { + uint8 versionMajor; + uint8 versionMinor; + uint32 variablesCount; + uint32 textsOffset; + uint32 resourcesOffset; + uint16 animDataSize; + uint8 imFileNumber; + uint8 exFileNumber; + uint8 communHandling; + uint16 functions[14]; + uint32 scriptEnd; + }; + + TOTFile(GobEngine *vm); + ~TOTFile(); + + bool load(const Common::String &fileName); + void unload(); + + Common::SeekableReadStream *getStream() const; + bool getProperties(Properties &props) const; + + static Common::String createFileName(const Common::String &base, bool &isLOM); + static Common::String getFileBase(const Common::String &fileName); + +private: + GobEngine *_vm; + + Common::SeekableReadStream *_stream; + + byte _header[128]; +}; + +} // End of namespace Gob + +#endif // GOB_TOTFILE_H diff --git a/engines/gob/util.cpp b/engines/gob/util.cpp index e1148dacb9..b0e7691c07 100644 --- a/engines/gob/util.cpp +++ b/engines/gob/util.cpp @@ -331,6 +331,12 @@ void Util::setFrameRate(int16 rate) { _frameRate = rate; _frameWaitTime = 1000 / rate; _startFrameTime = getTimeKey(); + _frameWaitLag = 0; +} + +void Util::notifyNewAnim() { + _startFrameTime = getTimeKey(); + _frameWaitLag = 0; } void Util::waitEndFrame() { diff --git a/engines/gob/util.h b/engines/gob/util.h index 3d7520fe69..0a76ee40ab 100644 --- a/engines/gob/util.h +++ b/engines/gob/util.h @@ -76,6 +76,7 @@ public: void clearPalette(void); int16 getFrameRate(); void setFrameRate(int16 rate); + void notifyNewAnim(); void waitEndFrame(); void setScrollOffset(int16 x = -1, int16 y = -1); diff --git a/engines/gob/videoplayer.cpp b/engines/gob/videoplayer.cpp index e82805d6ac..6c07d22333 100644 --- a/engines/gob/videoplayer.cpp +++ b/engines/gob/videoplayer.cpp @@ -201,15 +201,11 @@ bool VideoPlayer::findFile(char *fileName, Type &which) { int i; for (i = 0; i < ARRAYSIZE(_extensions); i++) { if ((which == kVideoTypeTry) || (which == ((Type) i))) { - int16 handle; - fileName[len] = '.'; fileName[len + 1] = 0; strcat(fileName, _extensions[i]); - handle = _vm->_dataIO->openData(fileName); - if (handle >= 0) { - _vm->_dataIO->closeData(handle); + if (_vm->_dataIO->existData(fileName)) { which = (Type) i; break; } |