aboutsummaryrefslogtreecommitdiff
path: root/engines/hugo
diff options
context:
space:
mode:
Diffstat (limited to 'engines/hugo')
-rw-r--r--engines/hugo/display.cpp15
-rw-r--r--engines/hugo/display.h3
-rw-r--r--engines/hugo/file.cpp27
-rw-r--r--engines/hugo/hugo.cpp316
-rw-r--r--engines/hugo/hugo.h27
-rw-r--r--engines/hugo/intro.cpp45
-rw-r--r--engines/hugo/intro.h11
-rw-r--r--engines/hugo/inventory.cpp41
-rw-r--r--engines/hugo/inventory.h8
-rw-r--r--engines/hugo/object.cpp100
-rw-r--r--engines/hugo/object.h4
-rw-r--r--engines/hugo/parser.cpp148
-rw-r--r--engines/hugo/parser.h17
-rw-r--r--engines/hugo/parser_v1d.cpp18
-rw-r--r--engines/hugo/parser_v1w.cpp8
-rw-r--r--engines/hugo/parser_v2d.cpp10
-rw-r--r--engines/hugo/parser_v3d.cpp20
-rw-r--r--engines/hugo/schedule.cpp155
-rw-r--r--engines/hugo/schedule.h29
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 {