diff options
Diffstat (limited to 'engines/hugo')
-rw-r--r-- | engines/hugo/display.cpp | 15 | ||||
-rw-r--r-- | engines/hugo/display.h | 3 | ||||
-rw-r--r-- | engines/hugo/file.cpp | 27 | ||||
-rw-r--r-- | engines/hugo/hugo.cpp | 316 | ||||
-rw-r--r-- | engines/hugo/hugo.h | 27 | ||||
-rw-r--r-- | engines/hugo/intro.cpp | 45 | ||||
-rw-r--r-- | engines/hugo/intro.h | 11 | ||||
-rw-r--r-- | engines/hugo/inventory.cpp | 41 | ||||
-rw-r--r-- | engines/hugo/inventory.h | 8 | ||||
-rw-r--r-- | engines/hugo/object.cpp | 100 | ||||
-rw-r--r-- | engines/hugo/object.h | 4 | ||||
-rw-r--r-- | engines/hugo/parser.cpp | 148 | ||||
-rw-r--r-- | engines/hugo/parser.h | 17 | ||||
-rw-r--r-- | engines/hugo/parser_v1d.cpp | 18 | ||||
-rw-r--r-- | engines/hugo/parser_v1w.cpp | 8 | ||||
-rw-r--r-- | engines/hugo/parser_v2d.cpp | 10 | ||||
-rw-r--r-- | engines/hugo/parser_v3d.cpp | 20 | ||||
-rw-r--r-- | engines/hugo/schedule.cpp | 155 | ||||
-rw-r--r-- | engines/hugo/schedule.h | 29 |
19 files changed, 546 insertions, 456 deletions
diff --git a/engines/hugo/display.cpp b/engines/hugo/display.cpp index 0c076f229e..9ee7715608 100644 --- a/engines/hugo/display.cpp +++ b/engines/hugo/display.cpp @@ -599,17 +599,12 @@ void Screen::loadPalette(Common::ReadStream &in) { } /** - * Free main and current palettes + * Free fonts, main and current palettes */ -void Screen::freePalette() { +void Screen::freeScreen() { free(_curPalette); free(_mainPalette); -} -/** - * Free fonts - */ -void Screen::freeFonts() { for (int i = 0; i < kNumFonts; i++) { if (_arrayFont[i]) free(_arrayFont[i]); @@ -621,11 +616,7 @@ void Screen::selectInventoryObjId(const int16 objId) { _vm->_inventory->setInventoryObjId(objId); // Select new object // Find index of icon - int16 iconId = 0; // Find index of dragged icon - for (; iconId < _vm->_maxInvent; iconId++) { - if (objId == _vm->_invent[iconId]) - break; - } + int16 iconId = _vm->_inventory->findIconId(objId); // Compute source coordinates in dib_u int16 ux = (iconId + kArrowNumb) * kInvDx % kXPix; diff --git a/engines/hugo/display.h b/engines/hugo/display.h index 21e9fe2e9c..b5a3c763bc 100644 --- a/engines/hugo/display.h +++ b/engines/hugo/display.h @@ -65,8 +65,7 @@ public: void drawRectangle(const bool filledFl, const int16 x1, const int16 y1, const int16 x2, const int16 y2, const int color); void drawShape(const int x, const int y, const int color1, const int color2); void drawStatusText(); - void freeFonts(); - void freePalette(); + void freeScreen(); void hideCursor(); void initDisplay(); void initNewScreenDisplay(); diff --git a/engines/hugo/file.cpp b/engines/hugo/file.cpp index 7427771906..a0602f0636 100644 --- a/engines/hugo/file.cpp +++ b/engines/hugo/file.cpp @@ -369,18 +369,7 @@ bool FileManager::saveGame(const int16 slot, const Common::String &descrip) { for (int i = 0; i < _vm->_numScreens; i++) out->writeByte(_vm->_screenStates[i]); - // Save points table - for (int i = 0; i < _vm->_numBonuses; i++) { - out->writeByte(_vm->_points[i].score); - out->writeByte((_vm->_points[i].scoredFl) ? 1 : 0); - } - - // Now save current time and all current events in event queue - _vm->_scheduler->saveEvents(out); - - // Now save current actions - _vm->_scheduler->saveActions(out); - + _vm->_scheduler->saveSchedulerData(out); // Save palette table _vm->_screen->savePal(out); @@ -475,19 +464,7 @@ bool FileManager::restoreGame(const int16 slot) { for (int i = 0; i < _vm->_numScreens; i++) _vm->_screenStates[i] = in->readByte(); - // Restore points table - for (int i = 0; i < _vm->_numBonuses; i++) { - _vm->_points[i].score = in->readByte(); - _vm->_points[i].scoredFl = (in->readByte() == 1); - } - - _vm->_object->restoreAllSeq(); - - // Now restore time of the save and the event queue - _vm->_scheduler->restoreEvents(in); - - // Now restore actions - _vm->_scheduler->restoreActions(in); + _vm->_scheduler->restoreSchedulerData(in); // Restore palette and change it if necessary _vm->_screen->restorePal(in); diff --git a/engines/hugo/hugo.cpp b/engines/hugo/hugo.cpp index 4a8b74fc1c..9f64db83ff 100644 --- a/engines/hugo/hugo.cpp +++ b/engines/hugo/hugo.cpp @@ -54,10 +54,8 @@ maze_t _maze; // Default to not in maze hugo_boot_t _boot; // Boot info structure file HugoEngine::HugoEngine(OSystem *syst, const HugoGameDescription *gd) : Engine(syst), _gameDescription(gd), - _arrayReqs(0), _invent(0), _uses(0), _catchallList(0), _backgroundObjects(0), _points(0), _cmdList(0), - _screenActs(0), _hero(0), _heroImage(0), _defltTunes(0), _introX(0), _introY(0), _maxInvent(0), _numBonuses(0), - _numScreens(0), _tunesNbr(0), _soundSilence(0), _soundTest(0), _screenStates(0), _score(0), _maxscore(0), - _backgroundObjectsSize(0), _screenActsSize(0), _usesSize(0), _lastTime(0), _curTime(0) + _hero(0), _heroImage(0), _defltTunes(0), _numScreens(0), _tunesNbr(0), _soundSilence(0), _soundTest(0), + _screenStates(0), _score(0), _maxscore(0), _lastTime(0), _curTime(0) { _system = syst; DebugMan.addDebugChannel(kDebugSchedule, "Schedule", "Script Schedule debug level"); @@ -76,61 +74,22 @@ HugoEngine::HugoEngine(OSystem *syst, const HugoGameDescription *gd) : Engine(sy } HugoEngine::~HugoEngine() { - shutdown(); - - _screen->freePalette(); - _text->freeAllTexts(); - - free(_introX); - free(_introY); - - if (_arrayReqs) { - for (int i = 0; _arrayReqs[i] != 0; i++) - free(_arrayReqs[i]); - free(_arrayReqs); - } + _file->closeDatabaseFiles(); + _intro->freeIntroData(); + _inventory->freeInvent(); _mouse->freeHotspots(); - free(_invent); - - if (_uses) { - for (int i = 0; i < _usesSize; i++) - free(_uses[i].targets); - free(_uses); - } - - free(_catchallList); - - if (_backgroundObjects) { - for (int i = 0; i < _backgroundObjectsSize; i++) - free(_backgroundObjects[i]); - free(_backgroundObjects); - } - - free(_points); - - if (_cmdList) { - for (int i = 0; i < _cmdListSize; i++) - free(_cmdList[i]); - free(_cmdList); - } - - if (_screenActs) { - for (int i = 0; i < _screenActsSize; i++) - free(_screenActs[i]); - free(_screenActs); - } - - _object->freeObjectArr(); - _scheduler->freeActListArr(); + _object->freeObjects(); + _parser->freeParser(); + _scheduler->freeScheduler(); + _screen->freeScreen(); + _text->freeAllTexts(); free(_defltTunes); free(_screenStates); - _screen->freeFonts(); delete _topMenu; - delete _object; delete _sound; delete _route; @@ -236,11 +195,12 @@ Common::Error HugoEngine::run() { _screen->setCursorPal(); _screen->resetInventoryObjId(); + _scheduler->initCypher(); + initStatus(); // Initialize game status initConfig(); // Initialize user's config initialize(); resetConfig(); // Reset user's config - initMachine(); // Start the state machine @@ -388,207 +348,23 @@ bool HugoEngine::loadHugoDat() { } _numVariant = in.readUint16BE(); + _screen->loadPalette(in); _text->loadAllTexts(in); - - // Read x_intro and y_intro - for (int varnt = 0; varnt < _numVariant; varnt++) { - int numRows = in.readUint16BE(); - if (varnt == _gameVariant) { - _introXSize = numRows; - _introX = (byte *)malloc(sizeof(byte) * _introXSize); - _introY = (byte *)malloc(sizeof(byte) * _introXSize); - for (int i = 0; i < _introXSize; i++) { - _introX[i] = in.readByte(); - _introY[i] = in.readByte(); - } - } else { - for (int i = 0; i < numRows; i++) { - in.readByte(); - in.readByte(); - } - } - } - - // Read _arrayReqs - _arrayReqs = loadLongArray(in); - + _intro->loadIntroData(in); + _parser->loadArrayReqs(in); _mouse->loadHotspots(in); - - int numElem, numSubElem; - //Read _invent - for (int varnt = 0; varnt < _numVariant; varnt++) { - numElem = in.readUint16BE(); - if (varnt == _gameVariant) { - _maxInvent = numElem; - _invent = (int16 *)malloc(sizeof(int16) * numElem); - for (int i = 0; i < numElem; i++) - _invent[i] = in.readSint16BE(); - } else { - for (int i = 0; i < numElem; i++) - in.readSint16BE(); - } - } - - //Read _uses - for (int varnt = 0; varnt < _numVariant; varnt++) { - numElem = in.readUint16BE(); - uses_t *wrkUses = (uses_t *)malloc(sizeof(uses_t) * numElem); - - for (int i = 0; i < numElem; i++) { - wrkUses[i].objId = in.readSint16BE(); - wrkUses[i].dataIndex = in.readUint16BE(); - numSubElem = in.readUint16BE(); - wrkUses[i].targets = (target_t *)malloc(sizeof(target_t) * numSubElem); - for (int j = 0; j < numSubElem; j++) { - wrkUses[i].targets[j].nounIndex = in.readUint16BE(); - wrkUses[i].targets[j].verbIndex = in.readUint16BE(); - } - } - - if (varnt == _gameVariant) { - _usesSize = numElem; - _uses = wrkUses; - } else { - for (int i = 0; i < numElem; i++) - free(wrkUses[i].targets); - free(wrkUses); - } - } - - //Read _catchallList - for (int varnt = 0; varnt < _numVariant; varnt++) { - numElem = in.readUint16BE(); - background_t *wrkCatchallList = (background_t *)malloc(sizeof(background_t) * numElem); - - for (int i = 0; i < numElem; i++) { - wrkCatchallList[i].verbIndex = in.readUint16BE(); - wrkCatchallList[i].nounIndex = in.readUint16BE(); - wrkCatchallList[i].commentIndex = in.readSint16BE(); - wrkCatchallList[i].matchFl = (in.readByte() != 0); - wrkCatchallList[i].roomState = in.readByte(); - wrkCatchallList[i].bonusIndex = in.readByte(); - } - - if (varnt == _gameVariant) - _catchallList = wrkCatchallList; - else - free(wrkCatchallList); - } - - // Read _background_objects - for (int varnt = 0; varnt < _numVariant; varnt++) { - numElem = in.readUint16BE(); - - background_t **wrkBackgroundObjects = (background_t **)malloc(sizeof(background_t *) * numElem); - - for (int i = 0; i < numElem; i++) { - numSubElem = in.readUint16BE(); - wrkBackgroundObjects[i] = (background_t *)malloc(sizeof(background_t) * numSubElem); - for (int j = 0; j < numSubElem; j++) { - wrkBackgroundObjects[i][j].verbIndex = in.readUint16BE(); - wrkBackgroundObjects[i][j].nounIndex = in.readUint16BE(); - wrkBackgroundObjects[i][j].commentIndex = in.readSint16BE(); - wrkBackgroundObjects[i][j].matchFl = (in.readByte() != 0); - wrkBackgroundObjects[i][j].roomState = in.readByte(); - wrkBackgroundObjects[i][j].bonusIndex = in.readByte(); - } - } - - if (varnt == _gameVariant) { - _backgroundObjectsSize = numElem; - _backgroundObjects = wrkBackgroundObjects; - } else { - for (int i = 0; i < numElem; i++) - free(wrkBackgroundObjects[i]); - free(wrkBackgroundObjects); - } - } - - // Read _points - for (int varnt = 0; varnt < _numVariant; varnt++) { - numElem = in.readUint16BE(); - if (varnt == _gameVariant) { - _numBonuses = numElem; - _points = (point_t *)malloc(sizeof(point_t) * _numBonuses); - for (int i = 0; i < _numBonuses; i++) { - _points[i].score = in.readByte(); - _points[i].scoredFl = false; - } - } else { - for (int i = 0; i < numElem; i++) - in.readByte(); - } - } - - // Read _cmdList - for (int varnt = 0; varnt < _numVariant; varnt++) { - numElem = in.readUint16BE(); - if (varnt == _gameVariant) { - _cmdListSize = numElem; - _cmdList = (cmd **)malloc(sizeof(cmd *) * _cmdListSize); - for (int i = 0; i < _cmdListSize; i++) { - numSubElem = in.readUint16BE(); - _cmdList[i] = (cmd *)malloc(sizeof(cmd) * numSubElem); - for (int j = 0; j < numSubElem; j++) { - _cmdList[i][j].verbIndex = in.readUint16BE(); - _cmdList[i][j].reqIndex = in.readUint16BE(); - _cmdList[i][j].textDataNoCarryIndex = in.readUint16BE(); - _cmdList[i][j].reqState = in.readByte(); - _cmdList[i][j].newState = in.readByte(); - _cmdList[i][j].textDataWrongIndex = in.readUint16BE(); - _cmdList[i][j].textDataDoneIndex = in.readUint16BE(); - _cmdList[i][j].actIndex = in.readUint16BE(); - } - } - } else { - for (int i = 0; i < numElem; i++) { - numSubElem = in.readUint16BE(); - for (int j = 0; j < numSubElem; j++) { - in.readUint16BE(); - in.readUint16BE(); - in.readUint16BE(); - in.readByte(); - in.readByte(); - in.readUint16BE(); - in.readUint16BE(); - in.readUint16BE(); - } - } - } - } - - // Read _screenActs - for (int varnt = 0; varnt < _numVariant; varnt++) { - numElem = in.readUint16BE(); - - uint16 **wrkScreenActs = (uint16 **)malloc(sizeof(uint16 *) * numElem); - for (int i = 0; i < numElem; i++) { - numSubElem = in.readUint16BE(); - if (numSubElem == 0) { - wrkScreenActs[i] = 0; - } else { - wrkScreenActs[i] = (uint16 *)malloc(sizeof(uint16) * numSubElem); - for (int j = 0; j < numSubElem; j++) - wrkScreenActs[i][j] = in.readUint16BE(); - } - } - - if (varnt == _gameVariant) { - _screenActsSize = numElem; - _screenActs = wrkScreenActs; - } else { - for (int i = 0; i < numElem; i++) - free(wrkScreenActs[i]); - free(wrkScreenActs); - } - } + _inventory->loadInvent(in); + _object->loadObjectUses(in); + _parser->loadCatchallList(in); + _parser->loadBackgroundObjects(in); + _scheduler->loadPoints(in); + _parser->loadCmdList(in); + _scheduler->loadScreenAct(in); _object->loadObjectArr(in); - _hero = &_object->_objects[kHeroIndex]; // This always points to hero _screen_p = &(_object->_objects[kHeroIndex].screenIndex); // Current screen is hero's _heroImage = kHeroIndex; // Current in use hero image - _scheduler->loadActListArr(in); for (int varnt = 0; varnt < _numVariant; varnt++) { @@ -603,6 +379,8 @@ bool HugoEngine::loadHugoDat() { } } + int numElem; + //Read _defltTunes for (int varnt = 0; varnt < _numVariant; varnt++) { numElem = in.readUint16BE(); @@ -792,16 +570,6 @@ void HugoEngine::initialize() { } /** - * Restore all resources before termination - */ -void HugoEngine::shutdown() { - debugC(1, kDebugEngine, "shutdown"); - - _file->closeDatabaseFiles(); - _object->freeObjects(); -} - -/** * Read scenery, overlay files for given screen number */ void HugoEngine::readScreenFiles(const int screenNum) { @@ -820,37 +588,6 @@ void HugoEngine::readScreenFiles(const int screenNum) { } /** - * Search background command list for this screen for supplied object. - * Return first associated verb (not "look") or 0 if none found. - */ -const char *HugoEngine::useBG(const char *name) { - debugC(1, kDebugEngine, "useBG(%s)", name); - - objectList_t p = _backgroundObjects[*_screen_p]; - for (int i = 0; p[i].verbIndex != 0; i++) { - if ((name == _text->getNoun(p[i].nounIndex, 0) && - p[i].verbIndex != _look) && - ((p[i].roomState == kStateDontCare) || (p[i].roomState == _screenStates[*_screen_p]))) - return _text->getVerb(p[i].verbIndex, 0); - } - - return 0; -} - -/** - * Add action lists for this screen to event queue - */ -void HugoEngine::screenActions(const int screenNum) { - debugC(1, kDebugEngine, "screenActions(%d)", screenNum); - - uint16 *screenAct = _screenActs[screenNum]; - if (screenAct) { - for (int i = 0; screenAct[i]; i++) - _scheduler->insertActionList(screenAct[i]); - } -} - -/** * Set the new screen number into the hero object and any carried objects */ void HugoEngine::setNewScreen(const int screenNum) { @@ -866,10 +603,7 @@ void HugoEngine::setNewScreen(const int screenNum) { void HugoEngine::calcMaxScore() { debugC(1, kDebugEngine, "calcMaxScore"); - _maxscore = _object->calcMaxScore(); - - for (int i = 0; i < _numBonuses; i++) - _maxscore += _points[i].score; + _maxscore = _object->calcMaxScore() + _scheduler->calcMaxPoints(); } /** diff --git a/engines/hugo/hugo.h b/engines/hugo/hugo.h index b73b24eccf..7c12fcd2ee 100644 --- a/engines/hugo/hugo.h +++ b/engines/hugo/hugo.h @@ -233,8 +233,6 @@ public: byte _numVariant; byte _gameVariant; - byte _maxInvent; - byte _numBonuses; int8 _soundSilence; int8 _soundTest; int8 _tunesNbr; @@ -245,23 +243,9 @@ public: byte *_screen_p; byte _heroImage; - byte *_introX; - byte *_introY; byte *_screenStates; command_t _line; // Line of user text input config_t _config; // User's config - uint16 **_arrayReqs; - int16 *_invent; - uses_t *_uses; - uint16 _usesSize; - background_t *_catchallList; - background_t **_backgroundObjects; - uint16 _backgroundObjectsSize; - point_t *_points; - cmd **_cmdList; - uint16 _cmdListSize; - uint16 **_screenActs; - uint16 _screenActsSize; int16 *_defltTunes; uint16 _look; uint16 _take; @@ -295,8 +279,6 @@ public: virtual bool canSaveGameStateCurrently(); bool loadHugoDat(); - const char *useBG(const char *name); - int8 getTPS() const; void initGame(const HugoGameDescription *gd); @@ -304,7 +286,6 @@ public: void endGame(); void initStatus(); void readScreenFiles(const int screen); - void screenActions(const int screen); void setNewScreen(const int screen); void shutdown(); void syncSoundSettings(); @@ -327,9 +308,6 @@ public: void setMaxScore(const int newScore) { _maxscore = newScore; } - byte getIntroSize() { - return _introXSize; - } Common::Error saveGameState(int slot, const char *desc) { return (_file->saveGame(slot, desc) ? Common::kWritingFailed : Common::kNoError); } @@ -345,6 +323,7 @@ public: const char *getCopyrightString() const { return "Copyright 1989-1997 David P Gray, All Rights Reserved."; } Common::String getSavegameFilename(int slot); + uint16 **loadLongArray(Common::ReadStream &in); FileManager *_file; Scheduler *_scheduler; @@ -357,7 +336,6 @@ public: IntroHandler *_intro; ObjectHandler *_object; TextHandler *_text; - TopMenu *_topMenu; protected: @@ -368,7 +346,6 @@ protected: private: static const int kTurboTps = 16; // This many in turbo mode - byte _introXSize; status_t _status; // Game status structure uint32 _lastTime; uint32 _curTime; @@ -384,8 +361,6 @@ private: int _score; // Holds current score int _maxscore; // Holds maximum score - uint16 **loadLongArray(Common::ReadStream &in); - void initPlaylist(bool playlist[kMaxTunes]); void initConfig(); void initialize(); diff --git a/engines/hugo/intro.cpp b/engines/hugo/intro.cpp index 02fb94c83d..4ee46f80b5 100644 --- a/engines/hugo/intro.cpp +++ b/engines/hugo/intro.cpp @@ -41,12 +41,41 @@ namespace Hugo { -IntroHandler::IntroHandler(HugoEngine *vm) : _vm(vm) { +IntroHandler::IntroHandler(HugoEngine *vm) : _vm(vm), _introX(0), _introY(0) { + _introXSize = 0; } IntroHandler::~IntroHandler() { } +/** + * Read _introX and _introY from hugo.dat + */ +void IntroHandler::loadIntroData(Common::ReadStream &in) { + for (int varnt = 0; varnt < _vm->_numVariant; varnt++) { + int numRows = in.readUint16BE(); + if (varnt == _vm->_gameVariant) { + _introXSize = numRows; + _introX = (byte *)malloc(sizeof(byte) * _introXSize); + _introY = (byte *)malloc(sizeof(byte) * _introXSize); + for (int i = 0; i < _introXSize; i++) { + _introX[i] = in.readByte(); + _introY[i] = in.readByte(); + } + } else { + for (int i = 0; i < numRows; i++) { + in.readByte(); + in.readByte(); + } + } + } +} + +void IntroHandler::freeIntroData() { + free(_introX); + free(_introY); +} + intro_v1d::intro_v1d(HugoEngine *vm) : IntroHandler(vm) { } @@ -68,7 +97,7 @@ void intro_v1d::introInit() { } bool intro_v1d::introPlay() { - byte introSize = _vm->getIntroSize(); + byte introSize = getIntroSize(); if (_vm->getGameStatus().skipIntroFl) return true; @@ -296,8 +325,8 @@ bool intro_v3d::introPlay() { if (_vm->getGameStatus().skipIntroFl) return true; - if (introTicks < _vm->getIntroSize()) { - font.drawString(&surf, ".", _vm->_introX[introTicks], _vm->_introY[introTicks] - kDibOffY, 320, _TBRIGHTWHITE); + if (introTicks < getIntroSize()) { + font.drawString(&surf, ".", _introX[introTicks], _introY[introTicks] - kDibOffY, 320, _TBRIGHTWHITE); _vm->_screen->displayBackground(); // Text boxes at various times @@ -314,7 +343,7 @@ bool intro_v3d::introPlay() { } } - return (++introTicks >= _vm->getIntroSize()); + return (++introTicks >= getIntroSize()); } intro_v1w::intro_v1w(HugoEngine *vm) : IntroHandler(vm) { @@ -387,9 +416,9 @@ bool intro_v3w::introPlay() { if (_vm->getGameStatus().skipIntroFl) return true; - if (introTicks < _vm->getIntroSize()) { + if (introTicks < getIntroSize()) { // Scale viewport x_intro,y_intro to screen (offsetting y) - _vm->_screen->writeStr(_vm->_introX[introTicks], _vm->_introY[introTicks] - kDibOffY, "x", _TBRIGHTWHITE); + _vm->_screen->writeStr(_introX[introTicks], _introY[introTicks] - kDibOffY, "x", _TBRIGHTWHITE); _vm->_screen->displayBackground(); // Text boxes at various times @@ -406,6 +435,6 @@ bool intro_v3w::introPlay() { } } - return (++introTicks >= _vm->getIntroSize()); + return (++introTicks >= getIntroSize()); } } // End of namespace Hugo diff --git a/engines/hugo/intro.h b/engines/hugo/intro.h index 37c846fc10..351352554e 100644 --- a/engines/hugo/intro.h +++ b/engines/hugo/intro.h @@ -54,9 +54,18 @@ public: virtual void introInit() = 0; virtual bool introPlay() = 0; + void freeIntroData(); + void loadIntroData(Common::ReadStream &in); + + byte getIntroSize() const { return _introXSize; } + protected: HugoEngine *_vm; - int16 introTicks; // Count calls to introPlay() + + byte *_introX; + byte *_introY; + byte _introXSize; + int16 introTicks; // Count calls to introPlay() }; class intro_v1w : public IntroHandler { diff --git a/engines/hugo/inventory.cpp b/engines/hugo/inventory.cpp index 4bf107575e..a45df7e077 100644 --- a/engines/hugo/inventory.cpp +++ b/engines/hugo/inventory.cpp @@ -46,11 +46,30 @@ namespace Hugo { static const int kMaxDisp = (kXPix / kInvDx); // Max icons displayable -InventoryHandler::InventoryHandler(HugoEngine *vm) : _vm(vm) { +InventoryHandler::InventoryHandler(HugoEngine *vm) : _vm(vm), _invent(0) { _firstIconId = 0; _inventoryState = kInventoryOff; // Inventory icon bar state _inventoryHeight = 0; // Inventory icon bar pos _inventoryObjId = -1; // Inventory object selected (none) + _maxInvent = 0; +} + +/** + * Read _invent from Hugo.dat + */ +void InventoryHandler::loadInvent(Common::ReadStream &in) { + for (int varnt = 0; varnt < _vm->_numVariant; varnt++) { + int16 numElem = in.readUint16BE(); + if (varnt == _vm->_gameVariant) { + _maxInvent = numElem; + _invent = (int16 *)malloc(sizeof(int16) * numElem); + for (int i = 0; i < numElem; i++) + _invent[i] = in.readSint16BE(); + } else { + for (int i = 0; i < numElem; i++) + in.readSint16BE(); + } + } } /** @@ -78,7 +97,7 @@ void InventoryHandler::constructInventory(const int16 imageTotNumb, int displayN int16 displayed = 0; int16 carried = 0; for (int16 i = 0; (i < imageTotNumb) && (displayed < displayNumb); i++) { - if (_vm->_object->isCarried(_vm->_invent[i])) { + if (_vm->_object->isCarried(_invent[i])) { // Check still room to display and past first scroll index if (displayed < displayNumb && carried >= firstObjId) { // Compute source coordinates in dib_u @@ -107,8 +126,8 @@ int16 InventoryHandler::processInventory(const invact_t action, ...) { int16 imageNumb; // Total number of inventory items int displayNumb; // Total number displayed/carried // Compute total number and number displayed, i.e. number carried - for (imageNumb = 0, displayNumb = 0; imageNumb < _vm->_maxInvent && _vm->_invent[imageNumb] != -1; imageNumb++) { - if (_vm->_object->isCarried(_vm->_invent[imageNumb])) + for (imageNumb = 0, displayNumb = 0; imageNumb < _maxInvent && _invent[imageNumb] != -1; imageNumb++) { + if (_vm->_object->isCarried(_invent[imageNumb])) displayNumb++; } @@ -236,4 +255,18 @@ void InventoryHandler::runInventory() { } } + +/** + * Find index of dragged icon + */ +int16 InventoryHandler::findIconId(int16 objId) { + int16 iconId = 0; + for (; iconId < _maxInvent; iconId++) { + if (objId == _invent[iconId]) + break; + } + + return iconId; +} + } // End of namespace Hugo diff --git a/engines/hugo/inventory.h b/engines/hugo/inventory.h index deb22cf9aa..8d60904c6f 100644 --- a/engines/hugo/inventory.h +++ b/engines/hugo/inventory.h @@ -45,11 +45,15 @@ public: void setInventoryObjId(int16 objId) { _inventoryObjId = objId; } void setInventoryState(istate_t state) { _inventoryState = state; } + void freeInvent() { free(_invent); } + int16 getInventoryObjId() const { return _inventoryObjId; } istate_t getInventoryState() const { return _inventoryState; } + int16 findIconId(int16 objId); + void loadInvent(Common::ReadStream &in); int16 processInventory(const invact_t action, ...); - void runInventory(); + void runInventory(); private: HugoEngine *_vm; @@ -57,9 +61,11 @@ private: static const int kStepDy = 8; // Pixels per step movement int16 _firstIconId; // Index of first icon to display + int16 *_invent; istate_t _inventoryState; // Inventory icon bar state int16 _inventoryHeight; // Inventory icon bar height int16 _inventoryObjId; // Inventory object selected, or -1 + byte _maxInvent; void constructInventory(const int16 imageTotNumb, int displayNumb, const bool scrollFl, int16 firstObjId); }; diff --git a/engines/hugo/object.cpp b/engines/hugo/object.cpp index b909df45bb..786ea4762a 100644 --- a/engines/hugo/object.cpp +++ b/engines/hugo/object.cpp @@ -48,9 +48,10 @@ namespace Hugo { -ObjectHandler::ObjectHandler(HugoEngine *vm) : _vm(vm), _objects(0) { +ObjectHandler::ObjectHandler(HugoEngine *vm) : _vm(vm), _objects(0), _uses(0) { _numObj = 0; _objCount = 0; + _usesSize = 0; memset(_objBound, '\0', sizeof(overlay_t)); memset(_boundary, '\0', sizeof(overlay_t)); memset(_overlay, '\0', sizeof(overlay_t)); @@ -108,20 +109,20 @@ void ObjectHandler::useObject(int16 objId) { if ((obj->genericCmd & TAKE) || obj->objValue) // Get collectible item sprintf(_vm->_line, "%s %s", _vm->_text->getVerb(_vm->_take, 0), _vm->_text->getNoun(obj->nounIndex, 0)); else if (obj->cmdIndex != 0) // Use non-collectible item if able - sprintf(_vm->_line, "%s %s", _vm->_text->getVerb(_vm->_cmdList[obj->cmdIndex][0].verbIndex, 0), _vm->_text->getNoun(obj->nounIndex, 0)); - else if ((verb = _vm->useBG(_vm->_text->getNoun(obj->nounIndex, 0))) != 0) + sprintf(_vm->_line, "%s %s", _vm->_text->getVerb(_vm->_parser->getCmdDefaultVerbIdx(obj->cmdIndex), 0), _vm->_text->getNoun(obj->nounIndex, 0)); + else if ((verb = _vm->_parser->useBG(_vm->_text->getNoun(obj->nounIndex, 0))) != 0) sprintf(_vm->_line, "%s %s", verb, _vm->_text->getNoun(obj->nounIndex, 0)); else return; // Can't use object directly } else { // Use status.objid on objid // Default to first cmd verb - sprintf(_vm->_line, "%s %s %s", _vm->_text->getVerb(_vm->_cmdList[_objects[inventObjId].cmdIndex][0].verbIndex, 0), + sprintf(_vm->_line, "%s %s %s", _vm->_text->getVerb(_vm->_parser->getCmdDefaultVerbIdx(_objects[inventObjId].cmdIndex), 0), _vm->_text->getNoun(_objects[inventObjId].nounIndex, 0), _vm->_text->getNoun(obj->nounIndex, 0)); // Check valid use of objects and override verb if necessary - for (uses_t *use = _vm->_uses; use->objId != _numObj; use++) { + for (uses_t *use = _uses; use->objId != _numObj; use++) { if (inventObjId == use->objId) { // Look for secondary object, if found use matching verb bool foundFl = false; @@ -212,40 +213,52 @@ void ObjectHandler::lookObject(object_t *obj) { } /** - * Free all object images + * Free all object images, uses and ObjArr (before exiting) */ void ObjectHandler::freeObjects() { debugC(1, kDebugObject, "freeObjects"); - // Nothing to do if not allocated yet - if (_vm->_hero == 0 || _vm->_hero->seqList[0].seqPtr == 0) - return; - - // Free all sequence lists and image data - for (int i = 0; i < _numObj; i++) { - object_t *obj = &_objects[i]; - for (int j = 0; j < obj->seqNumb; j++) { - seq_t *seq = obj->seqList[j].seqPtr; - seq_t *next; - if (seq == 0) // Failure during database load - break; - if (seq->imagePtr != 0) { - free(seq->imagePtr); - seq->imagePtr = 0; - } - seq = seq->nextSeqPtr; - while (seq != obj->seqList[j].seqPtr) { + if (_vm->_hero != 0 && _vm->_hero->seqList[0].seqPtr != 0) { + // Free all sequence lists and image data + for (int16 i = 0; i < _numObj; i++) { + object_t *obj = &_objects[i]; + for (int16 j = 0; j < obj->seqNumb; j++) { + seq_t *seq = obj->seqList[j].seqPtr; + seq_t *next; + if (seq == 0) // Failure during database load + break; if (seq->imagePtr != 0) { free(seq->imagePtr); seq->imagePtr = 0; } - next = seq->nextSeqPtr; + seq = seq->nextSeqPtr; + while (seq != obj->seqList[j].seqPtr) { + if (seq->imagePtr != 0) { + free(seq->imagePtr); + seq->imagePtr = 0; + } + next = seq->nextSeqPtr; + free(seq); + seq = next; + } free(seq); - seq = next; } - free(seq); } } + + if (_uses) { + for (int16 i = 0; i < _usesSize; i++) + free(_uses[i].targets); + free(_uses); + } + + for(int16 i = 0; i < _objCount; i++) { + free(_objects[i].stateDataIndex); + _objects[i].stateDataIndex = 0; + } + + free(_objects); + _objects = 0; } /** @@ -356,15 +369,34 @@ bool ObjectHandler::findObjectSpace(object_t *obj, int16 *destx, int16 *desty) { } /** - * Free ObjectArr (before exiting) + * Load _uses from Hugo.dat */ -void ObjectHandler::freeObjectArr() { - for(int16 i = 0; i < _objCount; i++) { - free(_objects[i].stateDataIndex); - _objects[i].stateDataIndex = 0; +void ObjectHandler::loadObjectUses(Common::ReadStream &in) { + //Read _uses + for (int varnt = 0; varnt < _vm->_numVariant; varnt++) { + uint16 numElem = in.readUint16BE(); + uses_t *wrkUses = (uses_t *)malloc(sizeof(uses_t) * numElem); + + for (int i = 0; i < numElem; i++) { + wrkUses[i].objId = in.readSint16BE(); + wrkUses[i].dataIndex = in.readUint16BE(); + uint16 numSubElem = in.readUint16BE(); + wrkUses[i].targets = (target_t *)malloc(sizeof(target_t) * numSubElem); + for (int j = 0; j < numSubElem; j++) { + wrkUses[i].targets[j].nounIndex = in.readUint16BE(); + wrkUses[i].targets[j].verbIndex = in.readUint16BE(); + } + } + + if (varnt == _vm->_gameVariant) { + _usesSize = numElem; + _uses = wrkUses; + } else { + for (int i = 0; i < numElem; i++) + free(wrkUses[i].targets); + free(wrkUses); + } } - free(_objects); - _objects = 0; } /** diff --git a/engines/hugo/object.h b/engines/hugo/object.h index aa2ed9ba9f..ef60e622f8 100644 --- a/engines/hugo/object.h +++ b/engines/hugo/object.h @@ -74,7 +74,7 @@ public: int16 findObject(uint16 x, uint16 y); void freeObjects(); void loadObjectArr(Common::ReadStream &in); - void freeObjectArr(); + void loadObjectUses(Common::ReadStream &in); void loadNumObj(Common::ReadStream &in); void lookObject(object_t *obj); void readObjectImages(); @@ -114,6 +114,8 @@ protected: static const int kMaxObjNumb = 128; // Used in Update_images() uint16 _objCount; + uses_t *_uses; + uint16 _usesSize; void restoreSeq(object_t *obj); diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp index 001ddac8e4..c7e252b012 100644 --- a/engines/hugo/parser.cpp +++ b/engines/hugo/parser.cpp @@ -51,17 +51,161 @@ namespace Hugo { -Parser::Parser(HugoEngine *vm) : - _vm(vm), _putIndex(0), _getIndex(0), _checkDoubleF1Fl(false) { +Parser::Parser(HugoEngine *vm) : _vm(vm), _putIndex(0), _getIndex(0), _arrayReqs(0), _catchallList(0), _backgroundObjects(0), _cmdList(0) { _cmdLineIndex = 0; _cmdLineTick = 0; _cmdLineCursor = '_'; _cmdLine[0] = '\0'; + _cmdListSize = 0; + _checkDoubleF1Fl = false; + _backgroundObjectsSize = 0; } Parser::~Parser() { } +/** + * Read _cmdList from Hugo.dat + */ +void Parser::loadCmdList(Common::ReadStream &in) { + for (int varnt = 0; varnt < _vm->_numVariant; varnt++) { + uint16 numElem = in.readUint16BE(); + if (varnt == _vm->_gameVariant) { + _cmdListSize = numElem; + _cmdList = (cmd **)malloc(sizeof(cmd *) * _cmdListSize); + for (int i = 0; i < _cmdListSize; i++) { + uint16 numSubElem = in.readUint16BE(); + _cmdList[i] = (cmd *)malloc(sizeof(cmd) * numSubElem); + for (int j = 0; j < numSubElem; j++) { + _cmdList[i][j].verbIndex = in.readUint16BE(); + _cmdList[i][j].reqIndex = in.readUint16BE(); + _cmdList[i][j].textDataNoCarryIndex = in.readUint16BE(); + _cmdList[i][j].reqState = in.readByte(); + _cmdList[i][j].newState = in.readByte(); + _cmdList[i][j].textDataWrongIndex = in.readUint16BE(); + _cmdList[i][j].textDataDoneIndex = in.readUint16BE(); + _cmdList[i][j].actIndex = in.readUint16BE(); + } + } + } else { + for (int i = 0; i < numElem; i++) { + uint16 numSubElem = in.readUint16BE(); + for (int j = 0; j < numSubElem; j++) { + in.readUint16BE(); + in.readUint16BE(); + in.readUint16BE(); + in.readByte(); + in.readByte(); + in.readUint16BE(); + in.readUint16BE(); + in.readUint16BE(); + } + } + } + } +} + +/** + * Read _backgrounObjects from Hugo.dat + */ +void Parser::loadBackgroundObjects(Common::ReadStream &in) { + for (int varnt = 0; varnt < _vm->_numVariant; varnt++) { + uint16 numElem = in.readUint16BE(); + + background_t **wrkBackgroundObjects = (background_t **)malloc(sizeof(background_t *) * numElem); + + for (int i = 0; i < numElem; i++) { + uint16 numSubElem = in.readUint16BE(); + wrkBackgroundObjects[i] = (background_t *)malloc(sizeof(background_t) * numSubElem); + for (int j = 0; j < numSubElem; j++) { + wrkBackgroundObjects[i][j].verbIndex = in.readUint16BE(); + wrkBackgroundObjects[i][j].nounIndex = in.readUint16BE(); + wrkBackgroundObjects[i][j].commentIndex = in.readSint16BE(); + wrkBackgroundObjects[i][j].matchFl = (in.readByte() != 0); + wrkBackgroundObjects[i][j].roomState = in.readByte(); + wrkBackgroundObjects[i][j].bonusIndex = in.readByte(); + } + } + + if (varnt == _vm->_gameVariant) { + _backgroundObjectsSize = numElem; + _backgroundObjects = wrkBackgroundObjects; + } else { + for (int i = 0; i < numElem; i++) + free(wrkBackgroundObjects[i]); + free(wrkBackgroundObjects); + } + } +} + +/** + * Read _catchallList from Hugo.dat + */ +void Parser::loadCatchallList(Common::ReadStream &in) { + for (int varnt = 0; varnt < _vm->_numVariant; varnt++) { + uint16 numElem = in.readUint16BE(); + background_t *wrkCatchallList = (background_t *)malloc(sizeof(background_t) * numElem); + + for (int i = 0; i < numElem; i++) { + wrkCatchallList[i].verbIndex = in.readUint16BE(); + wrkCatchallList[i].nounIndex = in.readUint16BE(); + wrkCatchallList[i].commentIndex = in.readSint16BE(); + wrkCatchallList[i].matchFl = (in.readByte() != 0); + wrkCatchallList[i].roomState = in.readByte(); + wrkCatchallList[i].bonusIndex = in.readByte(); + } + + if (varnt == _vm->_gameVariant) + _catchallList = wrkCatchallList; + else + free(wrkCatchallList); + } +} + +void Parser::loadArrayReqs(Common::ReadStream &in) { + _arrayReqs = _vm->loadLongArray(in); +} + +/** + * Search background command list for this screen for supplied object. + * Return first associated verb (not "look") or 0 if none found. + */ +const char *Parser::useBG(const char *name) { + debugC(1, kDebugEngine, "useBG(%s)", name); + + objectList_t p = _backgroundObjects[*_vm->_screen_p]; + for (int i = 0; p[i].verbIndex != 0; i++) { + if ((name == _vm->_text->getNoun(p[i].nounIndex, 0) && + p[i].verbIndex != _vm->_look) && + ((p[i].roomState == kStateDontCare) || (p[i].roomState == _vm->_screenStates[*_vm->_screen_p]))) + return _vm->_text->getVerb(p[i].verbIndex, 0); + } + + return 0; +} + +void Parser::freeParser() { + if (_arrayReqs) { + for (int i = 0; _arrayReqs[i] != 0; i++) + free(_arrayReqs[i]); + free(_arrayReqs); + } + + free(_catchallList); + + if (_backgroundObjects) { + for (int i = 0; i < _backgroundObjectsSize; i++) + free(_backgroundObjects[i]); + free(_backgroundObjects); + } + + if (_cmdList) { + for (int i = 0; i < _cmdListSize; i++) + free(_cmdList[i]); + free(_cmdList); + } +} + void Parser::switchTurbo() { _vm->_config.turboFl = !_vm->_config.turboFl; } diff --git a/engines/hugo/parser.h b/engines/hugo/parser.h index 2e807e543f..5bc602fb9a 100644 --- a/engines/hugo/parser.h +++ b/engines/hugo/parser.h @@ -48,11 +48,19 @@ public: virtual ~Parser(); bool isWordPresent(char **wordArr) const; - + + uint16 getCmdDefaultVerbIdx(const uint16 index) const { return _cmdList[index][0].verbIndex; } + void charHandler(); void command(const char *format, ...); + void freeParser(); void keyHandler(Common::Event event); + void loadArrayReqs(Common::ReadStream &in); + void loadBackgroundObjects(Common::ReadStream &in); + void loadCatchallList(Common::ReadStream &in); + void loadCmdList(Common::ReadStream &in); void switchTurbo(); + const char *useBG(const char *name); virtual void lineHandler() = 0; virtual void showInventory() const = 0; @@ -64,6 +72,13 @@ protected: uint32 _cmdLineTick; // For flashing cursor char _cmdLineCursor; command_t _cmdLine; // Build command line + uint16 _backgroundObjectsSize; + uint16 _cmdListSize; + + uint16 **_arrayReqs; + background_t **_backgroundObjects; + background_t *_catchallList; + cmd **_cmdList; const char *findNoun() const; const char *findVerb() const; diff --git a/engines/hugo/parser_v1d.cpp b/engines/hugo/parser_v1d.cpp index 1565490ce3..5796749354 100644 --- a/engines/hugo/parser_v1d.cpp +++ b/engines/hugo/parser_v1d.cpp @@ -192,18 +192,18 @@ bool Parser_v1d::isObjectVerb_v1(const char *word, object_t *obj) { return false; int i; - for (i = 0; _vm->_cmdList[cmdIndex][i].verbIndex != 0; i++) { // For each cmd - if (!strcmp(word, _vm->_text->getVerb(_vm->_cmdList[cmdIndex][i].verbIndex, 0))) // Is this verb catered for? + for (i = 0; _cmdList[cmdIndex][i].verbIndex != 0; i++) { // For each cmd + if (!strcmp(word, _vm->_text->getVerb(_cmdList[cmdIndex][i].verbIndex, 0))) // Is this verb catered for? break; } - if (_vm->_cmdList[cmdIndex][i].verbIndex == 0) // No + if (_cmdList[cmdIndex][i].verbIndex == 0) // No return false; // Verb match found, check all required objects are being carried - cmd *cmnd = &_vm->_cmdList[cmdIndex][i]; // ptr to struct cmd + cmd *cmnd = &_cmdList[cmdIndex][i]; // ptr to struct cmd if (cmnd->reqIndex) { // At least 1 thing in list - uint16 *reqs = _vm->_arrayReqs[cmnd->reqIndex]; // ptr to list of required objects + uint16 *reqs = _arrayReqs[cmnd->reqIndex]; // ptr to list of required objects for (i = 0; reqs[i]; i++) { // for each obj if (!_vm->_object->isCarrying(reqs[i])) { Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(cmnd->textDataNoCarryIndex)); @@ -413,16 +413,16 @@ void Parser_v1d::lineHandler() { return; } } - if ((*farComment == '\0') && isBackgroundWord_v1(noun, verb, _vm->_backgroundObjects[*_vm->_screen_p])) + if ((*farComment == '\0') && isBackgroundWord_v1(noun, verb, _backgroundObjects[*_vm->_screen_p])) return; } while (noun); } noun = findNextNoun(noun); if (*farComment != '\0') // An object matched but not near enough Utils::Box(kBoxAny, "%s", farComment); - else if (!isCatchallVerb_v1(true, noun, verb, _vm->_catchallList) && - !isCatchallVerb_v1(false, noun, verb, _vm->_backgroundObjects[*_vm->_screen_p]) && - !isCatchallVerb_v1(false, noun, verb, _vm->_catchallList)) + else if (!isCatchallVerb_v1(true, noun, verb, _catchallList) && + !isCatchallVerb_v1(false, noun, verb, _backgroundObjects[*_vm->_screen_p]) && + !isCatchallVerb_v1(false, noun, verb, _catchallList)) Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBEh_1d)); } diff --git a/engines/hugo/parser_v1w.cpp b/engines/hugo/parser_v1w.cpp index 2b6741d440..ad00549dcc 100644 --- a/engines/hugo/parser_v1w.cpp +++ b/engines/hugo/parser_v1w.cpp @@ -172,14 +172,14 @@ void Parser_v1w::lineHandler() { } // No objects match command line, try background and catchall commands - if (isBackgroundWord_v3(_vm->_backgroundObjects[*_vm->_screen_p])) + if (isBackgroundWord_v3(_backgroundObjects[*_vm->_screen_p])) return; - if (isCatchallVerb_v3(_vm->_backgroundObjects[*_vm->_screen_p])) + if (isCatchallVerb_v3(_backgroundObjects[*_vm->_screen_p])) return; - if (isBackgroundWord_v3(_vm->_catchallList)) + if (isBackgroundWord_v3(_catchallList)) return; - if (isCatchallVerb_v3(_vm->_catchallList)) + if (isCatchallVerb_v3(_catchallList)) return; // If a not-near comment was generated, print it diff --git a/engines/hugo/parser_v2d.cpp b/engines/hugo/parser_v2d.cpp index cd7928e069..c963441481 100644 --- a/engines/hugo/parser_v2d.cpp +++ b/engines/hugo/parser_v2d.cpp @@ -165,16 +165,16 @@ void Parser_v2d::lineHandler() { return; } } - if ((*farComment != '\0') && isBackgroundWord_v1(noun, verb, _vm->_backgroundObjects[*_vm->_screen_p])) + if ((*farComment != '\0') && isBackgroundWord_v1(noun, verb, _backgroundObjects[*_vm->_screen_p])) return; } while (noun); } noun = findNextNoun(noun); - if ( !isCatchallVerb_v1(true, noun, verb, _vm->_backgroundObjects[*_vm->_screen_p]) - && !isCatchallVerb_v1(true, noun, verb, _vm->_catchallList) - && !isCatchallVerb_v1(false, noun, verb, _vm->_backgroundObjects[*_vm->_screen_p]) - && !isCatchallVerb_v1(false, noun, verb, _vm->_catchallList)) { + if ( !isCatchallVerb_v1(true, noun, verb, _backgroundObjects[*_vm->_screen_p]) + && !isCatchallVerb_v1(true, noun, verb, _catchallList) + && !isCatchallVerb_v1(false, noun, verb, _backgroundObjects[*_vm->_screen_p]) + && !isCatchallVerb_v1(false, noun, verb, _catchallList)) { if (*farComment != '\0') { // An object matched but not near enough Utils::Box(kBoxAny, "%s", farComment); } else if (_maze.enabledFl && (verb == _vm->_text->getVerb(_vm->_look, 0))) { diff --git a/engines/hugo/parser_v3d.cpp b/engines/hugo/parser_v3d.cpp index 532b1f92d1..670f6efb73 100644 --- a/engines/hugo/parser_v3d.cpp +++ b/engines/hugo/parser_v3d.cpp @@ -174,14 +174,14 @@ void Parser_v3d::lineHandler() { } // No objects match command line, try background and catchall commands - if (isBackgroundWord_v3(_vm->_backgroundObjects[*_vm->_screen_p])) + if (isBackgroundWord_v3(_backgroundObjects[*_vm->_screen_p])) return; - if (isCatchallVerb_v3(_vm->_backgroundObjects[*_vm->_screen_p])) + if (isCatchallVerb_v3(_backgroundObjects[*_vm->_screen_p])) return; - if (isBackgroundWord_v3(_vm->_catchallList)) + if (isBackgroundWord_v3(_catchallList)) return; - if (isCatchallVerb_v3(_vm->_catchallList)) + if (isCatchallVerb_v3(_catchallList)) return; // If a not-near comment was generated, print it @@ -219,23 +219,23 @@ bool Parser_v3d::isObjectVerb_v3(object_t *obj, char *comment) { return false; int i; - for (i = 0; _vm->_cmdList[cmdIndex][i].verbIndex != 0; i++) { // For each cmd - if (isWordPresent(_vm->_text->getVerbArray(_vm->_cmdList[cmdIndex][i].verbIndex))) // Was this verb used? + for (i = 0; _cmdList[cmdIndex][i].verbIndex != 0; i++) { // For each cmd + if (isWordPresent(_vm->_text->getVerbArray(_cmdList[cmdIndex][i].verbIndex))) // Was this verb used? break; } - if (_vm->_cmdList[cmdIndex][i].verbIndex == 0) // No verbs used. + if (_cmdList[cmdIndex][i].verbIndex == 0) // No verbs used. return false; // Verb match found. Check if object is Near - char *verb = *_vm->_text->getVerbArray(_vm->_cmdList[cmdIndex][i].verbIndex); + char *verb = *_vm->_text->getVerbArray(_cmdList[cmdIndex][i].verbIndex); if (!isNear_v3(obj, verb, comment)) return false; // Check all required objects are being carried - cmd *cmnd = &_vm->_cmdList[cmdIndex][i]; // ptr to struct cmd + cmd *cmnd = &_cmdList[cmdIndex][i]; // ptr to struct cmd if (cmnd->reqIndex) { // At least 1 thing in list - uint16 *reqs = _vm->_arrayReqs[cmnd->reqIndex]; // ptr to list of required objects + uint16 *reqs = _arrayReqs[cmnd->reqIndex]; // ptr to list of required objects for (i = 0; reqs[i]; i++) { // for each obj if (!_vm->_object->isCarrying(reqs[i])) { Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(cmnd->textDataNoCarryIndex)); diff --git a/engines/hugo/schedule.cpp b/engines/hugo/schedule.cpp index b36ce70847..c5d1683a96 100644 --- a/engines/hugo/schedule.cpp +++ b/engines/hugo/schedule.cpp @@ -48,13 +48,19 @@ namespace Hugo { -Scheduler::Scheduler(HugoEngine *vm) : _vm(vm), _actListArr(0), _curTick(0), _oldTime(0), _refreshTimeout(0) { +Scheduler::Scheduler(HugoEngine *vm) : _vm(vm), _actListArr(0), _curTick(0), _oldTime(0), _refreshTimeout(0), _points(0), _screenActs(0) { memset(_events, 0, sizeof(_events)); + _numBonuses = 0; + _screenActsSize = 0; } Scheduler::~Scheduler() { } +void Scheduler::initCypher() { + _cypher = getCypher(); +} + /** * Initialise the timer event queue */ @@ -142,9 +148,9 @@ uint32 Scheduler::getDosTicks(const bool updateFl) { void Scheduler::processBonus(const int bonusIndex) { debugC(1, kDebugSchedule, "processBonus(%d)", bonusIndex); - if (!_vm->_points[bonusIndex].scoredFl) { - _vm->adjustScore(_vm->_points[bonusIndex].score); - _vm->_points[bonusIndex].scoredFl = true; + if (!_points[bonusIndex].scoredFl) { + _vm->adjustScore(_points[bonusIndex].score); + _points[bonusIndex].scoredFl = true; } } @@ -186,7 +192,7 @@ void Scheduler::newScreen(const int screenIndex) { _vm->readScreenFiles(screenIndex); // 4. Schedule action list for this screen - _vm->screenActions(screenIndex); + _vm->_scheduler->screenActions(screenIndex); // 5. Initialise prompt line and status line _vm->_screen->initNewScreenDisplay(); @@ -245,6 +251,28 @@ void Scheduler::loadAlNewscrIndex(Common::ReadStream &in) { } /** + * Load Points from Hugo.dat + */ +void Scheduler::loadPoints(Common::ReadStream &in) { + debugC(6, kDebugSchedule, "loadPoints(&in)"); + + for (int varnt = 0; varnt < _vm->_numVariant; varnt++) { + uint16 numElem = in.readUint16BE(); + if (varnt == _vm->_gameVariant) { + _numBonuses = numElem; + _points = (point_t *)malloc(sizeof(point_t) * _numBonuses); + for (int i = 0; i < _numBonuses; i++) { + _points[i].score = in.readByte(); + _points[i].scoredFl = false; + } + } else { + for (int i = 0; i < numElem; i++) + in.readByte(); + } + } +} + +/** * Load actListArr from Hugo.dat */ void Scheduler::loadActListArr(Common::ReadStream &in) { @@ -816,9 +844,47 @@ void Scheduler::loadActListArr(Common::ReadStream &in) { } } -void Scheduler::freeActListArr() { +/** + * Read _screenActs + */ +void Scheduler::loadScreenAct(Common::ReadStream &in) { + for (int varnt = 0; varnt < _vm->_numVariant; varnt++) { + uint16 numElem = in.readUint16BE(); + + uint16 **wrkScreenActs = (uint16 **)malloc(sizeof(uint16 *) * numElem); + for (int i = 0; i < numElem; i++) { + uint16 numSubElem = in.readUint16BE(); + if (numSubElem == 0) { + wrkScreenActs[i] = 0; + } else { + wrkScreenActs[i] = (uint16 *)malloc(sizeof(uint16) * numSubElem); + for (int j = 0; j < numSubElem; j++) + wrkScreenActs[i][j] = in.readUint16BE(); + } + } + + if (varnt == _vm->_gameVariant) { + _screenActsSize = numElem; + _screenActs = wrkScreenActs; + } else { + for (int i = 0; i < numElem; i++) + free(wrkScreenActs[i]); + free(wrkScreenActs); + } + } +} + +void Scheduler::freeScheduler() { debugC(6, kDebugSchedule, "freeActListArr()"); + free(_points); + + if (_screenActs) { + for (int i = 0; i < _screenActsSize; i++) + free(_screenActs[i]); + free(_screenActs); + } + if (_actListArr) { for (int i = 0; i < _actListArrSize; i++) { for (int j = 0; _actListArr[i][j].a0.actType != ANULL; j++) { @@ -832,6 +898,19 @@ void Scheduler::freeActListArr() { } /** + * Add action lists for this screen to event queue + */ +void Scheduler::screenActions(const int screenNum) { + debugC(1, kDebugEngine, "screenActions(%d)", screenNum); + + uint16 *screenAct = _screenActs[screenNum]; + if (screenAct) { + for (int i = 0; screenAct[i]; i++) + insertActionList(screenAct[i]); + } +} + +/** * Maze mode is enabled. Check to see whether hero has crossed the maze * bounding box, if so, go to the next room */ @@ -935,10 +1014,16 @@ void Scheduler::restoreActions(Common::ReadStream *f) { } } +int16 Scheduler::calcMaxPoints() const { + int16 tmpScore = 0; + for (int i = 0; i < _numBonuses; i++) + tmpScore += _points[i].score; + return tmpScore; +} + /* * Save the action data in the file with handle f */ - void Scheduler::saveActions(Common::WriteStream* f) const { for (int i = 0; i < _actListArrSize; i++) { // write all the sub elems data @@ -979,6 +1064,27 @@ void Scheduler::findAction(act* action, int16* index, int16* subElem) { assert(0); } +void Scheduler::saveSchedulerData(Common::WriteStream *out) { + savePoints(out); + + // Now save current time and all current events in event queue + saveEvents(out); + + // Now save current actions + saveActions(out); +} + +void Scheduler::restoreSchedulerData(Common::ReadStream *in) { + restorePoints(in); + _vm->_object->restoreAllSeq(); + + // Now restore time of the save and the event queue + restoreEvents(in); + + // Now restore actions + restoreActions(in); +} + /** * Restore the event list from file with handle f */ @@ -1262,7 +1368,7 @@ event_t *Scheduler::doAction(event_t *curEvent) { Utils::Box(kBoxOk, "%s", _vm->_file->fetchString(action->a40.stringIndex)); break; case COND_BONUS: // act41: Perform action if got bonus - if (_vm->_points[action->a41.BonusIndex].scoredFl) + if (_points[action->a41.BonusIndex].scoredFl) insertActionList(action->a41.actPassIndex); else insertActionList(action->a41.actFailIndex); @@ -1354,6 +1460,9 @@ void Scheduler::delQueue(event_t *curEvent) { _freeEvent = curEvent; } +/** + * Delete all the active events of a given type + */ void Scheduler::delEventType(const action_t actTypeDel) { // Note: actions are not deleted here, simply turned into NOPs! event_t *wrkEvent = _headEvent; // The earliest event @@ -1367,6 +1476,27 @@ void Scheduler::delEventType(const action_t actTypeDel) { } } +/** + * Save the points table + */ +void Scheduler::savePoints(Common::WriteStream *out) const { + for (int i = 0; i < _numBonuses; i++) { + out->writeByte(_points[i].score); + out->writeByte((_points[i].scoredFl) ? 1 : 0); + } +} + +/** + * Restore the points table + */ +void Scheduler::restorePoints(Common::ReadStream *in) { + // Restore points table + for (int i = 0; i < _numBonuses; i++) { + _points[i].score = in->readByte(); + _points[i].scoredFl = (in->readByte() == 1); + } +} + Scheduler_v1d::Scheduler_v1d(HugoEngine *vm) : Scheduler(vm) { } @@ -1427,11 +1557,9 @@ void Scheduler_v1d::promptAction(act *action) { void Scheduler_v1d::decodeString(char *line) { debugC(1, kDebugSchedule, "decodeString(%s)", line); - static const Common::String cypher = getCypher(); - uint16 linelength = strlen(line); for(uint16 i = 0; i < linelength; i++) { - line[i] = (line[i] + cypher.c_str()[i % cypher.size()]) % '~'; + line[i] = (line[i] + _cypher.c_str()[i % _cypher.size()]) % '~'; if (line[i] < ' ') line[i] += ' '; } @@ -1480,11 +1608,10 @@ void Scheduler_v2d::promptAction(act *action) { void Scheduler_v2d::decodeString(char *line) { debugC(1, kDebugSchedule, "decodeString(%s)", line); - static const Common::String cypher = getCypher(); - int16 lineLength = strlen(line); for (uint16 i = 0; i < lineLength; i++) - line[i] -= cypher.c_str()[i % cypher.size()]; + line[i] -= _cypher.c_str()[i % _cypher.size()]; + debugC(1, kDebugSchedule, "result : %s", line); } diff --git a/engines/hugo/schedule.h b/engines/hugo/schedule.h index b4889aa728..e2169a0aa9 100644 --- a/engines/hugo/schedule.h +++ b/engines/hugo/schedule.h @@ -458,31 +458,40 @@ public: virtual void decodeString(char *line) = 0; virtual void runScheduler() = 0; - void freeActListArr(); + int16 calcMaxPoints() const; + + void freeScheduler(); + void initCypher(); void initEventQueue(); void insertActionList(const uint16 actIndex); void loadActListArr(Common::ReadStream &in); void loadAlNewscrIndex(Common::ReadStream &in); + void loadPoints(Common::ReadStream &in); + void loadScreenAct(Common::ReadStream &in); void newScreen(const int screenIndex); void processBonus(const int bonusIndex); void processMaze(const int x1, const int x2, const int y1, const int y2); + void restoreSchedulerData(Common::ReadStream *in); void restoreScreen(const int screenIndex); - void restoreEvents(Common::ReadStream *f); - void saveEvents(Common::WriteStream *f); + void saveSchedulerData(Common::WriteStream *out); void waitForRefresh(); void findAction(act* action, int16* index, int16* subElem); - void saveActions(Common::WriteStream* f) const; - void restoreActions(Common::ReadStream *f); - protected: HugoEngine *_vm; static const int kFilenameLength = 12; // Max length of a DOS file name static const int kMaxEvents = 50; // Max events in event queue static const int kShiftSize = 8; // Place hero this far inside bounding box + Common::String _cypher; + uint16 _actListArrSize; uint16 _alNewscrIndex; + uint16 _screenActsSize; + uint16 **_screenActs; + + byte _numBonuses; + point_t *_points; uint32 _curTick; // Current system time in ticks uint32 _oldTime; // The previous wall time in ticks @@ -510,6 +519,14 @@ protected: void delEventType(const action_t actTypeDel); void delQueue(event_t *curEvent); void insertAction(act *action); + void restoreActions(Common::ReadStream *f); + void restoreEvents(Common::ReadStream *f); + void restorePoints(Common::ReadStream *in); + void saveActions(Common::WriteStream* f) const; + void saveEvents(Common::WriteStream *f); + void savePoints(Common::WriteStream *out) const; + void screenActions(const int screenNum); + }; class Scheduler_v1d : public Scheduler { |