aboutsummaryrefslogtreecommitdiff
path: root/engines/m4/mads_scene.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/m4/mads_scene.cpp')
-rw-r--r--engines/m4/mads_scene.cpp1272
1 files changed, 0 insertions, 1272 deletions
diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp
deleted file mode 100644
index e2d034f6d1..0000000000
--- a/engines/m4/mads_scene.cpp
+++ /dev/null
@@ -1,1272 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "common/system.h"
-#include "common/textconsole.h"
-
-#include "m4/mads_scene.h"
-#include "m4/dialogs.h"
-#include "m4/globals.h"
-#include "m4/scene.h"
-#include "m4/events.h"
-#include "m4/graphics.h"
-#include "m4/rails.h"
-#include "m4/font.h"
-#include "m4/m4_views.h"
-#include "m4/mads_views.h"
-#include "m4/compression.h"
-#include "m4/staticres.h"
-#include "m4/animation.h"
-
-namespace M4 {
-
-static const int INV_ANIM_FRAME_SPEED = 2;
-static const int INVENTORY_X = 160;
-static const int INVENTORY_Y = 159;
-static const int SCROLLER_DELAY = 200;
-
-//--------------------------------------------------------------------------
-
-void SceneNode::load(Common::SeekableReadStream *stream) {
- // Get the next data block
- pt.x = stream->readUint16LE();
- pt.y = stream->readUint16LE();
-
- for (int i = 0; i < MAX_ROUTE_NODES; ++i)
- indexes[i] = stream->readUint16LE();
-}
-
-//--------------------------------------------------------------------------
-
-MadsScene::MadsScene(MadsEngine *vm): _sceneResources(), Scene(vm, &_sceneResources), MadsView(this) {
- _vm = vm;
- _activeAnimation = NULL;
-
- MadsView::_bgSurface = Scene::_backgroundSurface;
- MadsView::_depthSurface = Scene::_walkSurface;
- _interfaceSurface = new MadsInterfaceView(vm);
- _showMousePos = false;
- _mouseMsgIndex = -1;
- _previousScene = -1;
-}
-
-MadsScene::~MadsScene() {
- delete _activeAnimation;
- _activeAnimation = NULL;
- leaveScene();
- _vm->_viewManager->deleteView(_interfaceSurface);
-}
-
-/**
- * Secondary scene loading code
- */
-void MadsScene::loadScene2(const char *aaName, int sceneNumber) {
- // TODO: Completely finish
- _madsVm->globals()->previousScene = _madsVm->globals()->sceneNumber;
- _madsVm->globals()->sceneNumber = sceneNumber;
-
- _spriteSlots.clear();
- _sequenceList.clear();
- _kernelMessages.clear();
-
- // Load up the properties for the scene
- _sceneResources.load(_currentScene, NULL, 0/*word_83546*/, _walkSurface, _backgroundSurface);
-
- // Load scene walk paths
- loadSceneCodes(_currentScene);
-
- // Initialize the scene animation
- uint16 flags = 0x4100;
- if (_madsVm->globals()->_config.textWindowStill)
- flags |= 0x200;
-
- _sceneAnimation->initialize(aaName, flags, _interfaceSurface, NULL);
-}
-
-/**
- * Existing ScummVM code that needs to be eventually replaced with MADS code
- */
-void MadsScene::loadSceneTemporary() {
- /* Existing code that eventually needs to be replaced with the proper MADS code */
- // Set system palette entries
- _vm->_palette->blockRange(0, 18);
- RGB8 sysColors[3] = { {0x1f<<2, 0x2d<<2, 0x31<<2}, {0x24<<2, 0x37<<2, 0x3a<<2},
- {0x00<<2, 0x10<<2, 0x16<<2}};
- _vm->_palette->setPalette(&sysColors[0], 4, 3);
-
- _interfaceSurface->initialize();
-
- loadSceneHotspots(_currentScene);
-
- _action.clear();
-}
-
-void MadsScene::loadScene(int sceneNumber) {
- // Close the menu if it's active
- View *mainMenu = _vm->_viewManager->getView(VIEWID_MAINMENU);
- if (mainMenu != NULL) {
- _vm->_viewManager->deleteView(mainMenu);
- }
-
- // Handle common scene setting
- Scene::loadScene(sceneNumber);
- _madsVm->globals()->_nextSceneId = sceneNumber;
-
- // Existing ScummVM code that needs to be eventually replaced with MADS code
- loadSceneTemporary();
-
- _madsVm->_player._spritesChanged = true;
- _madsVm->globals()->clearQuotes();
- _dynamicHotspots.reset();
-
- // Signal the script engine what scene is to be active
- _sceneLogic.selectScene(sceneNumber);
-
- // Add the scene if necessary to the list of scenes that have been visited
- _vm->globals()->addVisitedScene(sceneNumber);
-
- if (_vm->getGameType() == GType_RexNebular)
- _sceneLogic.setupScene();
-
- // TODO: Unknown code
-
- // Secondary scene load routine
- if (_vm->getGameType() == GType_RexNebular)
- // Secondary scene load routine
- loadScene2("*I0.AA", sceneNumber);
-
- _madsVm->_player.loadSprites(NULL);
-
- switch (_madsVm->globals()->_config.screenFades) {
- case 0:
- _abortTimers2 = 2;
- break;
- case 2:
- _abortTimers2 = 21;
- break;
- default:
- _abortTimers2 = 20;
- break;
- }
- _abortTimers = 0;
- _abortTimersMode2 = ABORTMODE_1;
-
-
- // Do any scene specific setup
- if (_vm->getGameType() == GType_RexNebular)
- _sceneLogic.doEnterScene();
-
- // Miscellaneous player setup
- //_madsVm->_player._destPos = _madsVm->_player._destPos;
- _madsVm->_player._newDirection = _madsVm->_player._direction;
- _madsVm->_player.setupFrame();
- _madsVm->_player.updateFrame();
-
- // Purge resources
- _vm->res()->purge();
-}
-
-void MadsScene::loadSceneHotspots(int sceneNumber) {
- char filename[kM4MaxFilenameSize];
- sprintf(filename, "rm%i.hh", sceneNumber);
- MadsPack hotSpotData(filename, _vm);
- Common::SeekableReadStream *hotspotStream = hotSpotData.getItemStream(0);
-
- int hotspotCount = hotspotStream->readUint16LE();
- delete hotspotStream;
-
- hotspotStream = hotSpotData.getItemStream(1);
-
- // Clear current hotspot lists
- _sceneResources.hotspots->clear();
- _sceneResources.hotspots->loadHotSpots(hotspotStream, hotspotCount);
-
- delete hotspotStream;
-}
-
-void MadsScene::leaveScene() {
- _sceneResources.hotspots->clear();
- _sceneResources.dynamicHotspots->clear();
-
- delete _sceneResources.hotspots;
- delete _sceneResources.dynamicHotspots;
- delete _walkSurface;
-
- if (_activeAnimation) {
- delete _activeAnimation;
- _activeAnimation = NULL;
- }
-
- Scene::leaveScene();
-}
-
-void MadsScene::show() {
- Scene::show();
- _vm->_viewManager->addView(_interfaceSurface);
-}
-
-void MadsScene::loadSceneCodes(int sceneNumber, int index) {
- char filename[kM4MaxFilenameSize];
- Common::SeekableReadStream *sceneS;
-
- if (_vm->getGameType() == GType_Phantom || _vm->getGameType() == GType_DragonSphere) {
- sprintf(filename, "rm%i.ww%i", sceneNumber, index);
- MadsPack walkData(filename, _vm);
- sceneS = walkData.getItemStream(0);
- _walkSurface->loadCodesMads(sceneS);
- _vm->res()->toss(filename);
- }
-}
-
-void MadsScene::mouseMove(int x, int y) {
- HotSpot *currentHotSpot = _sceneResources.hotspots->findByXY(x, y);
- if (currentHotSpot != NULL) {
- _vm->_mouse->setCursorNum(currentHotSpot->getCursor());
-
- _action._selectedRow = -1;
- _action._actionMode = ACTMODE_NONE;
- _action._actionMode2 = ACTMODE2_4;
- _action._hotspotId = currentHotSpot->getIndex();
-
- } else {
- _vm->_mouse->setCursorNum(0);
- }
-}
-
-void MadsScene::leftClick(int x, int y) {
- // TODO: figure out the rest of Scene_leftClick, and implements relevant parts in the interface class
- _action._v86F4C = -1;
- _action._v86F4E = 0;
- _customDest = _madsVm->_mouse->currentPos();
- _action._selectedAction = -1;
- _action._v86F4A = true;
-}
-
-void MadsScene::rightClick(int x, int y) {
- if (_vm->getGameType() == GType_RexNebular) {
- // ***DEBUG*** - sample dialog display
- int idx = 3; //_madsVm->_globals->messageIndexOf(0x277a);
- const char *msg = _madsVm->globals()->loadMessage(idx);
- Dialog *dlg = new Dialog(_vm, msg, "TEST DIALOG");
- _vm->_viewManager->addView(dlg);
- _vm->_viewManager->moveToFront(dlg);
- }
-}
-
-void MadsScene::setAction(int action, int objectId) {
- VALIDATE_MADS;
-
- error("todo");
- // TODO: Actually executing actions directly for objects. Also, some object actions are special in that
- // a second object can be selected, as in 'use gun to shoot person', with requires a target
-/*
- // Set up the new action
- strcpy(statusText, _madsVm->globals()->getVocab(action));
- statusText[0] = toupper(statusText[0]); // capitalize first letter
-
- if (objectId != -1) {
- MadsObject *obj = _madsVm->globals()->getObject(objectId);
- sprintf(statusText + strlen(statusText), " %s", _madsVm->globals()->getVocab(obj->descId));
- } else {
- _currentAction = action;
- }
-*/
-// setStatusText(statusText);
-}
-
-/**
- * Draws all the elements of the scene
- */
-void MadsScene::drawElements() {
- refresh();
-
- // Copy the user interface surface onto the surface
- _interfaceSurface->copyTo(this, 0, this->height() - _interfaceSurface->height());
-}
-
-
-void MadsScene::update() {
- // Draw all the various elements
- drawElements();
-
- _action.set();
-}
-
-void MadsScene::updateState() {
- if (!_abortTimers && !_madsVm->_player._unk3) {
- if (_dynamicHotspots._changed)
- _dynamicHotspots.refresh();
-
-// int v = (_madsVm->_player._stepEnabled && !_action._startWalkFlag && !_abortTimers2) ? 1 : 0;
-// _screenObjects.check(v, false);
- }
-
- // Handle starting off any selected action
- bool doPreAction = false;
- if ((_action._selectedAction != 0) && _madsVm->_player._stepEnabled &&
- !_action._startWalkFlag && !_abortTimers && !_madsVm->_player._unk3) {
- // Start the action
- _action.startAction();
-
- if (_action._action.verbId == kVerbLookAt) {
- _action._action.verbId = kVerbLook;
- _action._savedFields.selectedRow = 0;
- }
- doPreAction = true;
- }
- if (doPreAction || ((_abortTimers != 0) && (_abortTimersMode == ABORTMODE_2)))
- doPreactions();
-
- checkStartWalk();
-
- if (_action._inProgress && !_madsVm->_player._moving && !_action._startWalkFlag &&
- (_madsVm->_player._newDirection == _madsVm->_player._direction)) {
- // Reached the end of action movement, so ready to actually do action
- doAction();
- } else if ((_abortTimers != 0) && (_abortTimersMode == ABORTMODE_0))
- // Do an action designated by scripts
- doAction();
-
- bool freeFlag = false;
- if (_currentScene != _nextScene)
- freeFlag = true;
- else {
- doSceneStep();
-
- if (_currentScene != _nextScene)
- freeFlag = true;
- else {
- // Update the player
- _madsVm->_player.nextFrame();
-
- // Handle updating the animation
- if (!_abortTimers && (_activeAnimation))
- _activeAnimation->update();
-
- // Handle refreshing the mouse position display
- if (_mouseMsgIndex != -1)
- _madsVm->scene()->_kernelMessages.remove(_mouseMsgIndex);
- if (_showMousePos) {
- char buffer[20];
- sprintf(buffer, "(%d,%d)", _madsVm->_mouse->currentPos().x, _madsVm->_mouse->currentPos().y);
-
- _mouseMsgIndex = _madsVm->scene()->_kernelMessages.add(Common::Point(5, 5), 0x203, 0, 0, 1, buffer);
- }
- }
- }
-
- if (_madsVm->globals()->_config.easyMouse)
- _action.refresh();
-
- if ((_activeAnimation) && !_abortTimers) {
- _activeAnimation->update();
- if (((MadsAnimation *) _activeAnimation)->freeFlag() || freeFlag) {
- delete _activeAnimation;
- _activeAnimation = NULL;
- }
- }
-
- MadsView::update();
-
- // Remove the animation if it's been completed
- if ((_activeAnimation) && ((MadsAnimation *)_activeAnimation)->freeFlag())
- freeAnimation();
-
- if ((_action._selectedAction != 0) || !_madsVm->_player._stepEnabled) {
- _action.clear();
- _action._selectedAction = 0;
- }
-}
-
-void MadsScene::checkStartWalk() {
- if (_action._startWalkFlag && _action._walkFlag) {
- _madsVm->_player.setDest(_destPos.x, _destPos.y, _destFacing);
- _action._startWalkFlag = false;
- }
-}
-
-void MadsScene::doPreactions() {
- if ((_screenObjects._v832EC == 0) || (_screenObjects._v832EC == 2)) {
- _abortTimersMode2 = ABORTMODE_2;
- _action.checkAction();
-
- _sceneLogic.doPreactions();
-
- if (_abortTimersMode == ABORTMODE_2)
- _abortTimers = 0;
- }
-}
-
-void MadsScene::doSceneStep() {
- // Step through the scene
- _sceneLogic.doSceneStep();
-
- _madsVm->_player.step();
- _madsVm->_player._unk3 = 0;
-
- if (_abortTimersMode == ABORTMODE_1)
- _abortTimers = 0;
-}
-
-void MadsScene::doAction() {
- AbortTimerMode mode = ABORTMODE_0;
- _abortTimersMode2 = mode;
-
- if ((_action._inProgress || (_abortTimers != 0)) && !_action._v8453A) {
- _sceneLogic.doAction();
- mode = _action._inProgress ? ABORTMODE_0 : ABORTMODE_1;
- }
-
- if (_screenObjects._v832EC)
- _action._inProgress = false;
- else {
- if ((_action._inProgress || (_abortTimers != 0)) && (mode == ABORTMODE_0) && (_action._v8453A == mode)) {
- // TODO: sound_fn_p();
- mode = _action._inProgress ? ABORTMODE_0 : ABORTMODE_1;
-
- }
-
- if ((_action._inProgress || (_abortTimers != 0)) && (mode == ABORTMODE_0) && (_action._v8453A == mode)) {
- // Perform a core scene-indepedant action on an object
- // object_do_action
- }
- }
-
-}
-
-
-/**
- * Does extra work at cleaning up the animation, and then deletes it
- */
-void MadsScene::freeAnimation() {
- if (!_activeAnimation)
- return;
-
- MadsAnimation *anim = (MadsAnimation *)_activeAnimation;
- if (anim->freeFlag()) {
- _madsVm->scene()->_spriteSlots.clear();
- _madsVm->scene()->_spriteSlots.fullRefresh();
- _madsVm->scene()->_sequenceList.scan();
- }
-
- if (_madsVm->_player._visible) {
- _madsVm->_player._forceRefresh = true;
- _madsVm->_player.update();
- }
-
- delete _activeAnimation;
- _activeAnimation = NULL;
-}
-
-
-int MadsScene::loadSceneSpriteSet(const char *setName) {
- char resName[100];
- strcpy(resName, setName);
-
- // Append a '.SS' if it doesn't alreayd have an extension
- if (!strchr(resName, '.'))
- strcat(resName, ".SS");
-
- return _spriteSlots.addSprites(resName);
-}
-
-enum boxSprites {
- topLeft = 0,
- topRight = 1,
- bottomLeft = 2,
- bottomRight = 3,
- left = 4,
- right = 5,
- top = 6,
- bottom = 7,
- topMiddle = 8,
- filler1 = 9,
- filler2 = 10
- // TODO: finish this
-};
-
-// TODO: calculate width and height, show text, show face if it exists
-// TODO: this has been tested with Dragonsphere only, there are some differences
-// in the sprites used in Phantom
-void MadsScene::showMADSV2TextBox(char *text, int x, int y, char *faceName) {
- int repeatX = 40; // FIXME: this is hardcoded
- int repeatY = 30; // FIXME: this is hardcoded
- int curX = x, curY = y;
- int topRightX = x; // TODO: this is probably not needed
- Common::SeekableReadStream *data = _vm->res()->get("box.ss");
- SpriteAsset *boxSprites = new SpriteAsset(_vm, data, data->size(), "box.ss");
- _vm->res()->toss("box.ss");
-
- RGBList *palData = new RGBList(boxSprites->getColorCount(), boxSprites->getPalette(), true);
- _vm->_palette->addRange(palData);
-
- for (int i = 0; i < boxSprites->getCount(); i++)
- boxSprites->getFrame(i)->translate(palData); // sprite pixel translation
-
- // Top left corner
- boxSprites->getFrame(topLeft)->copyTo(_backgroundSurface, x, curY);
- curX += boxSprites->getFrame(topLeft)->width();
-
- // Top line
- for (int i = 0; i < repeatX; i++) {
- boxSprites->getFrame(top)->copyTo(_backgroundSurface, curX, curY + 3);
- curX += boxSprites->getFrame(top)->width();
- }
-
- // Top right corner
- boxSprites->getFrame(topRight)->copyTo(_backgroundSurface, curX, curY);
- topRightX = curX;
-
- // Top middle
- // FIXME: the transparent color for this is also the black border color
- boxSprites->getFrame(topMiddle)->copyTo(_backgroundSurface,
- x + (curX - x) / 2 - boxSprites->getFrame(topMiddle)->width() / 2,
- curY - 5, 167);
- curX = x;
- curY += boxSprites->getFrame(topLeft)->height();
-
- // -----------------------------------------------------------------------------------------------
-
- // Draw contents
- for (int i = 0; i < repeatY; i++) {
- for (int j = 0; j < repeatX; j++) {
- if (j == 0) {
- boxSprites->getFrame(left)->copyTo(_backgroundSurface, curX + 3, curY);
- curX += boxSprites->getFrame(left)->width();
- } else if (j == repeatX - 1) {
- curX = topRightX - 2;
- boxSprites->getFrame(right)->copyTo(_backgroundSurface, curX + 3, curY + 1);
- } else {
- // TODO: the background of the contents follows a pattern which is not understood yet
- if (j % 2 == 0) {
- boxSprites->getFrame(filler1)->copyTo(_backgroundSurface, curX + 3, curY);
- curX += boxSprites->getFrame(filler1)->width();
- } else {
- boxSprites->getFrame(filler2)->copyTo(_backgroundSurface, curX + 3, curY);
- curX += boxSprites->getFrame(filler2)->width();
- }
- }
- } // for j
- curX = x;
- curY += boxSprites->getFrame(left)->height();
- } // for i
-
- // -----------------------------------------------------------------------------------------------
- curX = x;
-
- // Bottom left corner
- boxSprites->getFrame(bottomLeft)->copyTo(_backgroundSurface, curX, curY);
- curX += boxSprites->getFrame(bottomLeft)->width();
-
- // Bottom line
- for (int i = 0; i < repeatX; i++) {
- boxSprites->getFrame(bottom)->copyTo(_backgroundSurface, curX, curY + 1);
- curX += boxSprites->getFrame(bottom)->width();
- }
-
- // Bottom right corner
- boxSprites->getFrame(bottomRight)->copyTo(_backgroundSurface, curX, curY + 1);
-}
-
-void MadsScene::loadAnimation(const Common::String &animName, int abortTimers) {
- if (_activeAnimation)
- error("Multiple active animations are not allowed");
-
- MadsAnimation *anim = new MadsAnimation(_vm, this);
- anim->load(animName.c_str(), abortTimers);
- _activeAnimation = anim;
-}
-
-bool MadsScene::getDepthHighBit(const Common::Point &pt) {
- const byte *p = _depthSurface->getBasePtr(pt.x, pt.y);
- if (_sceneResources._depthStyle == 2)
- return ((*p << 4) & 0x80) != 0;
-
- return (*p & 0x80) != 0;
-}
-
-bool MadsScene::getDepthHighBits(const Common::Point &pt) {
- if (_sceneResources._depthStyle == 2)
- return 0;
-
- const byte *p = _depthSurface->getBasePtr(pt.x, pt.y);
- return (*p & 0x70) >> 4;
-}
-
-/*--------------------------------------------------------------------------*/
-
-void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Surface *depthSurface, M4Surface *surface) {
- char buffer1[80];
- const char *sceneName;
-
- // TODO: Initialize spriteSet / xp_list
-
- if (sceneNumber > 0) {
- sceneName = MADSResourceManager::getResourceName(RESPREFIX_RM, sceneNumber, ".DAT");
- } else {
- strcpy(buffer1, "*");
- strcat(buffer1, resName);
- sceneName = buffer1; // TODO: Check whether this needs to be converted to 'HAG form'
- }
-
- Common::SeekableReadStream *rawStream = _vm->_resourceManager->get(sceneName);
- MadsPack sceneInfo(rawStream);
-
- // Chunk 0:
- // Basic scene info
- Common::SeekableReadStream *stream = sceneInfo.getItemStream(0);
-
- if (_vm->getGameType() == GType_RexNebular) {
- int resSceneId = stream->readUint16LE();
- assert(resSceneId == sceneNumber);
- } else {
- char roomFilename[10];
- char roomFilenameExpected[10];
- sprintf(roomFilenameExpected, "*RM%d", sceneNumber);
-
- stream->read(roomFilename, 6);
- roomFilename[6] = 0;
- assert(!strcmp(roomFilename, roomFilenameExpected));
- }
-
- // TODO: The following is wrong for Phantom/Dragon
- _artFileNum = stream->readUint16LE();
- _depthStyle = stream->readUint16LE();
- _width = stream->readUint16LE();
- _height = stream->readUint16LE();
-
- stream->skip(24);
-
- int nodeCount = stream->readUint16LE();
- _yBandsEnd = stream->readUint16LE();
- _yBandsStart = stream->readUint16LE();
- _maxScale = stream->readSint16LE();
- _minScale = stream->readSint16LE();
- for (int i = 0; i < DEPTH_BANDS_SIZE; ++i)
- _depthBands[i] = stream->readUint16LE();
- stream->skip(2);
-
- // Load in any scene objects
- for (int i = 0; i < nodeCount; ++i) {
- SceneNode rec;
- rec.load(stream);
- _nodes.push_back(rec);
- }
- for (int i = 0; i < 20 - nodeCount; ++i)
- stream->skip(48);
-
- // Add two extra nodes in that will be used for player movement
- for (int i = 0; i < 2; ++i) {
- SceneNode rec;
- _nodes.push_back(rec);
- }
-
- int setCount = stream->readUint16LE();
- stream->readUint16LE();
- for (int i = 0; i < setCount; ++i) {
- char buffer2[64];
- Common::String s(buffer2, 64);
- _setNames.push_back(s);
- }
-
- delete stream;
-
- // Initialize a copy of the surfaces if they weren't provided
- bool dsFlag = false, ssFlag = false;
- if (!surface) {
- surface = new M4Surface(_width, _height);
- ssFlag = true;
- } else if ((_width != surface->width()) || (_height != surface->height()))
- surface->setSize(_width, _height);
-
- if (!depthSurface) {
- depthSurface = new M4Surface(_width, _height);
- dsFlag = true;
- } else if ((_width != depthSurface->width()) || (_height != depthSurface->height()))
- depthSurface->setSize(_width, _height);
-
-
- // For Rex Nebular, read in the scene's compressed walk surface information
- if (_vm->getGameType() == GType_RexNebular) {
- assert(depthSurface);
- stream = sceneInfo.getItemStream(1);
- byte *walkData = (byte *)malloc(stream->size());
- stream->read(walkData, stream->size());
-
- // For Rex Nebular, the walk areas are part of the scene info
- byte *destP = depthSurface->getBasePtr(0, 0);
- const byte *srcP = walkData;
- byte runLength;
-
- // Run length encoded depth data
- while ((runLength = *srcP++) != 0) {
- if (_depthStyle == 2) {
- // 2-bit depth pixels
- byte byteVal = *srcP++;
- for (int byteCtr = 0; byteCtr < runLength; ++byteCtr) {
- byte v = byteVal;
- for (int bitCtr = 0; bitCtr < 4; ++bitCtr, v >>= 2)
- *destP++ = (((v & 1) + 1) << 3) - 1;
- }
- } else {
- // 8-bit depth pixels
- Common::fill(destP, destP + runLength, *srcP++);
- destP += runLength;
- }
- }
-
- free(walkData);
- delete stream;
- }
-
- _vm->_resourceManager->toss(sceneName);
-
- // Load the surface artwork
- surface->loadBackground(_artFileNum);
-
- // Final cleanup
- if (ssFlag)
- delete surface;
- if (dsFlag)
- delete depthSurface;
-}
-
-void MadsSceneResources::setRouteNode(int nodeIndex, const Common::Point &pt, M4Surface *depthSurface) {
- int flags, hypotenuse;
-
- _nodes[nodeIndex].pt = pt;
-
- // Recalculate inter-node lengths
- for (uint idx = 0; idx < _nodes.size(); ++idx) {
- int entry;
- if (idx == (uint)nodeIndex) {
- entry = 0x3FFF;
- } else {
- // Process the node
- flags = getRouteFlags(pt, _nodes[idx].pt, depthSurface);
-
- int xDiff = ABS(_nodes[idx].pt.x - pt.x);
- int yDiff = ABS(_nodes[idx].pt.y - pt.y);
- hypotenuse = SqrtF16(xDiff * xDiff + yDiff * yDiff);
-
- if (hypotenuse >= 0x3FFF)
- // Shouldn't ever be this large
- hypotenuse = 0x3FFF;
-
- entry = hypotenuse | flags;
- _nodes[idx].indexes[nodeIndex] = entry;
- _nodes[nodeIndex].indexes[idx] = entry;
- }
- }
-}
-
-int MadsSceneResources::getRouteFlags(const Common::Point &src, const Common::Point &dest, M4Surface *depthSurface) {
- int result = 0x8000;
- bool flag = false;
-
- int xDiff = ABS(dest.x - src.x);
- int yDiff = ABS(dest.y - src.y);
- int xDirection = dest.x >= src.x ? 1 : -1;
- int yDirection = dest.y >= src.y ? depthSurface->width() : -depthSurface->width();
- int majorDiff = 0;
- if (dest.x < src.x)
- majorDiff = MAX(xDiff, yDiff);
- ++xDiff;
- ++yDiff;
-
- byte *srcP = depthSurface->getBasePtr(src.x, src.y);
-
- int totalCtr = majorDiff;
- for (int xCtr = 0; xCtr < xDiff; ++xCtr, srcP += xDirection) {
- totalCtr += yDiff;
-
- if ((*srcP & 0x80) == 0)
- flag = false;
- else if (!flag) {
- flag = true;
- result -= 0x4000;
- if (result == 0)
- break;
- }
-
- while (totalCtr >= xDiff) {
- totalCtr -= xDiff;
-
- if ((*srcP & 0x80) == 0)
- flag = false;
- else if (!flag) {
- flag = true;
- result -= 0x4000;
- if (result == 0)
- break;
- }
-
- srcP += yDirection;
- }
- if (result == 0)
- break;
- }
-
- return result;
-}
-
-/*--------------------------------------------------------------------------*/
-
-/*--------------------------------------------------------------------------
- * MadsInterfaceView handles the user interface section at the bottom of
- * game screens in MADS games
- *--------------------------------------------------------------------------
- */
-
-MadsInterfaceView::MadsInterfaceView(MadsM4Engine *vm): GameInterfaceView(vm,
- Common::Rect(0, MADS_SURFACE_HEIGHT, vm->_screen->width(), vm->_screen->height())) {
- _screenType = VIEWID_INTERFACE;
- _highlightedElement = -1;
- _topIndex = 0;
- _selectedObject = -1;
- _cheatKeyCtr = 0;
-
- _objectSprites = NULL;
- _objectPalData = NULL;
-
- /* Set up the rect list for screen elements */
- // Actions
- for (int i = 0; i < 10; ++i)
- _screenObjects.addRect((i / 5) * 32 + 1, (i % 5) * 8 + MADS_SURFACE_HEIGHT + 2,
- ((i / 5) + 1) * 32 + 3, ((i % 5) + 1) * 8 + MADS_SURFACE_HEIGHT + 2);
-
- // Scroller elements (up arrow, scroller, down arrow)
- _screenObjects.addRect(73, 160, 82, 167);
- _screenObjects.addRect(73, 168, 82, 190);
- _screenObjects.addRect(73, 191, 82, 198);
-
- // Inventory object names
- for (int i = 0; i < 5; ++i)
- _screenObjects.addRect(89, 158 + i * 8, 160, 166 + i * 8);
-
- // Full rectangle area for all vocab actions
- for (int i = 0; i < 5; ++i)
- _screenObjects.addRect(239, 158 + i * 8, 320, 166 + i * 8);
-}
-
-MadsInterfaceView::~MadsInterfaceView() {
- delete _objectSprites;
-}
-
-void MadsInterfaceView::setFontMode(InterfaceFontMode newMode) {
- switch (newMode) {
- case ITEM_NORMAL:
- _vm->_font->current()->setColors(4, 4, 0xff);
- break;
- case ITEM_HIGHLIGHTED:
- _vm->_font->current()->setColors(5, 5, 0xff);
- break;
- case ITEM_SELECTED:
- _vm->_font->current()->setColors(6, 6, 0xff);
- break;
- }
-}
-
-void MadsInterfaceView::initialize() {
- // Build up the inventory list
- _inventoryList.clear();
-
- for (uint i = 0; i < _madsVm->globals()->getObjectsSize(); ++i) {
- MadsObject *obj = _madsVm->globals()->getObject(i);
- if (obj->_roomNumber == PLAYER_INVENTORY)
- _inventoryList.push_back(i);
- }
-
- // If the inventory has at least one object, select it
- if (_inventoryList.size() > 0)
- setSelectedObject(_inventoryList[0]);
-}
-
-void MadsInterfaceView::setSelectedObject(int objectNumber) {
- char resName[80];
-
- // Load inventory resource
- if (_objectSprites) {
- _vm->_palette->deleteRange(_objectPalData);
- delete _objectSprites;
- }
-
- // Check to make sure the object is in the inventory, and also visible on-screen
- int idx = _inventoryList.indexOf(objectNumber);
- if (idx == -1) {
- // Object wasn't found, so return
- _selectedObject = -1;
- return;
- }
-
- // Found the object
- if (idx < _topIndex)
- _topIndex = idx;
- else if (idx >= (_topIndex + 5))
- _topIndex = MAX(0, idx - 4);
-
- _selectedObject = objectNumber;
- sprintf(resName, "*OB%.3dI.SS", objectNumber);
-
- Common::SeekableReadStream *data = _vm->res()->get(resName);
- _objectSprites = new SpriteAsset(_vm, data, data->size(), resName);
- _vm->res()->toss(resName);
-
- // Slot it into available palette space
- _objectPalData = _objectSprites->getRgbList();
- _vm->_palette->addRange(_objectPalData);
- _objectSprites->translate(_objectPalData, true);
-
- _objectFrameNumber = 0;
-}
-
-void MadsInterfaceView::addObjectToInventory(int objectNumber) {
- if (_inventoryList.indexOf(objectNumber) == -1) {
- _madsVm->globals()->getObject(objectNumber)->_roomNumber = PLAYER_INVENTORY;
- _inventoryList.push_back(objectNumber);
- }
-
- setSelectedObject(objectNumber);
-}
-
-void MadsInterfaceView::onRefresh(RectList *rects, M4Surface *destSurface) {
- _vm->_font->setFont(FONT_INTERFACE_MADS);
- char buffer[100];
-
- // Check to see if any dialog is currently active
- bool dialogVisible = _vm->_viewManager->getView(LAYER_DIALOG) != NULL;
-
- // Highlighting logic for action list
- int actionIndex = 0;
- for (int x = 0; x < 2; ++x) {
- for (int y = 0; y < 5; ++y, ++actionIndex) {
- // Determine the font color depending on whether an item is selected. Note that the first action,
- // 'Look', is always 'selected', even when another action is clicked on
- setFontMode((_highlightedElement == actionIndex) ? ITEM_HIGHLIGHTED :
- ((actionIndex == 0) ? ITEM_SELECTED : ITEM_NORMAL));
-
- // Get the verb action and capitalise it
- const char *verbStr = _madsVm->globals()->getVocab(kVerbLook + actionIndex);
- strcpy(buffer, verbStr);
- if ((buffer[0] >= 'a') && (buffer[0] <= 'z')) buffer[0] -= 'a' - 'A';
-
- // Display the verb
- const Common::Rect r(_screenObjects[actionIndex]);
- _vm->_font->current()->writeString(destSurface, buffer, r.left, r.top, r.width(), 0);
- }
- }
-
- // Check for highlighting of the scrollbar controls
- if ((_highlightedElement == SCROLL_UP) || (_highlightedElement == SCROLL_SCROLLER) || (_highlightedElement == SCROLL_DOWN)) {
- // Highlight the control's borders
- const Common::Rect r(_screenObjects[_highlightedElement]);
- destSurface->frameRect(r, 5);
- }
-
- // Draw the horizontal line in the scroller representing the current top selected
- const Common::Rect scroller(_screenObjects[SCROLL_SCROLLER]);
- int yP = (_inventoryList.size() < 2) ? 0 : (scroller.height() - 5) * _topIndex / (_inventoryList.size() - 1);
- destSurface->setColor(4);
- destSurface->hLine(scroller.left + 2, scroller.right - 3, scroller.top + 2 + yP);
-
- // List inventory items
- for (uint i = 0; i < 5; ++i) {
- if ((_topIndex + i) >= _inventoryList.size())
- break;
-
- const char *descStr = _madsVm->globals()->getVocab(_madsVm->globals()->getObject(
- _inventoryList[_topIndex + i])->_descId);
- strcpy(buffer, descStr);
- if ((buffer[0] >= 'a') && (buffer[0] <= 'z')) buffer[0] -= 'a' - 'A';
-
- const Common::Rect r(_screenObjects[INVLIST_START + i]);
-
- // Set the highlighting of the inventory item
- if (_highlightedElement == (int)(INVLIST_START + i)) setFontMode(ITEM_HIGHLIGHTED);
- else if (_selectedObject == _inventoryList[_topIndex + i]) setFontMode(ITEM_SELECTED);
- else setFontMode(ITEM_NORMAL);
-
- // Write out it's description
- _vm->_font->current()->writeString(destSurface, buffer, r.left, r.top, r.width(), 0);
- }
-
- // Handle the display of any currently selected object
- if (_objectSprites) {
- // Display object sprite. Note that the frame number isn't used directly, because it would result
- // in too fast an animation
- M4Sprite *spr = _objectSprites->getFrame(_objectFrameNumber / INV_ANIM_FRAME_SPEED);
- spr->copyTo(destSurface, INVENTORY_X, INVENTORY_Y, TRANSPARENT_COLOR_INDEX);
-
- if (!_madsVm->globals()->_config.invObjectsStill && !dialogVisible) {
- // If objects need to be animated, move to the next frame
- if (++_objectFrameNumber >= (_objectSprites->getCount() * INV_ANIM_FRAME_SPEED))
- _objectFrameNumber = 0;
- }
-
- // List the vocab actions for the currently selected object
- MadsObject *obj = _madsVm->globals()->getObject(_selectedObject);
- int yIndex = MIN(_highlightedElement - VOCAB_START, obj->_vocabCount - 1);
-
- for (int i = 0; i < obj->_vocabCount; ++i) {
- const Common::Rect r(_screenObjects[VOCAB_START + i]);
-
- // Get the vocab description and capitalise it
- const char *descStr = _madsVm->globals()->getVocab(obj->_vocabList[i].vocabId);
- strcpy(buffer, descStr);
- if ((buffer[0] >= 'a') && (buffer[0] <= 'z')) buffer[0] -= 'a' - 'A';
-
- // Set the highlighting and display the entry
- setFontMode((i == yIndex) ? ITEM_HIGHLIGHTED : ITEM_NORMAL);
- _vm->_font->current()->writeString(destSurface, buffer, r.left, r.top, r.width(), 0);
- }
- }
-}
-
-bool MadsInterfaceView::onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents) {
- MadsAction &act = _madsVm->scene()->_action;
-
- // If the mouse isn't being held down, then reset the repeated scroll timer
- if (eventType != MEVENT_LEFT_HOLD)
- _nextScrollerTicks = 0;
-
- // Handle various event types
- switch (eventType) {
- case MEVENT_MOVE:
- // If the cursor isn't in "wait mode", don't do any processing
- if (_vm->_mouse->getCursorNum() == CURSOR_WAIT)
- return true;
-
- // Ensure the cursor is the standard arrow
- _vm->_mouse->setCursorNum(CURSOR_ARROW);
-
- // Check if any interface element is currently highlighted
- _highlightedElement = _screenObjects.find(Common::Point(x, y));
-
- return true;
-
- case MEVENT_LEFT_CLICK:
- // Left mouse click
- {
- // Check if an inventory object was selected
- if ((_highlightedElement >= INVLIST_START) && (_highlightedElement < (INVLIST_START + 5))) {
- // Ensure there is an inventory item listed in that cell
- uint idx = _highlightedElement - INVLIST_START;
- if ((_topIndex + idx) < _inventoryList.size()) {
- // Set the selected object
- setSelectedObject(_inventoryList[_topIndex + idx]);
- }
- } else if ((_highlightedElement >= ACTIONS_START) && (_highlightedElement < (ACTIONS_START + 10))) {
- // A standard action was selected
- int verbId = kVerbLook + (_highlightedElement - ACTIONS_START);
- warning("Selected action #%d", verbId);
-
- } else if ((_highlightedElement >= VOCAB_START) && (_highlightedElement < (VOCAB_START + 5))) {
- // A vocab action was selected
- MadsObject *obj = _madsVm->globals()->getObject(_selectedObject);
- int vocabIndex = MIN(_highlightedElement - VOCAB_START, obj->_vocabCount - 1);
- if (vocabIndex >= 0) {
- act._actionMode = ACTMODE_OBJECT;
- act._actionMode2 = ACTMODE2_2;
- act._flags1 = obj->_vocabList[1].flags1;
- act._flags2 = obj->_vocabList[1].flags2;
-
- act._action.verbId = _selectedObject;
- act._articleNumber = act._flags2;
- }
- }
- }
- return true;
-
- case MEVENT_LEFT_HOLD:
- // Left mouse hold
- // Handle the scroller - the up/down buttons allow for multiple actions whilst the mouse is held down
- if ((_highlightedElement == SCROLL_UP) || (_highlightedElement == SCROLL_DOWN)) {
- if ((_nextScrollerTicks == 0) || (g_system->getMillis() >= _nextScrollerTicks)) {
- // Handle scroll up/down action
- _nextScrollerTicks = g_system->getMillis() + SCROLLER_DELAY;
-
- if ((_highlightedElement == SCROLL_UP) && (_topIndex > 0))
- --_topIndex;
- if ((_highlightedElement == SCROLL_DOWN) && (_topIndex < (int)(_inventoryList.size() - 1)))
- ++_topIndex;
- }
- }
- return true;
-
- case MEVENT_LEFT_DRAG:
- // Left mouse drag
- // Handle the the the scroller area that can be dragged to adjust the top displayed index
- if (_highlightedElement == SCROLL_SCROLLER) {
- // Calculate the new top index based on the Y position
- const Common::Rect r(_screenObjects[SCROLL_SCROLLER]);
- _topIndex = CLIP((int)(_inventoryList.size() - 1) * (y - r.top - 2) / (r.height() - 5),
- 0, (int)_inventoryList.size() - 1);
- }
- return true;
-
- case KEVENT_KEY:
- if (_cheatKeyCtr == CHEAT_SEQUENCE_MAX)
- handleCheatKey(param1);
- handleKeypress(param1);
- return true;
-
- default:
- break;
- }
-
- return false;
-}
-
-bool MadsInterfaceView::handleCheatKey(int32 keycode) {
- switch (keycode) {
- case Common::KEYCODE_SPACE:
- // TODO: Move player to current destination
- return true;
-
- case Common::KEYCODE_c | (Common::KBD_CTRL << 24):
- // Toggle display of mouse position
- _madsVm->scene()->_showMousePos = !_madsVm->scene()->_showMousePos;
- break;
-
- case Common::KEYCODE_t | (Common::KBD_ALT << 24): {
- // Teleport to room
- //Scene *sceneView = (Scene *)vm->_viewManager->getView(VIEWID_SCENE);
- // TODO: Implement teleport code
-
- return true;
- }
-
- default:
- break;
- }
-
- return false;
-}
-
-const char *CHEAT_SEQUENCE = "widepipe";
-
-bool MadsInterfaceView::handleKeypress(int32 keycode) {
- int flags = keycode >> 24;
- int kc = keycode & 0xffff;
-
- // Capitalise the letter if necessary
- if (_cheatKeyCtr < CHEAT_SEQUENCE_MAX) {
- if ((flags & Common::KBD_CTRL) && (kc == CHEAT_SEQUENCE[_cheatKeyCtr])) {
- ++_cheatKeyCtr;
- if (_cheatKeyCtr == CHEAT_SEQUENCE_MAX)
- Dialog::display(_vm, 22, cheatingEnabledDesc);
- return true;
- } else {
- _cheatKeyCtr = 0;
- }
- }
-
- // Handle the various keys
- if ((keycode == Common::KEYCODE_ESCAPE) || (keycode == Common::KEYCODE_F1)) {
- // Game menu
- _madsVm->globals()->dialogType = DIALOG_GAME_MENU;
- leaveScene();
- return false;
- } else if (flags & Common::KBD_CTRL) {
- // Handling of the different control key combinations
- switch (kc) {
- case Common::KEYCODE_i:
- // Mouse to inventory
- warning("TODO: Mouse to inventory");
- break;
-
- case Common::KEYCODE_k:
- // Toggle hotspots
- warning("TODO: Toggle hotspots");
- break;
-
- case Common::KEYCODE_p:
- // Player stats
- warning("TODO: Player stats");
- break;
-
- case Common::KEYCODE_q:
- // Quit game
- break;
-
- case Common::KEYCODE_s:
- // Activate sound
- warning("TODO: Activate sound");
- break;
-
- case Common::KEYCODE_t:
- // Rotate player - This was Ctrl-U in the original, but in ScummVM Ctrl-U is a global mute key
- _madsVm->_player._newDirection = _madsVm->_player._directionListIndexes[_madsVm->_player._newDirection + 10];
- break;
-
- case Common::KEYCODE_v: {
- // Release version
- Dialog *dlg = new Dialog(_vm, GameReleaseInfoStr, GameReleaseTitleStr);
- _vm->_viewManager->addView(dlg);
- _vm->_viewManager->moveToFront(dlg);
- return false;
- }
-
- default:
- break;
- }
- } else if ((flags & Common::KBD_ALT) && (kc == Common::KEYCODE_q)) {
- // Quit Game
-
- } else {
- // Standard keypresses
- switch (kc) {
- case Common::KEYCODE_F2:
- // Save game
- _madsVm->globals()->dialogType = DIALOG_SAVE;
- leaveScene();
- break;
- case Common::KEYCODE_F3:
- // Restore game
- _madsVm->globals()->dialogType = DIALOG_RESTORE;
- leaveScene();
- break;
- }
- }
-//DIALOG_OPTIONS
- return false;
-}
-
-void MadsInterfaceView::leaveScene() {
- // Close the scene
- View *view = _madsVm->_viewManager->getView(VIEWID_SCENE);
- _madsVm->_viewManager->deleteView(view);
-}
-
-//--------------------------------------------------------------------------
-
-int getActiveAnimationBool() {
- return (_madsVm->scene()->activeAnimation()) ? 1 : 0;
-}
-
-int getAnimationCurrentFrame() {
- Animation *anim = _madsVm->scene()->activeAnimation();
- return anim ? anim->getCurrentFrame() : 0;
-}
-
-
-} // End of namespace M4