aboutsummaryrefslogtreecommitdiff
path: root/engines/macventure/macventure.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/macventure/macventure.cpp')
-rw-r--r--engines/macventure/macventure.cpp1185
1 files changed, 1185 insertions, 0 deletions
diff --git a/engines/macventure/macventure.cpp b/engines/macventure/macventure.cpp
new file mode 100644
index 0000000000..826409f30b
--- /dev/null
+++ b/engines/macventure/macventure.cpp
@@ -0,0 +1,1185 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/system.h"
+#include "common/debug-channels.h"
+#include "common/debug.h"
+#include "common/error.h"
+#include "common/config-manager.h"
+#include "engines/util.h"
+
+#include "macventure/macventure.h"
+
+// To move
+#include "common/file.h"
+
+namespace MacVenture {
+
+// HACK, see below
+void toASCII(Common::String &str) {
+ debugC(3, kMVDebugMain, "toASCII: %s", str.c_str());
+ Common::String::iterator it = str.begin();
+ for (; it != str.end(); it++) {
+ if (*it == '\216') {
+ str.replace(it, it + 1, "e");
+ }
+ if (*it == '\210') {
+ str.replace(it, it + 1, "a");
+ }
+ }
+}
+
+enum {
+ kMaxMenuTitleLength = 30
+};
+
+MacVentureEngine::MacVentureEngine(OSystem *syst, const ADGameDescription *gameDesc) : Engine(syst) {
+ _gameDescription = gameDesc;
+ _rnd = new Common::RandomSource("macventure");
+
+ initDebugChannels();
+
+ _debugger = NULL;
+ _resourceManager = NULL;
+ _globalSettings = NULL;
+ _gui = NULL;
+ _world = NULL;
+ _scriptEngine = NULL;
+ _filenames = NULL;
+
+ _decodingDirectArticles = NULL;
+ _decodingNamingArticles = NULL;
+ _decodingIndirectArticles = NULL;
+ _textHuffman = NULL;
+
+ _soundManager = NULL;
+
+ _dataBundle = NULL;
+
+ debug("MacVenture::MacVentureEngine()");
+}
+
+MacVentureEngine::~MacVentureEngine() {
+ debug("MacVenture::~MacVentureEngine()");
+
+ DebugMan.clearAllDebugChannels();
+
+ if (_rnd)
+ delete _rnd;
+
+ if (_debugger)
+ delete _debugger;
+
+ if (_resourceManager)
+ delete _resourceManager;
+
+ if (_globalSettings)
+ delete _globalSettings;
+
+ if (_gui)
+ delete _gui;
+
+ if (_world)
+ delete _world;
+
+ if (_scriptEngine)
+ delete _scriptEngine;
+
+ if (_filenames)
+ delete _filenames;
+
+ if (_decodingDirectArticles)
+ delete _decodingDirectArticles;
+
+ if (_decodingNamingArticles)
+ delete _decodingNamingArticles;
+
+ if (_decodingIndirectArticles)
+ delete _decodingIndirectArticles;
+
+ if (_textHuffman)
+ delete _textHuffman;
+
+ if (_soundManager)
+ delete _soundManager;
+
+ if (_dataBundle)
+ delete _dataBundle;
+}
+
+void MacVentureEngine::initDebugChannels() {
+ DebugMan.addDebugChannel(kMVDebugMain, "main", "Engine state");
+ DebugMan.addDebugChannel(kMVDebugGUI, "gui", "Gui");
+ DebugMan.addDebugChannel(kMVDebugText, "text", "Text decoders and printers");
+ DebugMan.addDebugChannel(kMVDebugImage, "image", "Image decoders and renderers");
+ DebugMan.addDebugChannel(kMVDebugScript, "script", "Script engine");
+ DebugMan.addDebugChannel(kMVDebugSound, "sound", "Sound decoders");
+ DebugMan.addDebugChannel(kMVDebugContainer, "container", "Containers");
+}
+
+Common::Error MacVentureEngine::run() {
+ debug("MacVenture::MacVentureEngine::init()");
+ initGraphics(kScreenWidth, kScreenHeight, true);
+
+ _debugger = new Console(this);
+
+ // Additional setup.
+ debug("MacVentureEngine::init");
+
+ _resourceManager = new Common::MacResManager();
+ if (!_resourceManager->open(getGameFileName()))
+ error("ENGINE: Could not open %s as a resource fork", getGameFileName());
+
+ // Engine-wide loading
+ if (!loadGlobalSettings())
+ error("ENGINE: Could not load the engine settings");
+
+ _oldTextEncoding = !loadTextHuffman();
+
+ _filenames = new StringTable(this, _resourceManager, kFilenamesStringTableID);
+ _decodingDirectArticles = new StringTable(this, _resourceManager, kCommonArticlesStringTableID);
+ _decodingNamingArticles = new StringTable(this, _resourceManager, kNamingArticlesStringTableID);
+ _decodingIndirectArticles = new StringTable(this, _resourceManager, kIndirectArticlesStringTableID);
+
+ loadDataBundle();
+
+ // Big class instantiation
+ _gui = new Gui(this, _resourceManager);
+ _world = new World(this, _resourceManager);
+ _scriptEngine = new ScriptEngine(this, _world);
+
+ _soundManager = new SoundManager(this, _mixer);
+
+ setInitialFlags();
+
+ int directSaveSlotLoading = ConfMan.getInt("save_slot");
+ if (directSaveSlotLoading >= 0) {
+ if (loadGameState(directSaveSlotLoading).getCode() != Common::kNoError) {
+ error("ENGINE: Could not load game from slot '%d'", directSaveSlotLoading);
+ }
+ } else {
+ setNewGameState();
+ }
+ selectControl(kStartOrResume);
+
+ _gui->addChild(kSelfWindow, 1);
+ _gui->updateWindow(kSelfWindow, false);
+
+ while (_gameState != kGameStateQuitting) {
+ processEvents();
+
+ if (_gameState != kGameStateQuitting && !_gui->isDialogOpen()) {
+
+ if (_prepared) {
+ _prepared = false;
+
+ if (!_halted)
+ updateState(false);
+
+ if (_cmdReady || _halted) {
+ _halted = false;
+ if (runScriptEngine()) {
+ _halted = true;
+ _paused = true;
+ } else {
+ _paused = false;
+ updateState(true);
+ updateControls();
+ updateExits();
+ }
+ }
+
+ if (_gameState == kGameStateWinnig || _gameState == kGameStateLosing) {
+ endGame();
+ }
+ }
+ }
+ refreshScreen();
+ }
+
+ return Common::kNoError;
+}
+
+void MacVentureEngine::refreshScreen() {
+ _gui->draw();
+ g_system->updateScreen();
+ g_system->delayMillis(50);
+}
+
+void MacVentureEngine::newGame() {
+ _world->startNewGame();
+ reset();
+ setInitialFlags();
+ setNewGameState();
+}
+
+void MacVentureEngine::setInitialFlags() {
+ _paused = false;
+ _halted = false;
+ _cmdReady = false;
+ _haltedAtEnd = false;
+ _haltedInSelection = false;
+ _clickToContinue = true;
+ _gameState = kGameStateInit;
+ _destObject = 0;
+ _prepared = true;
+}
+
+void MacVentureEngine::setNewGameState() {
+ _cmdReady = true;
+ ObjID playerParent = _world->getObjAttr(1, kAttrParentObject);
+ _currentSelection.push_back(playerParent);// Push the parent of the player
+ _world->setObjAttr(playerParent, kAttrContainerOpen, 1);
+}
+
+void MacVentureEngine::reset() {
+ resetInternals();
+ resetGui();
+}
+
+void MacVentureEngine::resetInternals() {
+ _scriptEngine->reset();
+ _currentSelection.clear();
+ _objQueue.clear();
+ _textQueue.clear();
+}
+
+void MacVentureEngine::resetGui() {
+ _gui->reloadInternals();
+ _gui->updateWindowInfo(kMainGameWindow, getParent(1), _world->getChildren(getParent(1), true));
+ // HACK! should update all inventories
+ _gui->ensureInventoryOpen(kInventoryStart, 1);
+ _gui->updateWindowInfo(kInventoryStart, 1, _world->getChildren(1, true));
+ updateControls();
+ updateExits();
+ refreshScreen();
+}
+
+void MacVentureEngine::requestQuit() {
+ // TODO: Display save game dialog and such
+ _gameState = kGameStateQuitting;
+}
+
+void MacVentureEngine::requestUnpause() {
+ _paused = false;
+ _gameState = kGameStatePlaying;
+}
+
+void MacVentureEngine::selectControl(ControlAction id) {
+ debugC(2, kMVDebugMain, "Select control %x", id);
+ if (id == kClickToContinue) {
+ _clickToContinue = false;
+ _paused = true;
+ return;
+ }
+
+ _selectedControl = id;
+ refreshReady();
+}
+
+void MacVentureEngine::refreshReady() {
+ switch (getInvolvedObjects()) {
+ case 0: // No selected object
+ _cmdReady = true;
+ break;
+ case 1: // We have some selected object
+ _cmdReady = _currentSelection.size() != 0;
+ break;
+ case 2:
+ if (_destObject > 0) // We have a destination seleted
+ _cmdReady = true;
+ break;
+ }
+}
+
+void MacVentureEngine::preparedToRun() {
+ _prepared = true;
+}
+
+void MacVentureEngine::gameChanged() {
+ _gameChanged = true;
+}
+
+void MacVentureEngine::winGame() {
+ _gui->showPrebuiltDialog(kWinGameDialog);
+ _gameState = kGameStateWinnig;
+}
+
+void MacVentureEngine::loseGame() {
+ _gui->showPrebuiltDialog(kLoseGameDialog);
+ _paused = true;
+ //_gameState = kGameStateLosing;
+}
+
+void MacVentureEngine::clickToContinue() {
+ _clickToContinue = true;
+}
+
+void MacVentureEngine::enqueueObject(ObjectQueueID type, ObjID objID, ObjID target) {
+ QueuedObject obj;
+ obj.id = type;
+
+ if (type == kUpdateObject && isObjEnqueued(objID)) {
+ return;
+ }
+
+ if (type == kUpdateWindow) {
+ obj.target = target;
+ }
+
+ if (type != kHightlightExits) {
+ obj.object = objID;
+ obj.parent = _world->getObjAttr(objID, kAttrParentObject);
+ obj.x = _world->getObjAttr(objID, kAttrPosX);
+ obj.y = _world->getObjAttr(objID, kAttrPosY);
+ obj.exitx = _world->getObjAttr(objID, kAttrExitX);
+ obj.exity = _world->getObjAttr(objID, kAttrExitY);
+ obj.hidden = _world->getObjAttr(objID, kAttrHiddenExit);
+ obj.offscreen = _world->getObjAttr(objID, kAttrInvisible);
+ obj.invisible = _world->getObjAttr(objID, kAttrUnclickable);
+ }
+ _objQueue.push_back(obj);
+}
+
+void MacVentureEngine::enqueueText(TextQueueID type, ObjID target, ObjID source, ObjID text) {
+ QueuedText newText;
+ newText.id = type;
+ newText.destination = target;
+ newText.source = source;
+ newText.asset = text;
+ _textQueue.push_back(newText);
+}
+
+void MacVentureEngine::enqueueSound(SoundQueueID type, ObjID target) {
+ QueuedSound newSound;
+ newSound.id = type;
+ newSound.reference = target;
+ _soundQueue.push_back(newSound);
+}
+
+void MacVentureEngine::handleObjectSelect(ObjID objID, WindowReference win, bool shiftPressed, bool isDoubleClick) {
+ if (win == kExitsWindow) {
+ win = kMainGameWindow;
+ }
+
+ const WindowData &windata = _gui->getWindowData(win);
+
+ if (shiftPressed) {
+ // TODO: Implement shift functionality.
+ } else {
+ if (_selectedControl && _currentSelection.size() > 0 && getInvolvedObjects() > 1) {
+ if (objID == 0) {
+ selectPrimaryObject(windata.objRef);
+ } else {
+ selectPrimaryObject(objID);
+ }
+ preparedToRun();
+ } else {
+ if (objID == 0) {
+ unselectAll();
+ objID = win;
+ }
+ if (objID > 0) {
+ int currentObjectIndex = findObjectInArray(objID, _currentSelection);
+
+ if (currentObjectIndex >= 0)
+ unselectAll();
+
+ if (isDoubleClick) {
+ selectObject(objID);
+ _destObject = objID;
+ setDeltaPoint(Common::Point(0, 0));
+ if (!_cmdReady) {
+ selectControl(kActivateObject);
+ _cmdReady = true;
+ }
+ } else {
+ selectObject(objID);
+ if (getInvolvedObjects() == 1)
+ _cmdReady = true;
+ }
+ preparedToRun();
+ }
+ }
+ }
+}
+
+void MacVentureEngine::handleObjectDrop(ObjID objID, Common::Point delta, ObjID newParent) {
+ _destObject = newParent;
+ setDeltaPoint(delta);
+ selectControl(kMoveObject);
+ refreshReady();
+ preparedToRun();
+}
+
+void MacVentureEngine::setDeltaPoint(Common::Point newPos) {
+ debugC(4, kMVDebugMain, "Update delta: Old(%d, %d), New(%d, %d)",
+ _deltaPoint.x, _deltaPoint.y,
+ newPos.x, newPos.y);
+ _deltaPoint = newPos;
+}
+
+void MacVentureEngine::focusObjWin(ObjID objID) {
+ _gui->bringToFront(getObjWindow(objID));
+}
+
+void MacVentureEngine::updateWindow(WindowReference winID) {
+ _gui->updateWindow(winID, true);
+}
+
+bool MacVentureEngine::showTextEntry(ObjID text, ObjID srcObj, ObjID destObj) {
+ debugC(3, kMVDebugMain, "Showing speech dialog, asset %d from %d to %d", text, srcObj, destObj);
+ _gui->getTextFromUser();
+
+ _prepared = false;
+ warning("Show text entry: not fully tested");
+ return true;
+}
+
+void MacVentureEngine::setTextInput(Common::String content) {
+ _prepared = true;
+ _userInput = content;
+ _clickToContinue = false;
+}
+
+Common::String MacVentureEngine::getUserInput() {
+ return _userInput;
+}
+
+
+Common::String MacVentureEngine::getStartGameFileName() {
+ Common::SeekableReadStream *res;
+ res = _resourceManager->getResource(MKTAG('S', 'T', 'R', ' '), kStartGameFilenameID);
+ if (!res)
+ return "";
+
+ byte length = res->readByte();
+ char *fileName = new char[length + 1];
+ res->read(fileName, length);
+ fileName[length] = '\0';
+ Common::String result = Common::String(fileName, length);
+ // HACK, see definition of toASCII
+ toASCII(result);
+
+ delete[] fileName;
+ delete res;
+
+ return result;
+}
+
+const GlobalSettings& MacVentureEngine::getGlobalSettings() const {
+ return *_globalSettings;
+}
+
+// Private engine methods
+void MacVentureEngine::processEvents() {
+ Common::Event event;
+
+ while (_eventMan->pollEvent(event)) {
+ if (_gui->processEvent(event))
+ continue;
+
+ switch (event.type) {
+ case Common::EVENT_QUIT:
+ _gameState = kGameStateQuitting;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+bool MacVenture::MacVentureEngine::runScriptEngine() {
+ debugC(3, kMVDebugMain, "Running script engine");
+ if (_haltedAtEnd) {
+ _haltedAtEnd = false;
+ if (_scriptEngine->resume(false)) {
+ _haltedAtEnd = true;
+ return true;
+ }
+ return false;
+ }
+
+ if (_haltedInSelection) {
+ _haltedInSelection = false;
+ if (_scriptEngine->resume(false)) {
+ _haltedInSelection = true;
+ return true;
+ }
+ updateState(true);
+ }
+
+ while (!_currentSelection.empty()) {
+ ObjID obj = _currentSelection.front();
+ _currentSelection.remove_at(0);
+ if (isGameRunning() && _world->isObjActive(obj)) {
+ if (_scriptEngine->runControl(_selectedControl, obj, _destObject, _deltaPoint)) {
+ _haltedInSelection = true;
+ return true;
+ }
+ updateState(true);
+ }
+ }
+ if (_selectedControl == 1) {
+ _gameChanged = false;
+ } else if (isGameRunning()) {
+ if (_scriptEngine->runControl(kTick, _selectedControl, _destObject, _deltaPoint)) {
+ _haltedAtEnd = true;
+ return true;
+ }
+ }
+ return false;
+}
+
+void MacVentureEngine::endGame() {
+ requestQuit();
+}
+
+void MacVentureEngine::updateState(bool pause) {
+ _prepared = false;
+ runObjQueue();
+ printTexts();
+ playSounds(pause);
+}
+
+void MacVentureEngine::revert() {
+ _gui->invertWindowColors(kMainGameWindow);
+ preparedToRun();
+}
+
+void MacVentureEngine::runObjQueue() {
+ while (!_objQueue.empty()) {
+ uint32 biggest = 0;
+ uint32 index = 0;
+ uint32 temp;
+ for (uint i = 0; i < _objQueue.size(); i++) {
+ temp = _objQueue[i].id;
+ if (temp > biggest) {
+ biggest = temp;
+ index = i;
+ }
+ }
+ QueuedObject obj = _objQueue[index];
+ _objQueue.remove_at(index);
+ switch (obj.id) {
+ case 0x2:
+ focusObjectWindow(obj.object);
+ break;
+ case 0x3:
+ openObject(obj.object);
+ break;
+ case 0x4:
+ closeObject(obj.object);
+ break;
+ case 0x7:
+ checkObject(obj);
+ break;
+ case 0x8:
+ reflectSwap(obj.object, obj.target);
+ break;
+ case 0xc:
+ _world->setObjAttr(_gui->getWindowData(kMainGameWindow).refcon, kAttrContainerOpen, 0);
+ _world->setObjAttr(_world->getObjAttr(1, kAttrParentObject), kAttrContainerOpen, 1);
+ break;
+ case 0xd:
+ toggleExits();
+ break;
+ case 0xe:
+ zoomObject(obj.object);
+ break;
+ }
+ }
+}
+
+void MacVentureEngine::printTexts() {
+ for (uint i = 0; i < _textQueue.size(); i++) {
+ QueuedText text = _textQueue.front();
+ _textQueue.remove_at(0);
+ switch (text.id) {
+ case kTextNumber:
+ _gui->printText(Common::String(text.asset));
+ gameChanged();
+ break;
+ case kTextNewLine:
+ _gui->printText(Common::String(""));
+ gameChanged();
+ break;
+ case kTextPlain:
+ _gui->printText(_world->getText(text.asset, text.source, text.destination));
+ gameChanged();
+ break;
+ }
+ }
+}
+
+void MacVentureEngine::playSounds(bool pause) {
+ int delay = 0;
+ while (!_soundQueue.empty()) {
+ QueuedSound item = _soundQueue.front();
+ _soundQueue.remove_at(0);
+ switch (item.id) {
+ case kSoundPlay:
+ _soundManager->playSound(item.reference);
+ break;
+ case kSoundPlayAndWait:
+ delay = _soundManager->playSound(item.reference);
+ break;
+ case kSoundWait:
+ // Empty in the original.
+ break;
+ }
+ }
+ if (pause && delay > 0) {
+ warning("Sound pausing not yet tested. Pausing for %d", delay);
+ g_system->delayMillis(delay);
+ preparedToRun();
+ }
+}
+
+void MacVentureEngine::updateControls() {
+ selectControl(kNoCommand);
+ _gui->clearControls();
+ toggleExits();
+ resetVars();
+}
+
+void MacVentureEngine::resetVars() {
+ selectControl(kNoCommand);
+ _currentSelection.clear();
+ _destObject = 0;
+ setDeltaPoint(Common::Point(0, 0));
+ _cmdReady = false;
+}
+
+void MacVentureEngine::unselectAll() {
+ while (!_currentSelection.empty()) {
+ unselectObject(_currentSelection.front());
+ }
+}
+
+void MacVentureEngine::selectObject(ObjID objID) {
+ if (!_currentSelection.empty()) {
+ if (findParentWindow(objID) != findParentWindow(_currentSelection[0])) {
+ // TODO: Needs further testing, but it doesn't seem necessary.
+ //unselectAll();
+ }
+ }
+ if (findObjectInArray(objID, _currentSelection) == -1) {
+ _currentSelection.push_back(objID);
+ highlightExit(objID);
+ }
+}
+
+void MacVentureEngine::unselectObject(ObjID objID) {
+ int idxCur = findObjectInArray(objID, _currentSelection);
+ if (idxCur != -1) {
+ _currentSelection.remove_at(idxCur);
+ highlightExit(objID);
+ }
+}
+
+
+void MacVentureEngine::updateExits() {
+ _gui->clearExits();
+ _gui->unselectExits();
+
+ Common::Array<ObjID> exits = _world->getChildren(_world->getObjAttr(1, kAttrParentObject), true);
+ for (uint i = 0; i < exits.size(); i++)
+ _gui->updateExit(exits[i]);
+
+}
+
+int MacVentureEngine::findObjectInArray(ObjID objID, const Common::Array<ObjID> &list) {
+ // Find the object in the current selection
+ bool found = false;
+ uint i = 0;
+ while (i < list.size() && !found) {
+ if (list[i] == objID) {
+ found = true;
+ } else {
+ i++;
+ }
+ }
+ // HACK, should use iterator
+ return found ? i : -1;
+}
+
+uint MacVentureEngine::getPrefixNdx(ObjID obj) {
+ return _world->getObjAttr(obj, kAttrPrefixes);
+}
+
+Common::String MacVentureEngine::getPrefixString(uint flag, ObjID obj) {
+ uint ndx = getPrefixNdx(obj);
+ ndx = ((ndx) >> flag) & 3;
+ return _decodingNamingArticles->getString(ndx);
+}
+
+Common::String MacVentureEngine::getNoun(ObjID ndx) {
+ return _decodingIndirectArticles->getString(ndx);
+}
+
+void MacVentureEngine::highlightExit(ObjID objID) {
+ // TODO: It seems unnecessary since the GUI checks whether an object
+ // is selected, which includes exits.
+ warning("STUB: highlightExit");
+}
+
+void MacVentureEngine::selectPrimaryObject(ObjID objID) {
+ if (objID == _destObject) {
+ return;
+ }
+ int idx;
+ debugC(4, kMVDebugMain, "Select primary object (%d)", objID);
+ if (_destObject > 0 &&
+ (idx = findObjectInArray(_destObject, _currentSelection)) != -1) {
+ unselectAll();
+ }
+ _destObject = objID;
+ if (findObjectInArray(_destObject, _currentSelection) == -1) {
+ selectObject(_destObject);
+ }
+
+ _cmdReady = true;
+}
+
+void MacVentureEngine::focusObjectWindow(ObjID objID) {
+ if (objID) {
+ WindowReference win = getObjWindow(objID);
+ if (win)
+ _gui->bringToFront(win);
+ }
+}
+
+void MacVentureEngine::openObject(ObjID objID) {
+ debugC(3, kMVDebugMain, "Open Object[%d] parent[%d] x[%d] y[%d]",
+ objID,
+ _world->getObjAttr(objID, kAttrParentObject),
+ _world->getObjAttr(objID, kAttrPosX),
+ _world->getObjAttr(objID, kAttrPosY));
+
+ if (getObjWindow(objID)) {
+ return;
+ }
+ if (objID == _world->getObjAttr(1, kAttrParentObject)) {
+ _gui->updateWindowInfo(kMainGameWindow, objID, _world->getChildren(objID, true));
+ _gui->updateWindow(kMainGameWindow, _world->getObjAttr(objID, kAttrContainerOpen));
+ updateExits();
+ _gui->setWindowTitle(kMainGameWindow, _world->getText(objID, objID, objID)); // it ignores source and target in the original
+ } else { // Open inventory window
+ Common::Point p(_world->getObjAttr(objID, kAttrPosX), _world->getObjAttr(objID, kAttrPosY));
+ WindowReference invID = _gui->createInventoryWindow(objID);
+ _gui->setWindowTitle(invID, _world->getText(objID, objID, objID));
+ _gui->updateWindowInfo(invID, objID, _world->getChildren(objID, true));
+ _gui->updateWindow(invID, _world->getObjAttr(objID, kAttrContainerOpen));
+ }
+}
+
+void MacVentureEngine::closeObject(ObjID objID) {
+ warning("closeObject: not fully implemented");
+ _gui->tryCloseWindow(getObjWindow(objID));
+ return;
+}
+
+void MacVentureEngine::checkObject(QueuedObject old) {
+ bool hasChanged = false;
+ debugC(3, kMVDebugMain, "Check Object[%d] parent[%d] x[%d] y[%d]",
+ old.object,
+ old.parent,
+ old.x,
+ old.y);
+ ObjID id = old.object;
+ if (id == 1) {
+ if (old.parent != _world->getObjAttr(id, kAttrParentObject)) {
+ enqueueObject(kSetToPlayerParent, id);
+ }
+ if (old.offscreen != _world->getObjAttr(id, kAttrInvisible) ||
+ old.invisible != _world->getObjAttr(id, kAttrUnclickable)) {
+ updateWindow(findParentWindow(id));
+ }
+ } else if (old.parent != _world->getObjAttr(id, kAttrParentObject) ||
+ old.x != _world->getObjAttr(id, kAttrPosX) ||
+ old.y != _world->getObjAttr(id, kAttrPosY)) {
+ WindowReference oldWin = getObjWindow(old.parent);
+ if (oldWin) {
+ _gui->removeChild(oldWin, id);
+ hasChanged = true;
+ }
+
+ WindowReference newWin = findParentWindow(id);
+ if (newWin) {
+ _gui->addChild(newWin, id);
+ hasChanged = true;
+ }
+ } else if (old.offscreen != _world->getObjAttr(id, kAttrInvisible) ||
+ old.invisible != _world->getObjAttr(id, kAttrUnclickable)) {
+ updateWindow(findParentWindow(id));
+ }
+
+ if (_world->getObjAttr(id, kAttrIsExit)) {
+ if (hasChanged ||
+ old.hidden != _world->getObjAttr(id, kAttrHiddenExit) ||
+ old.exitx != _world->getObjAttr(id, kAttrExitX) ||
+ old.exity != _world->getObjAttr(id, kAttrExitY))
+ _gui->updateExit(id);
+ }
+ WindowReference win = getObjWindow(id);
+ ObjID cur = id;
+ ObjID root = _world->getObjAttr(1, kAttrParentObject);
+ while (cur != root) {
+ if (cur == 0 || !_world->getObjAttr(cur, kAttrContainerOpen)) {
+ break;
+ }
+ cur = _world->getObjAttr(cur, kAttrParentObject);
+ }
+ if (cur == root) {
+ if (win) {
+ return;
+ }
+ enqueueObject(kOpenWindow, id); //open
+ } else {
+ if (!win) {
+ return;
+ }
+ enqueueObject(kCloseWindow, id); //close
+ }
+
+ // Update children
+ Common::Array<ObjID> children = _world->getChildren(id, true);
+ for (uint i = 0; i < children.size(); i++) {
+ enqueueObject(kUpdateObject, children[i]);
+ }
+}
+
+void MacVentureEngine::reflectSwap(ObjID fromID, ObjID toID) {
+ WindowReference from = getObjWindow(fromID);
+ WindowReference to = getObjWindow(toID);
+ WindowReference tmp = to;
+ debugC(3, kMVDebugMain, "Swap Object[%d] to Object[%d], from win[%d] to win[%d] ",
+ fromID, toID, from, to);
+
+ if (!to) {
+ tmp = from;
+ }
+ if (tmp) {
+ Common::String newTitle = _world->getText(toID, 0, 0); // Ignores src and targ in the original
+ _gui->setWindowTitle(tmp, newTitle);
+ _gui->updateWindowInfo(tmp, toID, _world->getChildren(toID, true));
+ updateWindow(tmp);
+ }
+}
+
+void MacVentureEngine::toggleExits() {
+ Common::Array<ObjID> exits = _currentSelection;
+ while (!exits.empty()) {
+ ObjID obj = exits.front();
+ exits.remove_at(0);
+ highlightExit(obj);
+ updateWindow(findParentWindow(obj));
+ }
+}
+
+void MacVentureEngine::zoomObject(ObjID objID) {
+ warning("zoomObject: unimplemented");
+}
+
+bool MacVentureEngine::isObjEnqueued(ObjID objID) {
+ Common::Array<QueuedObject>::const_iterator it;
+ for (it = _objQueue.begin(); it != _objQueue.end(); it++) {
+ if ((*it).object == objID) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool MacVentureEngine::isGameRunning() {
+ return (_gameState == kGameStateInit || _gameState == kGameStatePlaying);
+}
+
+ControlAction MacVenture::MacVentureEngine::referenceToAction(ControlType id) {
+ switch (id) {
+ case MacVenture::kControlExitBox:
+ return kActivateObject;//?? Like this in the original
+ case MacVenture::kControlExamine:
+ return kExamine;
+ case MacVenture::kControlOpen:
+ return kOpen;
+ case MacVenture::kControlClose:
+ return kClose;
+ case MacVenture::kControlSpeak:
+ return kSpeak;
+ case MacVenture::kControlOperate:
+ return kOperate;
+ case MacVenture::kControlGo:
+ return kGo;
+ case MacVenture::kControlHit:
+ return kHit;
+ case MacVenture::kControlConsume:
+ return kConsume;
+ default:
+ return kNoCommand;
+ }
+}
+
+// Data retrieval
+
+bool MacVentureEngine::isPaused() {
+ return _paused;
+}
+
+bool MacVentureEngine::needsClickToContinue() {
+ return _clickToContinue;
+}
+
+Common::String MacVentureEngine::getCommandsPausedString() const {
+ return Common::String("Click to continue");
+}
+
+Common::String MacVentureEngine::getFilePath(FilePathID id) const {
+ if (id <= 3) { // We don't want a file in the subdirectory
+ return _filenames->getString(id);
+ } else { // We want a game file
+ return _filenames->getString(3) + "/" + _filenames->getString(id);
+ }
+}
+
+bool MacVentureEngine::isOldText() const {
+ return _oldTextEncoding;
+}
+
+const HuffmanLists *MacVentureEngine::getDecodingHuffman() const {
+ return _textHuffman;
+}
+
+uint32 MacVentureEngine::randBetween(uint32 min, uint32 max) {
+ return _rnd->getRandomNumber(max - min) + min;
+}
+
+uint32 MacVentureEngine::getInvolvedObjects() {
+ // If there is no valid control selected, we return a number too big
+ // to be useful. There is no control that uses that many objects.
+ return (_selectedControl ? getGlobalSettings()._cmdArgCnts[_selectedControl - 1] : 3000);
+}
+
+Common::Point MacVentureEngine::getObjPosition(ObjID objID) {
+ return Common::Point(_world->getObjAttr(objID, kAttrPosX), _world->getObjAttr(objID, kAttrPosY));
+}
+
+bool MacVentureEngine::isObjVisible(ObjID objID) {
+ return _world->getObjAttr(objID, kAttrInvisible) == 0;
+}
+
+bool MacVentureEngine::isObjClickable(ObjID objID) {
+ return _world->getObjAttr(objID, kAttrUnclickable) == 0;
+}
+
+bool MacVentureEngine::isObjSelected(ObjID objID) {
+ int idx = findObjectInArray(objID, _currentSelection);
+ return idx != -1;
+}
+
+bool MacVentureEngine::isObjExit(ObjID objID) {
+ return _world->getObjAttr(objID, kAttrIsExit);
+}
+
+bool MacVentureEngine::isHiddenExit(ObjID objID) {
+ return _world->getObjAttr(objID, kAttrHiddenExit);
+}
+
+Common::Point MacVentureEngine::getObjExitPosition(ObjID objID) {
+ uint x = _world->getObjAttr(objID, kAttrExitX);
+ uint y = _world->getObjAttr(objID, kAttrExitY);
+ return Common::Point(x, y);
+}
+
+ObjID MacVentureEngine::getParent(ObjID objID) {
+ return _world->getObjAttr(objID, kAttrParentObject);
+}
+
+Common::Rect MacVentureEngine::getObjBounds(ObjID objID) {
+ Common::Point pos = getObjPosition(objID);
+
+ WindowReference win = findParentWindow(objID);
+ if (win != kNoWindow) { // If it's not in a window YET, we don't really care about the border
+ BorderBounds bounds = borderBounds(_gui->getWindowData(win).type); // HACK
+ pos.x += bounds.leftOffset;
+ pos.y += bounds.topOffset;
+ }
+ Common::Point measures = _gui->getObjMeasures(objID);
+ uint w = measures.x;
+ uint h = measures.y;
+ return Common::Rect(pos.x, pos.y, pos.x + w, pos.y + h);
+}
+
+uint MacVentureEngine::getOverlapPercent(ObjID one, ObjID other) {
+ // If it's not the same parent, there's 0 overlap
+ if (_world->getObjAttr(one, kAttrParentObject) !=
+ _world->getObjAttr(other, kAttrParentObject))
+ return 0;
+
+ Common::Rect oneBounds = getObjBounds(one);
+ Common::Rect otherBounds = getObjBounds(other);
+ if (otherBounds.intersects(oneBounds) ||
+ oneBounds.intersects(otherBounds)) {
+ uint areaOne = oneBounds.width() * oneBounds.height();
+ uint areaOther = otherBounds.width() * otherBounds.height();
+ return (areaOne != 0) ? (areaOther * 100 / areaOne) : 0;
+ }
+ return 0;
+}
+
+WindowReference MacVentureEngine::getObjWindow(ObjID objID) {
+ return _gui->getObjWindow(objID);
+}
+
+WindowReference MacVentureEngine::findParentWindow(ObjID objID) {
+ if (objID == 1) {
+ return kSelfWindow;
+ }
+ ObjID parent = _world->getObjAttr(objID, kAttrParentObject);
+ if (parent == 0) {
+ return kNoWindow;
+ }
+ return getObjWindow(parent);
+}
+
+Common::Point MacVentureEngine::getDeltaPoint() {
+ return _deltaPoint;
+}
+
+ObjID MacVentureEngine::getDestObject() {
+ return _destObject;
+}
+
+ControlAction MacVentureEngine::getSelectedControl() {
+ return _selectedControl;
+}
+
+// Data loading
+
+bool MacVentureEngine::loadGlobalSettings() {
+ Common::MacResIDArray resArray;
+
+ if ((resArray = _resourceManager->getResIDArray(MKTAG('G', 'N', 'R', 'L'))).size() == 0)
+ return false;
+
+ Common::SeekableReadStream *res;
+ res = _resourceManager->getResource(MKTAG('G', 'N', 'R', 'L'), kGlobalSettingsID);
+ if (res) {
+ _globalSettings = new GlobalSettings();
+ _globalSettings->loadSettings(res);
+ delete res;
+ return true;
+ }
+ return false;
+}
+
+bool MacVentureEngine::loadTextHuffman() {
+ Common::MacResIDArray resArray;
+ Common::SeekableReadStream *res;
+
+ if ((resArray = _resourceManager->getResIDArray(MKTAG('G', 'N', 'R', 'L'))).size() == 0)
+ return false;
+
+ res = _resourceManager->getResource(MKTAG('G', 'N', 'R', 'L'), kTextHuffmanTableID);
+ if (res) {
+ uint32 numEntries = res->readUint16BE();
+ res->readUint16BE(); // Skip
+
+ uint32 *masks = new uint32[numEntries];
+ for (uint i = 0; i < numEntries - 1; i++) {
+ // For some reason there are one lass mask than entries
+ masks[i] = res->readUint16BE();
+ }
+
+ uint32 *lengths = new uint32[numEntries];
+ for (uint i = 0; i < numEntries; i++) {
+ lengths[i] = res->readByte();
+ }
+
+ uint32 *values = new uint32[numEntries];
+ for (uint i = 0; i < numEntries; i++) {
+ values[i] = res->readByte();
+ }
+
+ _textHuffman = new HuffmanLists(numEntries, lengths, masks, values);
+ debugC(4, kMVDebugMain, "Text is huffman-encoded");
+
+ delete res;
+ delete[] masks;
+ delete[] lengths;
+ delete[] values;
+ return true;
+ }
+ return false;
+}
+
+// Global Settings
+GlobalSettings::GlobalSettings() {
+}
+
+GlobalSettings::~GlobalSettings() {
+
+}
+
+void GlobalSettings::loadSettings(Common::SeekableReadStream *dataStream) {
+ _numObjects = dataStream->readUint16BE();
+ _numGlobals = dataStream->readUint16BE();
+ _numCommands = dataStream->readUint16BE();
+ _numAttributes = dataStream->readUint16BE();
+ _numGroups = dataStream->readUint16BE();
+ dataStream->readUint16BE(); // unknown
+ _invTop = dataStream->readUint16BE();
+ _invLeft = dataStream->readUint16BE();
+ _invWidth = dataStream->readUint16BE();
+ _invHeight = dataStream->readUint16BE();
+ _invOffsetY = dataStream->readUint16BE();
+ _invOffsetX = dataStream->readSint16BE();
+ _defaultFont = dataStream->readUint16BE();
+ _defaultSize = dataStream->readUint16BE();
+
+ uint8 *attrIndices = new uint8[_numAttributes];
+ dataStream->read(attrIndices, _numAttributes);
+ _attrIndices = Common::Array<uint8>(attrIndices, _numAttributes);
+ delete[] attrIndices;
+
+ for (int i = 0; i < _numAttributes; i++) {
+ _attrMasks.push_back(dataStream->readUint16BE());
+ }
+
+ uint8 *attrShifts = new uint8[_numAttributes];
+ dataStream->read(attrShifts, _numAttributes);
+ _attrShifts = Common::Array<uint8>(attrShifts, _numAttributes);
+ delete[] attrShifts;
+
+ uint8 *cmdArgCnts = new uint8[_numCommands];
+ dataStream->read(cmdArgCnts, _numCommands);
+ _cmdArgCnts = Common::Array<uint8>(cmdArgCnts, _numCommands);
+ delete[] cmdArgCnts;
+
+ uint8 *commands = new uint8[_numCommands];
+ dataStream->read(commands, _numCommands);
+ _commands = Common::Array<uint8>(commands, _numCommands);
+ delete[] commands;
+}
+
+} // End of namespace MacVenture